Mon Mar 20 08:25:39 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

chan_misdn_config.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  * 
00004  * Copyright (C) 2005, Christian Richter
00005  *
00006  * Christian Richter <crich@beronet.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  *
00018  */
00019 
00020 /*!
00021  * \file
00022  *
00023  * \brief chan_misdn configuration management
00024  * \author Christian Richter <crich@beronet.com>
00025  *
00026  * \ingroup channel_drivers
00027  */
00028 
00029 
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033 
00034 #include "chan_misdn_config.h"
00035 
00036 #include <asterisk/config.h>
00037 #include <asterisk/channel.h>
00038 #include <asterisk/logger.h>
00039 #include <asterisk/lock.h>
00040 #include <asterisk/strings.h>
00041 
00042 #include <asterisk/utils.h>
00043 #define AST_LOAD_CFG ast_config_load
00044 #define AST_DESTROY_CFG ast_config_destroy
00045 
00046 #define DEF_ECHOCANCEL 128
00047 #define DEF_ECHOTRAINING 1
00048 
00049 struct msn_list {
00050    char *msn;
00051    struct msn_list *next;
00052 };
00053 
00054 struct port_config {
00055    char *name;
00056    int *rxgain;
00057    int *txgain;
00058    int *te_choose_channel;
00059    char *context;
00060    char *language;
00061    char *callerid;
00062    char *method;
00063    int *dialplan;
00064    int *localdialplan; 
00065    char *nationalprefix;
00066    char *internationalprefix;
00067    int *pres;
00068    int *always_immediate;
00069    int *immediate;
00070    int *hold_allowed;
00071    int *early_bconnect;
00072    int *use_callingpres;
00073    int *echocancel;
00074    int *echocancelwhenbridged;
00075    int *echotraining;
00076    struct msn_list *msn_list;
00077    ast_group_t *callgroup;    /* Call group */
00078    ast_group_t *pickupgroup;  /* Pickup group */
00079 };
00080 
00081 struct general_config {
00082    int *debug;
00083    char *tracefile;
00084    int *trace_calls;
00085    char *trace_dir;
00086    int *bridging;
00087    int *stop_tone_after_first_digit;
00088    int *append_digits2exten;
00089    int *l1_info_ok;
00090    int *clear_l3;
00091    int *dynamic_crypt;
00092    char *crypt_prefix;
00093    char *crypt_keys;
00094 };
00095 
00096 /* array of port configs, default is at position 0. */
00097 static struct port_config **port_cfg;
00098 /* max number of available ports, is set on init */
00099 static int max_ports;
00100 /* general config */
00101 static struct general_config *general_cfg;
00102 /* storing the ptp flag separated to save memory */
00103 static int *ptp;
00104 
00105 static ast_mutex_t config_mutex; 
00106 
00107 
00108 static inline void misdn_cfg_lock (void) {
00109    ast_mutex_lock(&config_mutex);
00110 }
00111 
00112 static inline void misdn_cfg_unlock (void) {
00113    ast_mutex_unlock(&config_mutex);
00114 }
00115 
00116 static void free_msn_list (struct msn_list* iter) {
00117    if (iter->next)
00118       free_msn_list(iter->next);
00119    if (iter->msn)
00120       free(iter->msn);
00121    free(iter);
00122 }
00123 
00124 static void free_port_cfg (void) {
00125 
00126    struct port_config **free_list = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
00127 
00128    int i, j;
00129 
00130    for (i = 0; i < max_ports; i++) {
00131       if (port_cfg[i]) {
00132          for (j = 0; j < max_ports && free_list[j]; j++) {
00133             if (free_list[j] && free_list[j] == port_cfg[i])
00134                continue; /* already in list */
00135             free_list[j] = port_cfg[i];
00136          }
00137       }
00138    }
00139 
00140 #define FREE_ELEM(elem) ({ \
00141       if (free_list[i]->elem) \
00142          free(free_list[i]->elem); \
00143    })
00144    
00145    for (i = 0; i < max_ports; i++) {
00146       if (free_list[i]) {
00147          FREE_ELEM(name);
00148          FREE_ELEM(rxgain);
00149          FREE_ELEM(txgain);
00150          FREE_ELEM(te_choose_channel);
00151          FREE_ELEM(context);
00152          FREE_ELEM(language);
00153          FREE_ELEM(callerid);
00154          FREE_ELEM(method);
00155          FREE_ELEM(dialplan);
00156          FREE_ELEM(localdialplan);
00157          FREE_ELEM(nationalprefix);
00158          FREE_ELEM(internationalprefix);
00159          FREE_ELEM(pres);
00160          FREE_ELEM(always_immediate);
00161          FREE_ELEM(immediate);
00162          FREE_ELEM(hold_allowed);
00163          FREE_ELEM(early_bconnect);
00164          FREE_ELEM(use_callingpres);
00165          FREE_ELEM(echocancel);
00166          FREE_ELEM(echocancelwhenbridged);
00167          FREE_ELEM(echotraining);
00168          if (free_list[i]->msn_list)
00169             free_msn_list(free_list[i]->msn_list);
00170          FREE_ELEM(callgroup);
00171          FREE_ELEM(pickupgroup);
00172          free(free_list[i]);
00173       }
00174    }
00175    free(free_list);
00176 }
00177 
00178 static void free_general_cfg (void) {
00179 
00180 #define FREE_GEN_ELEM(elem) ({ \
00181       if (general_cfg->elem) \
00182          free(general_cfg->elem); \
00183    })
00184    
00185    FREE_GEN_ELEM(debug);
00186    FREE_GEN_ELEM(tracefile);
00187    FREE_GEN_ELEM(trace_calls);
00188    FREE_GEN_ELEM(trace_dir);
00189    FREE_GEN_ELEM(bridging);
00190    FREE_GEN_ELEM(stop_tone_after_first_digit);
00191    FREE_GEN_ELEM(append_digits2exten);
00192    FREE_GEN_ELEM(l1_info_ok);
00193    FREE_GEN_ELEM(clear_l3);
00194    FREE_GEN_ELEM(dynamic_crypt);
00195    FREE_GEN_ELEM(crypt_prefix);
00196    FREE_GEN_ELEM(crypt_keys);
00197 }
00198 
00199 #define GET_PORTCFG_STRCPY(item) ({ \
00200       char *temp; \
00201       if (port_cfg[port] && port_cfg[port]->item) \
00202          temp = port_cfg[port]->item; \
00203       else \
00204          temp = port_cfg[0]->item; \
00205       if (!temp || !memccpy((void *)buf, (void *)temp, '\0', bufsize)) \
00206          memset(buf, 0, 1); \
00207    })
00208 
00209 #define GET_GENCFG_STRCPY(item) ({ \
00210       if (general_cfg && general_cfg->item) { \
00211          if (!memccpy((void *)buf, (void *)general_cfg->item, '\0', bufsize)) \
00212             memset(buf, 0, 1); \
00213       } else \
00214          memset(buf, 0, 1); \
00215    })
00216 
00217 #define GET_PORTCFG_MEMCPY(item) ({ \
00218       typeof(port_cfg[0]->item) temp; \
00219       if (port_cfg[port] && port_cfg[port]->item) \
00220          temp = port_cfg[port]->item; \
00221       else \
00222          temp = port_cfg[0]->item; \
00223       if (temp) { \
00224          int l = sizeof(*temp); \
00225          if (l > bufsize) \
00226             memset(buf, 0, bufsize); \
00227          else \
00228             memcpy(buf, temp, l); \
00229       } else \
00230          memset(buf, 0, bufsize); \
00231    })
00232 
00233 #define GET_GENCFG_MEMCPY(item) ({ \
00234       if (general_cfg && general_cfg->item) { \
00235          typeof(general_cfg->item) temp = general_cfg->item; \
00236          int l = sizeof(*temp); \
00237          if (l > bufsize) \
00238             memset(buf, 0, bufsize); \
00239          else \
00240             memcpy(buf, temp, l); \
00241       } else \
00242          memset(buf, 0, bufsize); \
00243    })
00244 
00245 void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize) {
00246    
00247    if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
00248       memset(buf, 0, bufsize);
00249       ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
00250       return;
00251    }
00252 
00253    misdn_cfg_lock();
00254    
00255    switch (elem) {
00256       
00257       /* port config elements */
00258          
00259       case MISDN_CFG_PTP:     if (sizeof(ptp[port]) <= bufsize)
00260                      memcpy(buf, &ptp[port], sizeof(ptp[port]));
00261                   else
00262                      buf = 0; /* error, should not happen */
00263                   break;
00264       case MISDN_CFG_GROUPNAME:  GET_PORTCFG_STRCPY(name);
00265                   break;
00266       case MISDN_CFG_RXGAIN:     GET_PORTCFG_MEMCPY(rxgain);
00267                   break;
00268       case MISDN_CFG_TXGAIN:     GET_PORTCFG_MEMCPY(txgain);
00269                   break;
00270       case MISDN_CFG_TE_CHOOSE_CHANNEL:
00271                   GET_PORTCFG_MEMCPY(te_choose_channel);
00272                   break;
00273       case MISDN_CFG_CONTEXT:    GET_PORTCFG_STRCPY(context);
00274                   break;
00275       case MISDN_CFG_LANGUAGE:   GET_PORTCFG_STRCPY(language);
00276                   break;
00277       case MISDN_CFG_CALLERID:   GET_PORTCFG_STRCPY(callerid);
00278                   break;
00279       case MISDN_CFG_METHOD:     GET_PORTCFG_STRCPY(method);
00280                   break;
00281       case MISDN_CFG_DIALPLAN:   GET_PORTCFG_MEMCPY(dialplan);
00282                   break;
00283    case MISDN_CFG_LOCALDIALPLAN: GET_PORTCFG_MEMCPY(localdialplan);
00284       break;
00285       case MISDN_CFG_NATPREFIX:  GET_PORTCFG_STRCPY(nationalprefix);
00286                   break;
00287       case MISDN_CFG_INTERNATPREFIX:
00288                   GET_PORTCFG_STRCPY(internationalprefix);
00289                   break;
00290       case MISDN_CFG_PRES:    GET_PORTCFG_MEMCPY(pres);
00291                   break;
00292       case MISDN_CFG_ALWAYS_IMMEDIATE:
00293                   GET_PORTCFG_MEMCPY(always_immediate);
00294                   break;
00295       case MISDN_CFG_IMMEDIATE:  GET_PORTCFG_MEMCPY(immediate);
00296                   break;
00297       case MISDN_CFG_HOLD_ALLOWED:
00298                   GET_PORTCFG_MEMCPY(hold_allowed);
00299                   break;
00300       case MISDN_CFG_EARLY_BCONNECT:
00301                   GET_PORTCFG_MEMCPY(early_bconnect);
00302                   break;
00303       case MISDN_CFG_USE_CALLINGPRES:
00304                   GET_PORTCFG_MEMCPY(use_callingpres);
00305                   break;
00306       case MISDN_CFG_ECHOCANCEL:
00307                   GET_PORTCFG_MEMCPY(echocancel );
00308                   break;
00309       case MISDN_CFG_ECHOCANCELWHENBRIDGED:
00310                   GET_PORTCFG_MEMCPY(echocancelwhenbridged);
00311                   break;
00312       case MISDN_CFG_ECHOTRAINING:
00313                   GET_PORTCFG_MEMCPY(echotraining);
00314                   break;
00315       case MISDN_CFG_CALLGROUP:  GET_PORTCFG_MEMCPY(callgroup);
00316                   break;
00317       case MISDN_CFG_PICKUPGROUP:   GET_PORTCFG_MEMCPY(pickupgroup);
00318                   break;
00319       
00320       /* general config elements */
00321          
00322       case MISDN_GEN_DEBUG:      GET_GENCFG_MEMCPY(debug);
00323                   break;
00324       case MISDN_GEN_TRACEFILE:  GET_GENCFG_STRCPY(tracefile);
00325                   break;
00326       case MISDN_GEN_TRACE_CALLS: GET_GENCFG_MEMCPY(trace_calls);
00327                   break;
00328       case MISDN_GEN_TRACE_DIR:  GET_GENCFG_STRCPY(trace_dir);
00329                   break;
00330       case MISDN_GEN_BRIDGING:   GET_GENCFG_MEMCPY(bridging);
00331                   break;
00332       case MISDN_GEN_STOP_TONE:  GET_GENCFG_MEMCPY(stop_tone_after_first_digit);
00333                   break;
00334       case MISDN_GEN_APPEND_DIGITS2EXTEN: 
00335                   GET_GENCFG_MEMCPY(append_digits2exten);
00336                   break;
00337       case MISDN_GEN_L1_INFO_OK: GET_GENCFG_MEMCPY(l1_info_ok);
00338                   break;
00339       case MISDN_GEN_CLEAR_L3:   GET_GENCFG_MEMCPY(clear_l3);
00340                   break;
00341       case MISDN_GEN_DYNAMIC_CRYPT: GET_GENCFG_MEMCPY(dynamic_crypt);
00342                   break;
00343       case MISDN_GEN_CRYPT_PREFIX:  GET_GENCFG_STRCPY(crypt_prefix);
00344                   break;
00345       case MISDN_GEN_CRYPT_KEYS:    GET_GENCFG_STRCPY(crypt_keys);
00346                   break;
00347       default:       memset(buf, 0, bufsize);
00348    }
00349    
00350    misdn_cfg_unlock();
00351 }
00352 
00353 int misdn_cfg_is_msn_valid (int port, char* msn) {
00354    
00355    if (!misdn_cfg_is_port_valid(port)) {
00356       ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
00357       return 0;
00358    }
00359    
00360    struct msn_list *iter;
00361    
00362    misdn_cfg_lock();
00363    
00364    if (port_cfg[port]->msn_list)
00365       iter = port_cfg[port]->msn_list;
00366    else
00367       iter = port_cfg[0]->msn_list;
00368    for (; iter; iter = iter->next) 
00369       if (*(iter->msn) == '*' || !strcasecmp(iter->msn, msn)) {
00370          misdn_cfg_unlock();
00371          return 1;
00372       }
00373    
00374    misdn_cfg_unlock();
00375    
00376    return 0;
00377 }
00378 
00379 int misdn_cfg_is_port_valid (int port) {
00380    
00381    misdn_cfg_lock();
00382    
00383    if (port < 1 || port > max_ports) {
00384       misdn_cfg_unlock();
00385       return 0;
00386    }
00387 
00388    int valid = (port_cfg[port] != NULL);
00389 
00390    misdn_cfg_unlock();
00391 
00392    return valid;
00393 }
00394 
00395 int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth) {
00396 
00397    int i, re = 0;
00398    char *method = NULL;
00399 
00400    misdn_cfg_lock();
00401    
00402    for (i = 0; i < max_ports; i++) {
00403       if (port_cfg[i]) {
00404          if (!strcasecmp(port_cfg[i]->name, group))
00405             method = port_cfg[i]->method ? port_cfg[i]->method : port_cfg[0]->method;
00406       }
00407    }
00408 
00409    if (method) {
00410       switch (meth) {
00411       case METHOD_STANDARD:      re = !strcasecmp(method, "standard");
00412                            break;
00413       case METHOD_ROUND_ROBIN:   re = !strcasecmp(method, "round_robin");
00414                            break;
00415       }
00416    }
00417 
00418    misdn_cfg_unlock();
00419 
00420    return re;
00421 }
00422 
00423 void misdn_cfg_get_ports_string (char *ports) {
00424    *ports = 0;
00425    char tmp[16];
00426    int l;
00427    
00428    misdn_cfg_lock();
00429 
00430    int i = 1;
00431    for (; i <= max_ports; i++) {
00432       if (port_cfg[i]) {
00433          if (ptp[i])
00434             sprintf(tmp, "%dptp,", i);
00435          else
00436             sprintf(tmp, "%d,", i);
00437          strcat(ports, tmp);
00438       }
00439    }
00440    
00441    misdn_cfg_unlock();
00442 
00443    if ((l = strlen(ports)))
00444       ports[l-1] = 0;
00445 }
00446 
00447 #define GET_CFG_STRING(typestr, type) ({ \
00448       if (port_cfg[port] && port_cfg[port]->type) \
00449          snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[port]->type); \
00450       else \
00451          snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[0]->type); \
00452    }) \
00453 
00454 #define GET_GEN_STRING(typestr, type) ({ \
00455       snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? general_cfg->type : "not set"); \
00456    }) \
00457 
00458 #define GET_CFG_INT(typestr, type) ({ \
00459       if (port_cfg[port] && port_cfg[port]->type) \
00460          snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[port]->type); \
00461       else \
00462          snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[0]->type); \
00463    }) \
00464 
00465 #define GET_GEN_INT(typestr, type) ({ \
00466       snprintf(buf, bufsize, "%s " #typestr ": %d", begin, general_cfg->type ? *general_cfg->type : 0); \
00467    }) \
00468 
00469 #define GET_CFG_BOOL(typestr, type, yes, no) ({ \
00470       int bool; \
00471       if (port_cfg[port] && port_cfg[port]->type) \
00472          bool = *port_cfg[port]->type; \
00473       else \
00474          bool = *port_cfg[0]->type; \
00475       snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
00476    }) \
00477 
00478 #define GET_CFG_HYBRID(typestr, type, yes, no) ({ \
00479       int bool; \
00480       if (port_cfg[port] && port_cfg[port]->type) \
00481          bool = *port_cfg[port]->type; \
00482       else \
00483          bool = *port_cfg[0]->type; \
00484       if (bool == 1 || bool == 0) \
00485          snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
00486       else \
00487          snprintf(buf, bufsize, "%s " #typestr ": %d", begin, bool); \
00488    }) \
00489 
00490 #define GET_GEN_BOOL(typestr, type, yes, no) ({ \
00491       snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? (*general_cfg->type ? #yes : #no) : "not set"); \
00492    }) \
00493 
00494 #define GET_CFG_AST_GROUP_T(typestr, type) ({ \
00495       ast_group_t *tmp; \
00496       if (port_cfg[port] && port_cfg[port]->type) \
00497          tmp = port_cfg[port]->type; \
00498       else \
00499          tmp = port_cfg[0]->type; \
00500       if (tmp) { \
00501          char tmpbuf[256]; \
00502          snprintf(buf, bufsize, "%s " #typestr ": %s", begin, ast_print_group(tmpbuf, sizeof(tmpbuf), *tmp)); \
00503       } else \
00504          snprintf(buf, bufsize, "%s " #typestr ": %s", begin, "none"); \
00505    }) \
00506 
00507 void misdn_cfg_get_config_string(int port, enum misdn_cfg_elements elem, char* buf, int bufsize) {
00508 
00509    if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
00510       *buf = 0;
00511       ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
00512       return;
00513    }
00514    
00515    char begin[] = " -> ";
00516    
00517    misdn_cfg_lock();
00518    
00519    switch (elem) {
00520       
00521       case MISDN_CFG_PTP:     snprintf(buf, bufsize, "%s PTP: %s", begin, ptp[port] ? "yes" : "no");
00522                            break;
00523       case MISDN_CFG_GROUPNAME:  GET_CFG_STRING(GROUPNAME, name);
00524                            break;
00525       case MISDN_CFG_RXGAIN:     GET_CFG_INT(RXGAIN, rxgain);
00526                            break;
00527       case MISDN_CFG_TXGAIN:     GET_CFG_INT(TXGAIN, txgain);
00528                            break;
00529       case MISDN_CFG_TE_CHOOSE_CHANNEL:
00530                   GET_CFG_BOOL(TE_CHOOSE_CHANNEL, te_choose_channel, yes, no);
00531                            break;
00532       case MISDN_CFG_CONTEXT:    GET_CFG_STRING(CONTEXT, context);
00533                            break;
00534       case MISDN_CFG_LANGUAGE:   GET_CFG_STRING(LANGUAGE, language);
00535                            break;
00536       case MISDN_CFG_CALLERID:   GET_CFG_STRING(CALLERID, callerid);
00537                            break;
00538       case MISDN_CFG_METHOD:     GET_CFG_STRING(METHOD, method);
00539                            break;
00540       case MISDN_CFG_DIALPLAN:   GET_CFG_INT(DIALPLAN, dialplan);
00541                            break;
00542    case MISDN_CFG_LOCALDIALPLAN: GET_CFG_INT(LOCALDIALPLAN, localdialplan);
00543       break;
00544       case MISDN_CFG_NATPREFIX:  GET_CFG_STRING(NATIONALPREFIX, nationalprefix);
00545                            break;
00546       case MISDN_CFG_INTERNATPREFIX:
00547                   GET_CFG_STRING(INTERNATIONALPREFIX, internationalprefix);
00548                            break;
00549       case MISDN_CFG_PRES:    GET_CFG_BOOL(PRESENTATION, pres, allowed, not_screened);
00550                            break;
00551       case MISDN_CFG_ALWAYS_IMMEDIATE:
00552                   GET_CFG_BOOL(ALWAYS_IMMEDIATE, always_immediate, yes, no);
00553                            break;
00554       case MISDN_CFG_IMMEDIATE:  GET_CFG_BOOL(IMMEDIATE, immediate, yes, no);
00555                            break;
00556       case MISDN_CFG_HOLD_ALLOWED:
00557                   GET_CFG_BOOL(HOLD_ALLOWED, hold_allowed, yes, no);
00558                            break;
00559       case MISDN_CFG_EARLY_BCONNECT:
00560                   GET_CFG_BOOL(EARLY_BCONNECT, early_bconnect, yes, no);
00561                            break;
00562       case MISDN_CFG_USE_CALLINGPRES:
00563                   GET_CFG_BOOL(USE_CALLINGPRES, use_callingpres, yes, no);
00564                            break;
00565       case MISDN_CFG_ECHOCANCEL: GET_CFG_HYBRID(ECHOCANCEL, echocancel, yes, no);
00566                            break;
00567       case MISDN_CFG_ECHOCANCELWHENBRIDGED:
00568                   GET_CFG_BOOL(ECHOCANCELWHENBRIDGED, echocancelwhenbridged, yes, no);
00569                            break;
00570       case MISDN_CFG_ECHOTRAINING:
00571                   GET_CFG_HYBRID(ECHOTRAINING, echotraining, yes, no);
00572                            break;
00573       case MISDN_CFG_CALLGROUP:  GET_CFG_AST_GROUP_T(CALLINGGROUP, callgroup);
00574                            break;
00575       case MISDN_CFG_PICKUPGROUP:   GET_CFG_AST_GROUP_T(PICKUPGROUP, pickupgroup);
00576                            break;
00577       case MISDN_CFG_MSNS:    {
00578                      char tmpbuffer[BUFFERSIZE];
00579                      tmpbuffer[0] = 0;
00580                      struct msn_list *iter;
00581                      if (port_cfg[port]->msn_list)
00582                         iter = port_cfg[port]->msn_list;
00583                      else
00584                         iter = port_cfg[0]->msn_list;
00585                      if (iter) {
00586                         for (; iter; iter = iter->next)
00587                            sprintf(tmpbuffer, "%s%s, ", tmpbuffer, iter->msn);
00588                         tmpbuffer[strlen(tmpbuffer)-2] = 0;
00589                      }
00590                      snprintf(buf, bufsize, "%s MSNs: %s", begin, *tmpbuffer ? tmpbuffer : "none"); \
00591                   }
00592                   break;
00593       
00594       /* general config elements */
00595       
00596       case MISDN_GEN_DEBUG:      GET_GEN_INT(DEBUG_LEVEL, debug);
00597                            break;
00598       case MISDN_GEN_TRACEFILE:  GET_GEN_STRING(TRACEFILE, tracefile);
00599                            break;
00600       case MISDN_GEN_TRACE_CALLS: GET_GEN_BOOL(TRACE_CALLS, trace_calls, true, false);
00601                            break;
00602       case MISDN_GEN_TRACE_DIR:  GET_GEN_STRING(TRACE_DIR, trace_dir);
00603                            break;
00604       case MISDN_GEN_BRIDGING:   GET_GEN_BOOL(BRIDGING, bridging, yes, no);
00605                            break;
00606       case MISDN_GEN_STOP_TONE:  GET_GEN_BOOL(STOP_TONE_AFTER_FIRST_DIGIT, stop_tone_after_first_digit, yes, no);
00607                            break;
00608       case MISDN_GEN_APPEND_DIGITS2EXTEN: 
00609                   GET_GEN_BOOL(APPEND_DIGITS2EXTEN, append_digits2exten, yes, no);
00610                            break;
00611       case MISDN_GEN_L1_INFO_OK: GET_GEN_BOOL(L1_INFO_OK, l1_info_ok, yes, no);
00612                            break;
00613       case MISDN_GEN_CLEAR_L3:   GET_GEN_BOOL(CLEAR_L3, clear_l3, yes, no);
00614                            break;
00615       case MISDN_GEN_DYNAMIC_CRYPT:
00616                   GET_GEN_BOOL(DYNAMIC_CRYPT,dynamic_crypt, yes, no);
00617                            break;
00618       case MISDN_GEN_CRYPT_PREFIX:
00619                   GET_GEN_STRING(CRYPT_PREFIX, crypt_prefix);
00620                            break;
00621       case MISDN_GEN_CRYPT_KEYS: GET_GEN_STRING(CRYPT_KEYS, crypt_keys);
00622                            break;
00623                            
00624       default:       *buf = 0;
00625                            break;
00626    }
00627 
00628    misdn_cfg_unlock();
00629 }
00630 
00631 int misdn_cfg_get_next_port (int port) {
00632    
00633    misdn_cfg_lock();
00634    
00635    for (port++; port <= max_ports; port++) {
00636       if (port_cfg[port]) {
00637          misdn_cfg_unlock();
00638          return port;
00639       }
00640    }
00641    
00642    misdn_cfg_unlock();
00643    
00644    return -1;
00645 }
00646 
00647 int misdn_cfg_get_next_port_spin (int port) {
00648 
00649    int ret = misdn_cfg_get_next_port(port);
00650 
00651    if (ret > 0)
00652       return ret;
00653 
00654    return misdn_cfg_get_next_port(0);
00655 }
00656 
00657 #define PARSE_GEN_INT(item) ({ \
00658       if (!strcasecmp(v->name, #item)) { \
00659          int temp; \
00660          if (!sscanf(v->value, "%d", &temp)) { \
00661             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); \
00662          } else { \
00663             general_cfg->item = (int *)malloc(sizeof(int)); \
00664             memcpy(general_cfg->item, &temp, sizeof(int)); \
00665          } \
00666          continue; \
00667       } \
00668    }) \
00669 
00670 #define PARSE_GEN_BOOL(item) ({ \
00671       if (!strcasecmp(v->name, #item)) { \
00672          general_cfg->item = (int *)malloc(sizeof(int)); \
00673          *(general_cfg->item) = ast_true(v->value)?1:0; \
00674          continue; \
00675       } \
00676    })
00677 
00678 #define PARSE_GEN_STR(item) ({ \
00679       if (!strcasecmp(v->name, #item)) { \
00680          int l = strlen(v->value); \
00681          if (l) { \
00682             general_cfg->item = (char *)calloc(l+1, sizeof(char)); \
00683             strncpy(general_cfg->item,v->value, l); \
00684          } \
00685          continue; \
00686       } \
00687    })
00688 
00689 static void build_general_config(struct ast_variable *v) {
00690 
00691    if (!v) 
00692       return;
00693 
00694    for (; v; v = v->next) {
00695 
00696       PARSE_GEN_INT(debug);
00697       PARSE_GEN_STR(tracefile);
00698       PARSE_GEN_BOOL(trace_calls);
00699       PARSE_GEN_STR(trace_dir);
00700       PARSE_GEN_BOOL(bridging);
00701       PARSE_GEN_BOOL(stop_tone_after_first_digit);
00702       PARSE_GEN_BOOL(append_digits2exten);
00703       PARSE_GEN_BOOL(l1_info_ok);
00704       PARSE_GEN_BOOL(clear_l3);
00705       PARSE_GEN_BOOL(dynamic_crypt);
00706       PARSE_GEN_STR(crypt_prefix);
00707       PARSE_GEN_STR(crypt_keys);
00708       
00709    }
00710 }
00711 
00712 #define PARSE_CFG_HYBRID(item, def) ({ \
00713       if (!strcasecmp(v->name, #item)) { \
00714          new->item = (int *)malloc(sizeof(int)); \
00715          if (!sscanf(v->value, "%d", new->item)) { \
00716             if (ast_true(v->value)) \
00717                *new->item = def; \
00718             else \
00719                *new->item = 0; \
00720          } \
00721          continue; \
00722       } \
00723    }) \
00724 
00725 #define PARSE_CFG_INT(item) ({ \
00726       if (!strcasecmp(v->name, #item)) { \
00727          new->item = (int *)malloc(sizeof(int)); \
00728          if (!sscanf(v->value, "%d", new->item)) { \
00729             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); \
00730             free(new->item); \
00731             new->item = NULL; \
00732          } \
00733          continue; \
00734       } \
00735    }) \
00736 
00737 #define PARSE_CFG_BOOL(item) ({ \
00738       if (!strcasecmp(v->name, #item)) { \
00739          new->item = (int *)malloc(sizeof(int)); \
00740          *(new->item) = ast_true(v->value)?1:0; \
00741          continue; \
00742       } \
00743    })
00744 
00745 #define PARSE_CFG_STR(item) ({ \
00746       if (!strcasecmp(v->name, #item)) { \
00747          int l = strlen(v->value); \
00748          if (l) { \
00749             new->item = (char *)calloc(l+1, sizeof(char)); \
00750             strncpy(new->item,v->value,l); \
00751          } \
00752          continue; \
00753       } \
00754    })
00755 
00756 static void build_port_config(struct ast_variable *v, char *cat) {
00757    if (!v || !cat)
00758       return;
00759 
00760    int cfg_for_ports[max_ports + 1];
00761    int i = 0;
00762    for (; i < (max_ports + 1); i++) {
00763       cfg_for_ports[i] = 0;
00764    }
00765    
00766    /* we store the default config at position 0 */
00767    if (!strcasecmp(cat, "default")) {
00768       cfg_for_ports[0] = 1;
00769    }
00770 
00771    struct port_config* new = (struct port_config *)calloc(1, sizeof(struct port_config));
00772    
00773    {
00774       int l = strlen(cat);
00775       new->name = (char *)calloc(l+1, sizeof(char));
00776       strncpy(new->name, cat, l);
00777    }
00778    
00779    for (; v; v=v->next) {
00780       if (!strcasecmp(v->name, "ports")) {
00781          /* TODO check for value not beeing set, like PORTS= */
00782          char *iter;
00783          char *value = v->value;
00784          while ((iter = strchr(value, ',')) != NULL) {
00785             *iter = 0;
00786             /* strip spaces */
00787             while (*value && *value == ' ') {
00788                value++;
00789             }
00790             /* TODO check for char not 0-9 */
00791 
00792             if (*value){
00793                int p = atoi(value);
00794                if (p <= max_ports && p > 0) {
00795                   cfg_for_ports[p] = 1;
00796                   if (strstr(value, "ptp"))
00797                      ptp[p] = 1;
00798                } else
00799                   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);
00800                value = ++iter;
00801             }
00802          }
00803          /* the remaining or the only one */
00804          /* strip spaces */
00805          while (*value && *value == ' ') {
00806             value++;
00807          }
00808          /* TODO check for char not 0-9 */
00809          if (*value) {
00810             int p = atoi(value);
00811             if (p <= max_ports && p > 0) {
00812                cfg_for_ports[p] = 1;
00813                if (strstr(value, "ptp"))
00814                   ptp[p] = 1;
00815             } else
00816                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);
00817          }
00818          continue;
00819       }
00820       PARSE_CFG_STR(context);
00821       PARSE_CFG_INT(dialplan);
00822       PARSE_CFG_INT(localdialplan);
00823       PARSE_CFG_STR(nationalprefix);
00824       PARSE_CFG_STR(internationalprefix);
00825       PARSE_CFG_STR(language);
00826       if (!strcasecmp(v->name, "presentation")) {
00827          if (v->value && strlen(v->value)) {
00828             new->pres = (int *)malloc(sizeof(int));
00829             if (!strcasecmp(v->value, "allowed")) {
00830                *(new->pres) = 1;
00831             }
00832             /* TODO: i assume if it is not "allowed", it is "not_screened" */
00833             else {
00834                *(new->pres) = 0;
00835             }
00836          }
00837          continue;
00838       }
00839       PARSE_CFG_INT(rxgain);
00840       PARSE_CFG_INT(txgain);
00841       PARSE_CFG_BOOL(te_choose_channel);
00842       PARSE_CFG_BOOL(immediate);
00843       PARSE_CFG_BOOL(always_immediate);
00844       PARSE_CFG_BOOL(hold_allowed);
00845       PARSE_CFG_BOOL(early_bconnect);
00846       PARSE_CFG_BOOL(use_callingpres);
00847       PARSE_CFG_HYBRID(echocancel, DEF_ECHOCANCEL);
00848       PARSE_CFG_BOOL(echocancelwhenbridged);
00849       PARSE_CFG_HYBRID(echotraining, DEF_ECHOTRAINING);
00850       PARSE_CFG_STR(callerid);
00851       PARSE_CFG_STR(method);
00852       if (!strcasecmp(v->name, "msns")) {
00853          /* TODO check for value not beeing set, like msns= */
00854          char *iter;
00855          char *value = v->value;
00856 
00857          while ((iter = strchr(value, ',')) != NULL) {
00858             *iter = 0;
00859             /* strip spaces */
00860             while (*value && *value == ' ') {
00861                value++;
00862             }
00863             /* TODO check for char not 0-9 */
00864             if (*value){
00865                int l = strlen(value);
00866                if (l) {
00867                   struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
00868                   ml->msn = (char *)calloc(l+1, sizeof(char));
00869                   strncpy(ml->msn,value,l);
00870                   ml->next = new->msn_list;
00871                   new->msn_list = ml;
00872                }
00873                value = ++iter;
00874             }
00875          }
00876          /* the remaining or the only one */
00877          /* strip spaces */
00878          while (*value && *value == ' ') {
00879             value++;
00880          }
00881          /* TODO check for char not 0-9 */
00882          if (*value) {
00883             int l = strlen(value);
00884             if (l) {
00885                struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
00886                ml->msn = (char *)calloc(l+1, sizeof(char));
00887                strncpy(ml->msn,value,l);
00888                ml->next = new->msn_list;
00889                new->msn_list = ml;
00890             }
00891          }
00892          continue;
00893       }
00894       if (!strcasecmp(v->name, "callgroup")) {
00895          new->callgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
00896          *(new->callgroup)=ast_get_group(v->value);
00897          continue;
00898       }
00899       if (!strcasecmp(v->name, "pickupgroup")) {
00900          new->pickupgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
00901          *(new->pickupgroup)=ast_get_group(v->value);
00902          continue;
00903       }
00904    }
00905    /* store the new config in our array of port configs */
00906    for (i = 0; i < (max_ports + 1); i++) {
00907       if (cfg_for_ports[i])
00908          port_cfg[i] = new;
00909    }
00910 }
00911 
00912 
00913 static void fill_defaults (void) {
00914    
00915    /* general defaults */
00916    if (!general_cfg->debug)
00917       general_cfg->debug = (int*)calloc(1, sizeof(int));
00918    if (!general_cfg->trace_calls)
00919       general_cfg->trace_calls = (int*)calloc(1, sizeof(int));
00920    if (!general_cfg->trace_dir) {
00921       general_cfg->trace_dir = (char *)malloc(10 * sizeof(char));
00922       sprintf(general_cfg->trace_dir, "/var/log/");
00923    }
00924    if (!general_cfg->bridging) {
00925       general_cfg->bridging = (int*)malloc(sizeof(int));
00926       *general_cfg->bridging = 1;
00927    }
00928    if (!general_cfg->stop_tone_after_first_digit) {
00929       general_cfg->stop_tone_after_first_digit = (int*)malloc(sizeof(int));
00930       *general_cfg->stop_tone_after_first_digit = 1;
00931    }
00932    if (!general_cfg->append_digits2exten) {
00933       general_cfg->append_digits2exten = (int*)malloc(sizeof(int));
00934       *general_cfg->append_digits2exten = 1;
00935    }
00936    if (!general_cfg->l1_info_ok) {
00937       general_cfg->l1_info_ok = (int*)malloc(sizeof(int));
00938       *general_cfg->l1_info_ok = 1;
00939    }
00940    if (!general_cfg->clear_l3)
00941       general_cfg->clear_l3 =(int*)calloc(1, sizeof(int));
00942    if (!general_cfg->dynamic_crypt)
00943       general_cfg->dynamic_crypt = (int*)calloc(1, sizeof(int));
00944 
00945    /* defaults for default port config */
00946    if (!port_cfg[0])
00947       port_cfg[0] = (struct port_config*)calloc(1, sizeof(struct port_config));
00948    if (!port_cfg[0]->name) {
00949       port_cfg[0]->name = (char *)malloc(8 * sizeof(char));
00950       sprintf(port_cfg[0]->name, "default");
00951    }
00952    if (!port_cfg[0]->rxgain)
00953       port_cfg[0]->rxgain = (int *)calloc(1, sizeof(int));
00954    if (!port_cfg[0]->txgain)
00955       port_cfg[0]->txgain = (int *)calloc(1, sizeof(int));
00956    if (!port_cfg[0]->te_choose_channel)
00957       port_cfg[0]->te_choose_channel = (int *)calloc(1, sizeof(int));
00958    if (!port_cfg[0]->context) {
00959       port_cfg[0]->context = (char *)malloc(8 * sizeof(char));
00960       sprintf(port_cfg[0]->context, "default");
00961    }
00962    if (!port_cfg[0]->language) {
00963       port_cfg[0]->language = (char *)malloc(3 * sizeof(char));
00964       sprintf(port_cfg[0]->language, "en");
00965    }
00966    if (!port_cfg[0]->callerid)
00967       port_cfg[0]->callerid = (char *)calloc(1, sizeof(char));
00968    if (!port_cfg[0]->method) {
00969       port_cfg[0]->method = (char *)malloc(9 * sizeof(char));
00970       sprintf(port_cfg[0]->method, "standard");
00971    }
00972    if (!port_cfg[0]->dialplan)
00973       port_cfg[0]->dialplan = (int *)calloc(1, sizeof(int));
00974    if (!port_cfg[0]->localdialplan)
00975       port_cfg[0]->localdialplan = (int *)calloc(1, sizeof(int));
00976    if (!port_cfg[0]->nationalprefix) {
00977       port_cfg[0]->nationalprefix = (char *)malloc(2 * sizeof(char));
00978       sprintf(port_cfg[0]->nationalprefix, "0");
00979    }
00980    if (!port_cfg[0]->internationalprefix) {
00981       port_cfg[0]->internationalprefix = (char *)malloc(3 * sizeof(char));
00982       sprintf(port_cfg[0]->internationalprefix, "00");
00983    }
00984    if (!port_cfg[0]->pres) {
00985       port_cfg[0]->pres = (int *)malloc(sizeof(int));
00986       *port_cfg[0]->pres = 1;
00987    }
00988    if (!port_cfg[0]->always_immediate)
00989       port_cfg[0]->always_immediate = (int *)calloc(1, sizeof(int));
00990    if (!port_cfg[0]->immediate)
00991       port_cfg[0]->immediate = (int *)calloc(1, sizeof(int));
00992    if (!port_cfg[0]->hold_allowed)
00993       port_cfg[0]->hold_allowed = (int *)calloc(1, sizeof(int));
00994    if (!port_cfg[0]->early_bconnect) {
00995       port_cfg[0]->early_bconnect = (int *)malloc(sizeof(int));
00996       *port_cfg[0]->early_bconnect = 1;
00997    }
00998    if (!port_cfg[0]->echocancel)
00999       port_cfg[0]->echocancel=(int *)calloc(1, sizeof(int));
01000    if (!port_cfg[0]->echocancelwhenbridged)
01001       port_cfg[0]->echocancelwhenbridged=(int *)calloc(1, sizeof(int));
01002    if (!port_cfg[0]->echotraining) {
01003       port_cfg[0]->echotraining=(int *)malloc(sizeof(int));
01004       *port_cfg[0]->echotraining = 1;
01005    }
01006    if (!port_cfg[0]->use_callingpres) {
01007       port_cfg[0]->use_callingpres = (int *)malloc(sizeof(int));
01008       *port_cfg[0]->use_callingpres = 1;
01009    }
01010    if (!port_cfg[0]->msn_list) {
01011       port_cfg[0]->msn_list = (struct msn_list *)malloc(sizeof(struct msn_list));
01012       port_cfg[0]->msn_list->next = NULL;
01013       port_cfg[0]->msn_list->msn = (char *)calloc(2, sizeof(char));
01014       *(port_cfg[0]->msn_list->msn) = '*';
01015    }
01016 }
01017 
01018 void misdn_cfg_reload (void) {
01019    misdn_cfg_init (0);
01020 }
01021 
01022 void misdn_cfg_destroy (void) {
01023 
01024    misdn_cfg_lock();
01025    
01026    free_port_cfg();
01027    free_general_cfg();
01028    
01029    free(port_cfg);
01030    free(general_cfg);
01031    free(ptp);
01032 
01033    misdn_cfg_unlock();
01034    ast_mutex_destroy(&config_mutex);
01035 }
01036 
01037 void misdn_cfg_init (int this_max_ports)
01038 {
01039    char config[]="misdn.conf";
01040    
01041    struct ast_config *cfg;
01042    cfg = AST_LOAD_CFG(config);
01043    if (!cfg) {
01044       ast_log(LOG_WARNING,"no misdn.conf ?\n");
01045       return;
01046    }
01047 
01048    misdn_cfg_lock();
01049    
01050    if (this_max_ports) {
01051       /* this is the first run */
01052       max_ports = this_max_ports;
01053       port_cfg = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
01054       general_cfg = (struct general_config*)calloc(1, sizeof(struct general_config));
01055       ptp = (int *)calloc(max_ports + 1, sizeof(int));
01056    }
01057    else {
01058       free_port_cfg();
01059       free_general_cfg();
01060       port_cfg = memset(port_cfg, 0, sizeof(struct port_config *) * (max_ports + 1));
01061       general_cfg = memset(general_cfg, 0, sizeof(struct general_config));
01062       ptp = memset(ptp, 0, sizeof(int) * (max_ports + 1));
01063    }
01064    
01065    char *cat;
01066    cat = ast_category_browse(cfg, NULL);
01067 
01068    while(cat) {
01069       struct ast_variable *v=ast_variable_browse(cfg,cat);
01070       if (!strcasecmp(cat,"general")) {
01071          build_general_config (v);
01072       } else {
01073          build_port_config (v, cat);
01074       }
01075       cat=ast_category_browse(cfg,cat);
01076    }
01077 
01078    fill_defaults();
01079    
01080    misdn_cfg_unlock();
01081    
01082    AST_DESTROY_CFG(cfg);
01083 }

Generated on Mon Mar 20 08:25:39 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1