Sat Mar 24 22:55:17 2007

Asterisk developer's documentation


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 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <errno.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/pbx.h>
00041 #include <asterisk/strings.h>
00042 #include <asterisk/utils.h>
00043 
00044 #define AST_LOAD_CFG ast_config_load
00045 #define AST_DESTROY_CFG ast_config_destroy
00046 
00047 #define NO_DEFAULT "<>"
00048 #define NONE 0
00049 
00050 #define GEN_CFG 1
00051 #define PORT_CFG 2
00052 #define NUM_GEN_ELEMENTS (sizeof(gen_spec) / sizeof(struct misdn_cfg_spec))
00053 #define NUM_PORT_ELEMENTS (sizeof(port_spec) / sizeof(struct misdn_cfg_spec))
00054 
00055 enum misdn_cfg_type {
00056    MISDN_CTYPE_STR,
00057    MISDN_CTYPE_INT,
00058    MISDN_CTYPE_BOOL,
00059    MISDN_CTYPE_BOOLINT,
00060    MISDN_CTYPE_MSNLIST,
00061    MISDN_CTYPE_ASTGROUP
00062 };
00063 
00064 struct msn_list {
00065    char *msn;
00066    struct msn_list *next;
00067 };
00068 
00069 union misdn_cfg_pt {
00070    char *str;
00071    int *num;
00072    struct msn_list *ml;
00073    ast_group_t *grp;
00074    void *any;
00075 };
00076 
00077 struct misdn_cfg_spec {
00078    char name[BUFFERSIZE];
00079    enum misdn_cfg_elements elem;
00080    enum misdn_cfg_type type;
00081    char def[BUFFERSIZE];
00082    int boolint_def;
00083 };
00084 
00085 static const struct misdn_cfg_spec port_spec[] = {
00086    { "name", MISDN_CFG_GROUPNAME, MISDN_CTYPE_STR, "default", NONE },
00087    { "allowed_bearers", MISDN_CFG_ALLOWED_BEARERS, MISDN_CTYPE_STR, "all", NONE },
00088    { "rxgain", MISDN_CFG_RXGAIN, MISDN_CTYPE_INT, "0", NONE },
00089    { "txgain", MISDN_CFG_TXGAIN, MISDN_CTYPE_INT, "0", NONE },
00090    { "te_choose_channel", MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CTYPE_BOOL, "no", NONE },
00091    { "far_alerting", MISDN_CFG_FAR_ALERTING, MISDN_CTYPE_BOOL, "no", NONE },
00092    { "pmp_l1_check", MISDN_CFG_PMP_L1_CHECK, MISDN_CTYPE_BOOL, "yes", NONE },
00093    { "block_on_alarm", MISDN_CFG_ALARM_BLOCK, MISDN_CTYPE_BOOL, "yes", NONE },
00094    { "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE },
00095    { "context", MISDN_CFG_CONTEXT, MISDN_CTYPE_STR, "default", NONE },
00096    { "language", MISDN_CFG_LANGUAGE, MISDN_CTYPE_STR, "en", NONE },
00097    { "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE },
00098    { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE },
00099    { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE },
00100    { "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE },
00101    { "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
00102    { "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
00103    { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE },
00104    { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE },
00105    { "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE },
00106    { "screen", MISDN_CFG_SCREEN, MISDN_CTYPE_INT, "-1", NONE },
00107    { "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
00108    { "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE },
00109    { "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
00110    { "senddtmf", MISDN_CFG_SENDDTMF, MISDN_CTYPE_BOOL, "no", NONE },
00111    { "hold_allowed", MISDN_CFG_HOLD_ALLOWED, MISDN_CTYPE_BOOL, "no", NONE },
00112    { "early_bconnect", MISDN_CFG_EARLY_BCONNECT, MISDN_CTYPE_BOOL, "yes", NONE },
00113    { "incoming_early_audio", MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CTYPE_BOOL, "no", NONE },
00114    { "echocancel", MISDN_CFG_ECHOCANCEL, MISDN_CTYPE_BOOLINT, "0", 128 },
00115    { "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE },
00116    { "jitterbuffer", MISDN_CFG_JITTERBUFFER, MISDN_CTYPE_INT, "4000", NONE },
00117    { "jitterbuffer_upper_threshold", MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CTYPE_INT, "0", NONE },
00118    { "callgroup", MISDN_CFG_CALLGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
00119    { "pickupgroup", MISDN_CFG_PICKUPGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
00120    { "msns", MISDN_CFG_MSNS, MISDN_CTYPE_MSNLIST, NO_DEFAULT, NONE }
00121 };
00122 
00123 static const struct misdn_cfg_spec gen_spec[] = {
00124    { "debug", MISDN_GEN_DEBUG, MISDN_CTYPE_INT, "0", NONE },
00125    { "misdn_init", MISDN_GEN_MISDN_INIT, MISDN_CTYPE_STR, "/etc/misdn-init.conf", NONE },
00126    { "tracefile", MISDN_GEN_TRACEFILE, MISDN_CTYPE_STR, "/var/log/asterisk/misdn.log", NONE },
00127    { "bridging", MISDN_GEN_BRIDGING, MISDN_CTYPE_BOOL, "yes", NONE },
00128    { "stop_tone_after_first_digit", MISDN_GEN_STOP_TONE, MISDN_CTYPE_BOOL, "yes", NONE },
00129    { "append_digits2exten", MISDN_GEN_APPEND_DIGITS2EXTEN, MISDN_CTYPE_BOOL, "yes", NONE },
00130    { "dynamic_crypt", MISDN_GEN_DYNAMIC_CRYPT, MISDN_CTYPE_BOOL, "no", NONE },
00131    { "crypt_prefix", MISDN_GEN_CRYPT_PREFIX, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
00132    { "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
00133    { "ntdebugflags", MISDN_GEN_NTDEBUGFLAGS, MISDN_CTYPE_INT, "0", NONE },
00134    { "ntdebugfile", MISDN_GEN_NTDEBUGFILE, MISDN_CTYPE_STR, "/var/log/misdn-nt.log", NONE }
00135 };
00136 
00137 /* array of port configs, default is at position 0. */
00138 static union misdn_cfg_pt **port_cfg;
00139 /* max number of available ports, is set on init */
00140 static int max_ports;
00141 /* general config */
00142 static union misdn_cfg_pt *general_cfg;
00143 /* storing the ptp flag separated to save memory */
00144 static int *ptp;
00145 /* maps enum config elements to array positions */
00146 static int *map;
00147 
00148 static ast_mutex_t config_mutex; 
00149 
00150 #define CLI_ERROR(name, value, section) ({ \
00151    ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \
00152       "Please edit your misdn.conf and then do a \"misdn reload\".\n", name, value, section); \
00153 })
00154 
00155 static void _enum_array_map (void)
00156 {
00157    int i, j;
00158 
00159    for (i = MISDN_CFG_FIRST + 1; i < MISDN_CFG_LAST; ++i) {
00160       if (i == MISDN_CFG_PTP)
00161          continue;
00162       for (j = 0; j < NUM_PORT_ELEMENTS; ++j) {
00163          if (port_spec[j].elem == i) {
00164             map[i] = j;
00165             break;
00166          }
00167       }
00168    }
00169    for (i = MISDN_GEN_FIRST + 1; i < MISDN_GEN_LAST; ++i) {
00170       for (j = 0; j < NUM_GEN_ELEMENTS; ++j) {
00171          if (gen_spec[j].elem == i) {
00172             map[i] = j;
00173             break;
00174          }
00175       }
00176    }
00177 }
00178 
00179 static int get_cfg_position (char *name, int type)
00180 {
00181    int i;
00182 
00183    switch (type) {
00184    case PORT_CFG:
00185       for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
00186          if (!strcasecmp(name, port_spec[i].name))
00187             return i;
00188       }
00189       break;
00190    case GEN_CFG:
00191       for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
00192          if (!strcasecmp(name, gen_spec[i].name))
00193             return i;
00194       }
00195    }
00196 
00197    return -1;
00198 }
00199 
00200 static inline void misdn_cfg_lock (void)
00201 {
00202    ast_mutex_lock(&config_mutex);
00203 }
00204 
00205 static inline void misdn_cfg_unlock (void)
00206 {
00207    ast_mutex_unlock(&config_mutex);
00208 }
00209 
00210 static void _free_msn_list (struct msn_list* iter)
00211 {
00212    if (iter->next)
00213       _free_msn_list(iter->next);
00214    if (iter->msn)
00215       free(iter->msn);
00216    free(iter);
00217 }
00218 
00219 static void _free_port_cfg (void)
00220 {
00221    int i, j;
00222    int gn = map[MISDN_CFG_GROUPNAME];
00223    union misdn_cfg_pt* free_list[max_ports + 2];
00224    
00225    memset(free_list, 0, sizeof(free_list));
00226    free_list[0] = port_cfg[0];
00227    for (i = 1; i <= max_ports; ++i) {
00228       if (port_cfg[i][gn].str) {
00229          /* we always have a groupname in the non-default case, so this is fine */
00230          for (j = 1; j <= max_ports; ++j) {
00231             if (free_list[j] && free_list[j][gn].str == port_cfg[i][gn].str)
00232                break;
00233             else if (!free_list[j]) {
00234                free_list[j] = port_cfg[i];
00235                break;
00236             }
00237          }
00238       }
00239    }
00240    for (j = 0; free_list[j]; ++j) {
00241       for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
00242          if (free_list[j][i].any) {
00243             if (port_spec[i].type == MISDN_CTYPE_MSNLIST)
00244                _free_msn_list(free_list[j][i].ml);
00245             else
00246                free(free_list[j][i].any);
00247          }
00248       }
00249    }
00250 }
00251 
00252 static void _free_general_cfg (void)
00253 {
00254    int i;
00255 
00256    for (i = 0; i < NUM_GEN_ELEMENTS; i++) 
00257       if (general_cfg[i].any)
00258          free(general_cfg[i].any);
00259 }
00260 
00261 void misdn_cfg_get (int port, enum misdn_cfg_elements elem, void *buf, int bufsize)
00262 {
00263    int place;
00264 
00265    if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
00266       memset(buf, 0, bufsize);
00267       ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
00268       return;
00269    }
00270 
00271    misdn_cfg_lock();
00272    if (elem == MISDN_CFG_PTP) {
00273       if (!memcpy(buf, &ptp[port], (bufsize > ptp[port]) ? sizeof(ptp[port]) : bufsize))
00274          memset(buf, 0, bufsize);
00275    } else {
00276       if ((place = map[elem]) < 0) {
00277          memset (buf, 0, bufsize);
00278          ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Invalid element (%d) requested.\n", elem);
00279       } else {
00280          if (elem < MISDN_CFG_LAST) {
00281             switch (port_spec[place].type) {
00282             case MISDN_CTYPE_STR:
00283                if (port_cfg[port][place].str) {
00284                   if (!memccpy(buf, port_cfg[port][place].str, 0, bufsize))
00285                      memset(buf, 0, 1);
00286                } else if (port_cfg[0][place].str) {
00287                   if (!memccpy(buf, port_cfg[0][place].str, 0, bufsize))
00288                      memset(buf, 0, 1);
00289                }
00290                break;
00291             default:
00292                if (port_cfg[port][place].any)
00293                   memcpy(buf, port_cfg[port][place].any, bufsize);
00294                else if (port_cfg[0][place].any)
00295                   memcpy(buf, port_cfg[0][place].any, bufsize);
00296                else
00297                   memset(buf, 0, bufsize);
00298             }
00299          } else {
00300             switch (gen_spec[place].type) {
00301             case MISDN_CTYPE_STR:
00302                if (!general_cfg[place].str || !memccpy(buf, general_cfg[place].str, 0, bufsize))
00303                   memset(buf, 0, 1);
00304                break;
00305             default:
00306                if (general_cfg[place].any)
00307                   memcpy(buf, general_cfg[place].any, bufsize);
00308                else
00309                   memset(buf, 0, bufsize);
00310             }
00311          }
00312       }
00313    }
00314    misdn_cfg_unlock();
00315 }
00316 
00317 int misdn_cfg_is_msn_valid (int port, char* msn)
00318 {
00319    int re = 0;
00320    struct msn_list *iter;
00321 
00322    if (!misdn_cfg_is_port_valid(port)) {
00323       ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
00324       return 0;
00325    }
00326 
00327    misdn_cfg_lock();
00328    if (port_cfg[port][map[MISDN_CFG_MSNS]].ml)
00329       iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
00330    else
00331       iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
00332    for (; iter; iter = iter->next) 
00333       if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
00334          re = 1;
00335          break;
00336       }
00337    misdn_cfg_unlock();
00338 
00339    return re;
00340 }
00341 
00342 int misdn_cfg_is_port_valid (int port)
00343 {
00344    return (port >= 1 && port <= max_ports);
00345 }
00346 
00347 int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth)
00348 {
00349    int i, re = 0;
00350    char *method = NULL;
00351 
00352    misdn_cfg_lock();
00353    for (i = 1; i <= max_ports; i++) {
00354       if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) {
00355          if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group))
00356             method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ? 
00357                     port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str);
00358       }
00359    }
00360    if (method) {
00361       switch (meth) {
00362       case METHOD_STANDARD:      re = !strcasecmp(method, "standard");
00363                            break;
00364       case METHOD_ROUND_ROBIN:   re = !strcasecmp(method, "round_robin");
00365                            break;
00366       }
00367    }
00368    misdn_cfg_unlock();
00369 
00370    return re;
00371 }
00372 
00373 void misdn_cfg_get_ports_string (char *ports)
00374 {
00375    char tmp[16];
00376    int l, i;
00377    int gn = map[MISDN_CFG_GROUPNAME];
00378 
00379    *ports = 0;
00380 
00381    misdn_cfg_lock();
00382    for (i = 1; i <= max_ports; i++) {
00383       if (port_cfg[i][gn].str) {
00384          if (ptp[i])
00385             sprintf(tmp, "%dptp,", i);
00386          else
00387             sprintf(tmp, "%d,", i);
00388          strcat(ports, tmp);
00389       }
00390    }
00391    misdn_cfg_unlock();
00392 
00393    if ((l = strlen(ports)))
00394       ports[l-1] = 0;
00395 }
00396 
00397 void misdn_cfg_get_config_string (int port, enum misdn_cfg_elements elem, char* buf, int bufsize)
00398 {
00399    int place;
00400    char tempbuf[BUFFERSIZE] = "";
00401    struct msn_list *iter;
00402 
00403    if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
00404       *buf = 0;
00405       ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
00406       return;
00407    }
00408 
00409    place = map[elem];
00410 
00411    misdn_cfg_lock();
00412    if (elem == MISDN_CFG_PTP) {
00413       snprintf(buf, bufsize, " -> ptp: %s", ptp[port] ? "yes" : "no");
00414    }
00415    else if (elem > MISDN_CFG_FIRST && elem < MISDN_CFG_LAST) {
00416       switch (port_spec[place].type) {
00417       case MISDN_CTYPE_INT:
00418       case MISDN_CTYPE_BOOLINT:
00419          if (port_cfg[port][place].num)
00420             snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[port][place].num);
00421          else if (port_cfg[0][place].num)
00422             snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[0][place].num);
00423          else
00424             snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00425          break;
00426       case MISDN_CTYPE_BOOL:
00427          if (port_cfg[port][place].num)
00428             snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[port][place].num ? "yes" : "no");
00429          else if (port_cfg[0][place].num)
00430             snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[0][place].num ? "yes" : "no");
00431          else
00432             snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00433          break;
00434       case MISDN_CTYPE_ASTGROUP:
00435          if (port_cfg[port][place].grp)
00436             snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, 
00437                    ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp));
00438          else if (port_cfg[0][place].grp)
00439             snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, 
00440                    ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp));
00441          else
00442             snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00443          break;
00444       case MISDN_CTYPE_MSNLIST:
00445          if (port_cfg[port][place].ml)
00446             iter = port_cfg[port][place].ml;
00447          else
00448             iter = port_cfg[0][place].ml;
00449          if (iter) {
00450             for (; iter; iter = iter->next)
00451                sprintf(tempbuf, "%s%s, ", tempbuf, iter->msn);
00452             tempbuf[strlen(tempbuf)-2] = 0;
00453          }
00454          snprintf(buf, bufsize, " -> msns: %s", *tempbuf ? tempbuf : "none");
00455          break;
00456       case MISDN_CTYPE_STR:
00457          if ( port_cfg[port][place].str) {
00458             snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[port][place].str);
00459          } else if (port_cfg[0][place].str) {
00460             snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[0][place].str);
00461          } else {
00462             snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00463          }
00464          break;
00465       }
00466    } else if (elem > MISDN_GEN_FIRST && elem < MISDN_GEN_LAST) {
00467       switch (gen_spec[place].type) {
00468       case MISDN_CTYPE_INT:
00469       case MISDN_CTYPE_BOOLINT:
00470          if (general_cfg[place].num)
00471             snprintf(buf, bufsize, " -> %s: %d", gen_spec[place].name, *general_cfg[place].num);
00472          else
00473             snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00474          break;
00475       case MISDN_CTYPE_BOOL:
00476          if (general_cfg[place].num)
00477             snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, *general_cfg[place].num ? "yes" : "no");
00478          else
00479             snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00480          break;
00481       case MISDN_CTYPE_STR:
00482          if ( general_cfg[place].str) {
00483             snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, general_cfg[place].str);
00484          } else {
00485             snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00486          }
00487          break;
00488       default:
00489          snprintf(buf, bufsize, " -> type of %s not handled yet", gen_spec[place].name);
00490          break;
00491       }
00492    } else {
00493       *buf = 0;
00494       ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Invalid config element (%d) requested.\n", elem);
00495    }
00496    misdn_cfg_unlock();
00497 }
00498 
00499 int misdn_cfg_get_next_port (int port)
00500 {
00501    int p = -1;
00502    int gn = map[MISDN_CFG_GROUPNAME];
00503    
00504    misdn_cfg_lock();
00505    for (port++; port <= max_ports; port++) {
00506       if (port_cfg[port][gn].str) {
00507          p = port;
00508          break;
00509       }
00510    }
00511    misdn_cfg_unlock();
00512 
00513    return p;
00514 }
00515 
00516 int misdn_cfg_get_next_port_spin (int port)
00517 {
00518    int p = misdn_cfg_get_next_port(port);
00519    return (p > 0) ? p : misdn_cfg_get_next_port(0);
00520 }
00521 
00522 static int _parse (union misdn_cfg_pt *dest, char *value, enum misdn_cfg_type type, int boolint_def)
00523 {
00524    int re = 0;
00525    int len, tmp;
00526    char *valtmp;
00527 
00528    switch (type) {
00529    case MISDN_CTYPE_STR:
00530       if ((len = strlen(value))) {
00531          dest->str = (char *)malloc((len + 1) * sizeof(char));
00532          strncpy(dest->str, value, len);
00533          dest->str[len] = 0;
00534       } else {
00535          dest->str = (char *)malloc( sizeof(char));
00536          dest->str[0] = 0;
00537       }
00538       break;
00539    case MISDN_CTYPE_INT:
00540    {
00541       char *pat;
00542       if (strchr(value,'x')) 
00543          pat="%x";
00544       else
00545          pat="%d";
00546       if (sscanf(value, pat, &tmp)) {
00547          dest->num = (int *)malloc(sizeof(int));
00548          memcpy(dest->num, &tmp, sizeof(int));
00549       } else
00550          re = -1;
00551    }
00552       break;
00553    case MISDN_CTYPE_BOOL:
00554       dest->num = (int *)malloc(sizeof(int));
00555       *(dest->num) = (ast_true(value) ? 1 : 0);
00556       break;
00557    case MISDN_CTYPE_BOOLINT:
00558       dest->num = (int *)malloc(sizeof(int));
00559       if (sscanf(value, "%d", &tmp)) {
00560          memcpy(dest->num, &tmp, sizeof(int));
00561       } else {
00562          *(dest->num) = (ast_true(value) ? boolint_def : 0);
00563       }
00564       break;
00565    case MISDN_CTYPE_MSNLIST:
00566       for (valtmp = strsep(&value, ","); valtmp; valtmp = strsep(&value, ",")) {
00567          if ((len = strlen(valtmp))) {
00568             struct msn_list *ml = (struct msn_list *)malloc(sizeof(struct msn_list));
00569             ml->msn = (char *)calloc(len+1, sizeof(char));
00570             strncpy(ml->msn, valtmp, len);
00571             ml->next = dest->ml;
00572             dest->ml = ml;
00573          }
00574       }
00575       break;
00576    case MISDN_CTYPE_ASTGROUP:
00577       dest->grp = (ast_group_t *)malloc(sizeof(ast_group_t));
00578       *(dest->grp) = ast_get_group(value);
00579       break;
00580    }
00581 
00582    return re;
00583 }
00584 
00585 static void _build_general_config (struct ast_variable *v)
00586 {
00587    int pos;
00588 
00589    for (; v; v = v->next) {
00590       if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) || 
00591          (_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0))
00592          CLI_ERROR(v->name, v->value, "general");
00593    }
00594 }
00595 
00596 static void _build_port_config (struct ast_variable *v, char *cat)
00597 {
00598    int pos, i;
00599    union misdn_cfg_pt cfg_tmp[NUM_PORT_ELEMENTS];
00600    int cfg_for_ports[max_ports + 1];
00601 
00602    if (!v || !cat)
00603       return;
00604 
00605    memset(cfg_tmp, 0, sizeof(cfg_tmp));
00606    memset(cfg_for_ports, 0, sizeof(cfg_for_ports));
00607 
00608    if (!strcasecmp(cat, "default")) {
00609       cfg_for_ports[0] = 1;
00610    }
00611 
00612    if (((pos = get_cfg_position("name", PORT_CFG)) < 0) || 
00613       (_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) {
00614       CLI_ERROR(v->name, v->value, cat);
00615       return;
00616    }
00617 
00618    for (; v; v = v->next) {
00619       if (!strcasecmp(v->name, "ports")) {
00620          char *token;
00621          char ptpbuf[BUFFERSIZE] = "";
00622          int start, end;
00623          for (token = strsep(&v->value, ","); token; token = strsep(&v->value, ","), *ptpbuf = 0) { 
00624             if (!*token)
00625                continue;
00626             if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) {
00627                for (; start <= end; start++) {
00628                   if (start <= max_ports && start > 0) {
00629                      cfg_for_ports[start] = 1;
00630                      ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
00631                   } else
00632                      CLI_ERROR(v->name, v->value, cat);
00633                }
00634             } else {
00635                if (sscanf(token, "%d%s", &start, ptpbuf)) {
00636                   if (start <= max_ports && start > 0) {
00637                      cfg_for_ports[start] = 1;
00638                      ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
00639                   } else
00640                      CLI_ERROR(v->name, v->value, cat);
00641                } else
00642                   CLI_ERROR(v->name, v->value, cat);
00643             }
00644          }
00645       } else {
00646          if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) || 
00647             (_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0))
00648             CLI_ERROR(v->name, v->value, cat);
00649       }
00650    }
00651 
00652    for (i = 0; i < (max_ports + 1); ++i) {
00653       if (cfg_for_ports[i]) {
00654          memcpy(port_cfg[i], cfg_tmp, sizeof(cfg_tmp));
00655       }
00656    }
00657 }
00658 
00659 void misdn_cfg_update_ptp (void)
00660 {
00661    char misdn_init[BUFFERSIZE];
00662    char line[BUFFERSIZE];
00663    FILE *fp;
00664    char *tok, *p, *end;
00665    int port;
00666 
00667    misdn_cfg_get(0, MISDN_GEN_MISDN_INIT, &misdn_init, sizeof(misdn_init));
00668 
00669    if (misdn_init) {
00670       fp = fopen(misdn_init, "r");
00671       if (fp) {
00672          while(fgets(line, sizeof(line), fp)) {
00673             if (!strncmp(line, "nt_ptp", 6)) {
00674                for (tok = strtok_r(line,",=", &p);
00675                    tok;
00676                    tok = strtok_r(NULL,",=", &p)) {
00677                   port = strtol(tok, &end, 10);
00678                   if (end != tok && misdn_cfg_is_port_valid(port)) {
00679                      misdn_cfg_lock();
00680                      ptp[port] = 1;
00681                      misdn_cfg_unlock();
00682                   }
00683                }
00684             }
00685          }
00686          fclose(fp);
00687       } else {
00688          ast_log(LOG_WARNING,"Couldn't open %s: %s\n", misdn_init, strerror(errno));
00689       }
00690    }
00691 }
00692 
00693 static void _fill_defaults (void)
00694 {
00695    int i;
00696 
00697    for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
00698       if (!port_cfg[0][i].any && strcasecmp(port_spec[i].def, NO_DEFAULT))
00699          _parse(&(port_cfg[0][i]), (char *)port_spec[i].def, port_spec[i].type, port_spec[i].boolint_def);
00700    }
00701    for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
00702       if (!general_cfg[i].any && strcasecmp(gen_spec[i].def, NO_DEFAULT))
00703          _parse(&(general_cfg[i]), (char *)gen_spec[i].def, gen_spec[i].type, gen_spec[i].boolint_def);
00704    }
00705 }
00706 
00707 void misdn_cfg_reload (void)
00708 {
00709    misdn_cfg_init (0);
00710 }
00711 
00712 void misdn_cfg_destroy (void)
00713 {
00714    misdn_cfg_lock();
00715 
00716    _free_port_cfg();
00717    _free_general_cfg();
00718 
00719    free(port_cfg);
00720    free(general_cfg);
00721    free(ptp);
00722    free(map);
00723 
00724    misdn_cfg_unlock();
00725    ast_mutex_destroy(&config_mutex);
00726 }
00727 
00728 void misdn_cfg_init (int this_max_ports)
00729 {
00730    char config[] = "misdn.conf";
00731    char *cat, *p;
00732    int i;
00733    struct ast_config *cfg;
00734    struct ast_variable *v;
00735 
00736    if (!(cfg = AST_LOAD_CFG(config))) {
00737       ast_log(LOG_WARNING,"no misdn.conf ?\n");
00738       return;
00739    }
00740 
00741    misdn_cfg_lock();
00742 
00743    if (this_max_ports) {
00744       /* this is the first run */
00745       max_ports = this_max_ports;
00746       p = (char *)calloc(1, (max_ports + 1) * sizeof(union misdn_cfg_pt *)
00747                      + (max_ports + 1) * NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt));
00748       port_cfg = (union misdn_cfg_pt **)p;
00749       p += (max_ports + 1) * sizeof(union misdn_cfg_pt *);
00750       for (i = 0; i <= max_ports; ++i) {
00751          port_cfg[i] = (union misdn_cfg_pt *)p;
00752          p += NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt);
00753       }
00754       general_cfg = (union misdn_cfg_pt *)calloc(1, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
00755       ptp = (int *)calloc(max_ports + 1, sizeof(int));
00756       map = (int *)calloc(MISDN_GEN_LAST + 1, sizeof(int));
00757       _enum_array_map();
00758    }
00759    else {
00760       /* misdn reload */
00761       _free_port_cfg();
00762       _free_general_cfg();
00763       memset(port_cfg[0], 0, NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt) * (max_ports + 1));
00764       memset(general_cfg, 0, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
00765       memset(ptp, 0, sizeof(int) * (max_ports + 1));
00766    }
00767 
00768    cat = ast_category_browse(cfg, NULL);
00769 
00770    while(cat) {
00771       v = ast_variable_browse(cfg, cat);
00772       if (!strcasecmp(cat,"general")) {
00773          _build_general_config(v);
00774       } else {
00775          _build_port_config(v, cat);
00776       }
00777       cat = ast_category_browse(cfg,cat);
00778    }
00779 
00780    _fill_defaults();
00781 
00782    misdn_cfg_unlock();
00783    AST_DESTROY_CFG(cfg);
00784 }

Generated on Sat Mar 24 22:55:17 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.7