cfgutils.c

Go to the documentation of this file.
00001 /*
00002  * $Id: cfgutils.c 5482 2009-01-17 17:40:08Z miconda $
00003  *
00004  * Copyright (C) 2007 1&1 Internet AG
00005  * Copyright (C) 2007 BASIS AudioNet GmbH
00006  * Copyright (C) 2004 FhG
00007  * Copyright (C) 2005-2006 Voice Sistem S.R.L.
00008  *
00009  * This file is part of Kamailio, a free SIP server.
00010  *
00011  * Kamailio is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * Kamailio is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License 
00022  * along with this program; if not, write to the Free Software 
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  * cfgutils module: random probability functions for openser;
00026  * it provide functions to make a decision in the script
00027  * of the server based on a probability function.
00028  * The benefit of this module is the value of the probability function
00029  * can be manipulated by external applications such as web interface
00030  * or command line tools.
00031  * Furthermore it provides some functions to let the server wait a
00032  * specific time interval.
00033  *
00034  * gflags module: global flags; it keeps a bitmap of flags
00035  * in shared memory and may be used to change behaviour 
00036  * of server based on value of the flags. E.g.,
00037  *    if (is_gflag("1")) { t_relay_to_udp("10.0.0.1","5060"); }
00038  *    else { t_relay_to_udp("10.0.0.2","5060"); }
00039  * The benefit of this module is the value of the switch flags
00040  * can be manipulated by external applications such as web interface
00041  * or command line tools.
00042  */
00043 
00044 
00045 /* FIFO action protocol names */
00046 #define FIFO_SET_PROB   "rand_set_prob"
00047 #define FIFO_RESET_PROB "rand_reset_prob"
00048 #define FIFO_GET_PROB   "rand_get_prob"
00049 #define FIFO_GET_HASH   "get_config_hash"
00050 #define FIFO_CHECK_HASH "check_config_hash"
00051 
00052 /* flag buffer size for FIFO protocool */
00053 #define MAX_FLAG_LEN 12
00054 /* FIFO action protocol names for gflag functionality */
00055 #define FIFO_SET_GFLAG "set_gflag"
00056 #define FIFO_IS_GFLAG "is_gflag"
00057 #define FIFO_RESET_GFLAG "reset_gflag"
00058 #define FIFO_GET_GFLAGS "get_gflags"
00059 
00060 #include "../../sr_module.h"
00061 #include "../../error.h"
00062 #include "../../pvar.h"
00063 #include "../../ut.h"
00064 #include "../../mem/mem.h"
00065 #include "../../mem/shm_mem.h"
00066 #include "../../mi/mi.h"
00067 #include "../../mod_fix.h"
00068 #include "../../md5utils.h"
00069 #include "../../globals.h"
00070 #include "../../hash_func.h"
00071 #include "../../locking.h"
00072 #include <stdio.h>
00073 #include <stdlib.h>
00074 
00075 MODULE_VERSION
00076 
00077 static int set_prob(struct sip_msg*, char *, char *);
00078 static int reset_prob(struct sip_msg*, char *, char *);
00079 static int get_prob(struct sip_msg*, char *, char *);
00080 static int rand_event(struct sip_msg*, char *, char *);
00081 static int m_sleep(struct sip_msg*, char *, char *);
00082 static int m_usleep(struct sip_msg*, char *, char *);
00083 static int dbg_abort(struct sip_msg*, char*,char*);
00084 static int dbg_pkg_status(struct sip_msg*, char*,char*);
00085 static int dbg_shm_status(struct sip_msg*, char*,char*);
00086 
00087 static int set_gflag(struct sip_msg*, char *, char *);
00088 static int reset_gflag(struct sip_msg*, char *, char *);
00089 static int is_gflag(struct sip_msg*, char *, char *);
00090 
00091 static int cfg_lock(struct sip_msg*, char *, char *);
00092 static int cfg_unlock(struct sip_msg*, char *, char *);
00093 
00094 static struct mi_root* mi_set_prob(struct mi_root* cmd, void* param );
00095 static struct mi_root* mi_reset_prob(struct mi_root* cmd, void* param );
00096 static struct mi_root* mi_get_prob(struct mi_root* cmd, void* param );
00097 static struct mi_root* mi_get_hash(struct mi_root* cmd, void* param );
00098 static struct mi_root* mi_check_hash(struct mi_root* cmd, void* param );
00099 
00100 static struct mi_root* mi_set_gflag(struct mi_root* cmd, void* param );
00101 static struct mi_root* mi_reset_gflag(struct mi_root* cmd, void* param );
00102 static struct mi_root* mi_is_gflag(struct mi_root* cmd, void* param );
00103 static struct mi_root* mi_get_gflags(struct mi_root* cmd, void* param );
00104 
00105 
00106 static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
00107       pv_value_t *res);
00108 
00109 
00110 static int fixup_prob( void** param, int param_no);
00111 static int fixup_gflags( void** param, int param_no);
00112 
00113 
00114 static int mod_init(void);
00115 static void mod_destroy(void);
00116 
00117 static int initial_prob = 10;
00118 static int *probability;
00119 
00120 static char config_hash[MD5_LEN];
00121 static char* hash_file = NULL;
00122 
00123 static int initial_gflags=0;
00124 static unsigned int *gflags=0;
00125 
00126 static gen_lock_set_t *_cfg_lock_set = NULL;
00127 static unsigned int _cfg_lock_size = 0;
00128 
00129 static cmd_export_t cmds[]={
00130    {"rand_set_prob", /* action name as in scripts */
00131       (cmd_function)set_prob,  /* C function name */
00132       1,          /* number of parameters */
00133       fixup_prob, 0,         /* */
00134       /* can be applied to original/failed requests and replies */
00135       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00136    {"rand_reset_prob", (cmd_function)reset_prob, 0, 0, 0,
00137       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00138    {"rand_get_prob",   (cmd_function)get_prob,   0, 0, 0,
00139       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00140    {"rand_event",      (cmd_function)rand_event, 0, 0, 0,
00141       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00142    {"sleep",  (cmd_function)m_sleep,  1, fixup_uint_null, 0,
00143       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00144    {"usleep", (cmd_function)m_usleep, 1, fixup_uint_null, 0,
00145       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00146    {"abort",      (cmd_function)dbg_abort,        0, 0, 0,
00147       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00148    {"pkg_status", (cmd_function)dbg_pkg_status,   0, 0, 0,
00149       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00150    {"shm_status", (cmd_function)dbg_shm_status,   0, 0, 0,
00151       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00152    {"set_gflag",    (cmd_function)set_gflag,   1,   fixup_gflags, 0,
00153       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00154    {"reset_gflag",  (cmd_function)reset_gflag, 1,   fixup_gflags, 0,
00155       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00156    {"is_gflag",     (cmd_function)is_gflag,    1,   fixup_gflags, 0,
00157       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00158    {"lock",         (cmd_function)cfg_lock,    1,   fixup_spve_null, 0,
00159       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00160    {"unlock",       (cmd_function)cfg_unlock,  1,   fixup_spve_null, 0,
00161       REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00162    {0, 0, 0, 0, 0, 0}
00163 };
00164 
00165 
00166 static param_export_t params[]={ 
00167    {"initial_probability", INT_PARAM, &initial_prob   },
00168    {"initial_gflags",      INT_PARAM, &initial_gflags },
00169    {"hash_file",           STR_PARAM, &hash_file      },
00170    {"lock_set_size",       INT_PARAM, &_cfg_lock_size },
00171    {0,0,0}
00172 };
00173 
00174 
00175 static mi_export_t mi_cmds[] = {
00176    { FIFO_SET_PROB,   mi_set_prob,   0,                 0,  0 },
00177    { FIFO_RESET_PROB, mi_reset_prob, MI_NO_INPUT_FLAG,  0,  0 },
00178    { FIFO_GET_PROB,   mi_get_prob,   MI_NO_INPUT_FLAG,  0,  0 },
00179    { FIFO_GET_HASH,   mi_get_hash,   MI_NO_INPUT_FLAG,  0,  0 },
00180    { FIFO_CHECK_HASH, mi_check_hash, MI_NO_INPUT_FLAG,  0,  0 },
00181    { FIFO_SET_GFLAG,   mi_set_gflag,   0,                 0,  0 },
00182    { FIFO_RESET_GFLAG, mi_reset_gflag, 0,                 0,  0 },
00183    { FIFO_IS_GFLAG,    mi_is_gflag,    0,                 0,  0 },
00184    { FIFO_GET_GFLAGS,  mi_get_gflags,  MI_NO_INPUT_FLAG,  0,  0 },
00185    { 0, 0, 0, 0, 0}
00186 };
00187 
00188 
00189 static pv_export_t mod_items[] = {
00190    { {"RANDOM", sizeof("RANDOM")-1}, PVT_OTHER, pv_get_random_val, 0,
00191       0, 0, 0, 0 },
00192    { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00193 };
00194 
00195 
00196 struct module_exports exports = {
00197    "cfgutils",
00198    DEFAULT_DLFLAGS, /* dlopen flags */
00199    cmds,        /* exported functions */
00200    params,      /* exported parameters */
00201    0,           /* exported statistics */
00202    mi_cmds,     /* exported MI functions */
00203    mod_items,   /* exported pseudo-variables */
00204    0,           /* extra processes */
00205    mod_init,    /* module initialization function */
00206    0,           /* response function*/
00207    mod_destroy, /* destroy function */
00208    0            /* per-child init function */
00209 };
00210 
00211 
00212 /**************************** fixup functions ******************************/
00213 static int fixup_prob( void** param, int param_no)
00214 {
00215    unsigned int myint;
00216    str param_str;
00217 
00218    /* we only fix the parameter #1 */
00219    if (param_no!=1)
00220       return 0;
00221 
00222    param_str.s=(char*) *param;
00223    param_str.len=strlen(param_str.s);
00224    str2int(&param_str, &myint);
00225 
00226    if (myint > 100) {
00227       LM_ERR("invalid probability <%d>\n", myint);
00228       return E_CFG;
00229    }
00230 
00231    pkg_free(*param);
00232    *param=(void *)(long)myint;
00233    return 0;
00234 }
00235 
00236 /**
00237  * convert char* to int and do bitwise right-shift
00238  * char* must be pkg_alloced and will be freed by the function
00239  */
00240 static int fixup_gflags( void** param, int param_no)
00241 {
00242    unsigned int myint;
00243    str param_str;
00244 
00245    /* we only fix the parameter #1 */
00246    if (param_no!=1)
00247       return 0;
00248 
00249    param_str.s=(char*) *param;
00250    param_str.len=strlen(param_str.s);
00251 
00252    if (str2int(&param_str, &myint )<0) {
00253       LM_ERR("bad number <%s>\n", (char *)(*param));
00254       return E_CFG;
00255    }
00256    if ( myint >= 8*sizeof(*gflags) ) {
00257       LM_ERR("flag <%d> out of "
00258          "range [0..%lu]\n", myint, ((unsigned long)8*sizeof(*gflags))-1 );
00259       return E_CFG;
00260    }
00261    /* convert from flag index to flag bitmap */
00262    myint = 1 << myint;
00263    /* success -- change to int */
00264    pkg_free(*param);
00265    *param=(void *)(long)myint;
00266    return 0;
00267 }
00268 
00269 
00270 /************************** module functions **********************************/
00271 
00272 static int set_gflag(struct sip_msg *bar, char *flag, char *foo) 
00273 {
00274    (*gflags) |= (unsigned int)(long)flag;
00275    return 1;
00276 }
00277 
00278 
00279 static int reset_gflag(struct sip_msg *bar, char *flag, char *foo)
00280 {
00281    (*gflags) &= ~ ((unsigned int)(long)flag);
00282    return 1;
00283 }
00284 
00285 
00286 static int is_gflag(struct sip_msg *bar, char *flag, char *foo)
00287 {
00288    return ( (*gflags) & ((unsigned int)(long)flag)) ? 1 : -1;
00289 }
00290 
00291 
00292 static struct mi_root* mi_set_gflag(struct mi_root* cmd_tree, void* param )
00293 {
00294    unsigned int flag;
00295    struct mi_node* node;
00296 
00297    node = cmd_tree->node.kids;
00298    if(node == NULL)
00299       return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00300 
00301    flag = 0;
00302    if( strno2int( &node->value, &flag) <0)
00303       goto error;
00304    if (!flag) {
00305       LM_ERR("incorrect flag\n");
00306       goto error;
00307    }
00308 
00309    (*gflags) |= flag;
00310 
00311    return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00312 error:
00313    return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00314 }
00315 
00316 
00317 static struct mi_root*  mi_reset_gflag(struct mi_root* cmd_tree, void* param )
00318 {
00319    unsigned int flag;
00320    struct mi_node* node = NULL;
00321 
00322    node = cmd_tree->node.kids;
00323    if(node == NULL)
00324       return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00325 
00326    flag = 0;
00327    if( strno2int( &node->value, &flag) <0)
00328       goto error;
00329    if (!flag) {
00330       LM_ERR("incorrect flag\n");
00331       goto error;
00332    }
00333 
00334    (*gflags) &= ~ flag;
00335 
00336    return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00337 error:
00338    return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00339 }
00340 
00341 
00342 static struct mi_root* mi_is_gflag(struct mi_root* cmd_tree, void* param )
00343 {
00344    unsigned int flag;
00345    struct mi_root* rpl_tree = NULL;
00346    struct mi_node* node = NULL;
00347 
00348    node = cmd_tree->node.kids;
00349    if(node == NULL)
00350       return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00351 
00352    flag = 0;
00353    if( strno2int( &node->value, &flag) <0)
00354       goto error_param;
00355    if (!flag) {
00356       LM_ERR("incorrect flag\n");
00357       goto error_param;
00358    }
00359 
00360    rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00361    if(rpl_tree ==0)
00362       return 0;
00363 
00364    if( ((*gflags) & flag)== flag )
00365       node = add_mi_node_child( &rpl_tree->node, 0, 0, 0, "TRUE", 4);
00366    else
00367       node = add_mi_node_child( &rpl_tree->node, 0, 0, 0, "FALSE", 5);
00368 
00369    if(node == NULL)
00370    {
00371       LM_ERR("failed to add node\n");
00372       free_mi_tree(rpl_tree);
00373       return 0;
00374    }
00375 
00376    return rpl_tree;
00377 error_param:
00378    return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00379 }
00380 
00381 
00382 static struct mi_root*  mi_get_gflags(struct mi_root* cmd_tree, void* param )
00383 {
00384    struct mi_root* rpl_tree= NULL;
00385    struct mi_node* node= NULL;
00386 
00387    rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00388    if(rpl_tree == NULL)
00389       return 0;
00390 
00391    node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "0x%X",(*gflags));
00392    if(node == NULL)
00393       goto error;
00394 
00395    node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%u",(*gflags));
00396    if(node == NULL)
00397       goto error;
00398 
00399    return rpl_tree;
00400 error:
00401    free_mi_tree(rpl_tree);
00402    return 0;
00403 }
00404 
00405 
00406 static struct mi_root* mi_set_prob(struct mi_root* cmd, void* param )
00407 {
00408    unsigned int percent;
00409    struct mi_node* node;
00410 
00411    node = cmd->node.kids;
00412    if(node == NULL)
00413       return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00414 
00415    if( str2int( &node->value, &percent) <0)
00416       goto error;
00417    if (percent > 100) {
00418       LM_ERR("incorrect probability <%u>\n", percent);
00419       goto error;
00420    }
00421    *probability = percent;
00422    return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00423 
00424 error:
00425    return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00426 }
00427 
00428 static struct mi_root* mi_reset_prob(struct mi_root* cmd, void* param )
00429 {
00430 
00431    *probability = initial_prob;
00432    return init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00433 }
00434 
00435 static struct mi_root* mi_get_prob(struct mi_root* cmd, void* param )
00436 {
00437    struct mi_root* rpl_tree= NULL;
00438    struct mi_node* node= NULL;
00439    rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00440    if(rpl_tree == NULL)
00441       return 0;
00442    node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "actual probability: %u percent\n",(*probability));
00443    if(node == NULL)
00444       goto error;
00445    
00446    return rpl_tree;
00447 
00448 error:
00449    free_mi_tree(rpl_tree);
00450    return 0;
00451 }
00452 
00453 static struct mi_root* mi_get_hash(struct mi_root* cmd, void* param )
00454 {
00455    struct mi_root* rpl_tree= NULL;
00456    struct mi_node* node= NULL;
00457 
00458    if (!hash_file) {
00459       LM_INFO("no hash_file given, disable hash functionality\n");
00460       rpl_tree = init_mi_tree(404, "Functionality disabled\n", 23);
00461    } else {
00462       rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00463       if(rpl_tree == NULL)
00464          return 0;
00465       node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%.*s\n", MD5_LEN, config_hash);
00466       if(node == NULL)
00467          goto error;
00468    }
00469    return rpl_tree;
00470 
00471 error:
00472    free_mi_tree(rpl_tree);
00473    return 0;
00474 }
00475 
00476 static struct mi_root* mi_check_hash(struct mi_root* cmd, void* param )
00477 {
00478    struct mi_root* rpl_tree= NULL;
00479    struct mi_node* node= NULL;
00480    char tmp[MD5_LEN];
00481    memset(tmp, 0, MD5_LEN);
00482 
00483    if (!hash_file) {
00484       LM_INFO("no hash_file given, disable hash functionality\n");
00485       rpl_tree = init_mi_tree(404, "Functionality disabled\n", 23);
00486    } else {
00487       if (MD5File(tmp, hash_file) != 0) {
00488          LM_ERR("could not hash the config file");
00489          rpl_tree = init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN );
00490       }
00491       
00492       if (strncmp(config_hash, tmp, MD5_LEN) == 0) {
00493          rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00494          if(rpl_tree == NULL)
00495             return 0;
00496          node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "The actual config file hash is identical to the stored one.\n");
00497       } else {
00498          rpl_tree = init_mi_tree( 400, "Error", 5 );
00499          if(rpl_tree == NULL)
00500             return 0;
00501          node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "The actual config file hash is not identical to the stored one.\n");
00502       }
00503       if(node == NULL)
00504          goto error;
00505    }
00506    
00507    return rpl_tree;
00508 
00509 error:
00510    free_mi_tree(rpl_tree);
00511    return 0;
00512 }
00513 
00514 static int set_prob(struct sip_msg *bar, char *percent_par, char *foo) 
00515 {
00516    *probability=(int)(long)percent_par;
00517    return 1;
00518 }
00519    
00520 static int reset_prob(struct sip_msg *bar, char *percent_par, char *foo)
00521 {
00522    *probability=initial_prob;
00523    return 1;
00524 }
00525 
00526 static int get_prob(struct sip_msg *bar, char *foo1, char *foo2)
00527 {
00528    return *probability;
00529 }
00530 
00531 static int rand_event(struct sip_msg *bar, char *foo1, char *foo2)
00532 {
00533    /* most of the time this will be disabled completly. Tis will also fix the
00534     * problem with the corner cases if rand() returned zero or RAND_MAX */
00535    if ((*probability) == 0) return -1;
00536    if ((*probability) == 100) return 1;
00537 
00538    double tmp = ((double) rand() / RAND_MAX);
00539    LM_DBG("generated random %f\n", tmp);
00540    if (tmp < ((double) (*probability) / 100)) {
00541       LM_DBG("return true\n");
00542       return 1;
00543    }
00544    else {
00545       LM_DBG("return false\n");
00546       return -1;
00547    }
00548 }
00549 
00550 static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
00551       pv_value_t *res)
00552 {
00553    int n;
00554    int l = 0;
00555    char *ch;
00556 
00557    if(msg==NULL || res==NULL)
00558       return -1;
00559 
00560    n = rand();
00561    ch = int2str(n , &l);
00562    res->rs.s = ch;
00563    res->rs.len = l;
00564    res->ri = n;
00565    res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00566 
00567    return 0;
00568 }
00569 
00570 static int m_sleep(struct sip_msg *msg, char *time, char *str2)
00571 {
00572    LM_DBG("sleep %lu seconds\n", (unsigned long)time);
00573    sleep((unsigned int)(unsigned long)time);
00574    return 1;
00575 }
00576 
00577 static int m_usleep(struct sip_msg *msg, char *time, char *str2)
00578 {
00579    LM_DBG("sleep %lu microseconds\n", (unsigned long)time);
00580    sleep_us((unsigned int)(unsigned long)time);
00581    return 1;
00582 }
00583 
00584 static int dbg_abort(struct sip_msg* msg, char* foo, char* bar)
00585 {
00586    LM_CRIT("abort called\n");
00587    abort();
00588    return 0;
00589 }
00590 
00591 static int dbg_pkg_status(struct sip_msg* msg, char* foo, char* bar)
00592 {
00593    pkg_status();
00594    return 1;
00595 }
00596 
00597 static int dbg_shm_status(struct sip_msg* msg, char* foo, char* bar)
00598 {
00599    shm_status();
00600    return 1;
00601 }
00602 
00603 int cfg_lock_helper(struct sip_msg *msg, gparam_p key, int mode)
00604 {
00605    str s;
00606    unsigned int pos;
00607    if(fixup_get_svalue(msg, key, &s)!=0)
00608    {
00609       LM_ERR("cannot get first parameter\n");
00610       return -1;
00611    }
00612    pos = core_case_hash(&s, 0, _cfg_lock_size);
00613    LM_DBG("cfg_lock mode %d on %u\n", mode, pos);
00614    if(mode==0)
00615       lock_set_get(_cfg_lock_set, pos);
00616    else
00617       lock_set_release(_cfg_lock_set, pos);
00618    return 1;
00619 }
00620 
00621 static int cfg_lock(struct sip_msg *msg, char *key, char *s2)
00622 {
00623    if(_cfg_lock_set==NULL || key==NULL)
00624       return -1;
00625    return cfg_lock_helper(msg, (gparam_p)key, 0);
00626 }
00627 
00628 static int cfg_unlock(struct sip_msg *msg, char *key, char *s2)
00629 {
00630    if(_cfg_lock_set==NULL || key==NULL)
00631       return -1;
00632    return cfg_lock_helper(msg, (gparam_p)key, 1);
00633 }
00634 
00635 
00636 static int mod_init(void)
00637 {
00638    if (!hash_file) {
00639       LM_INFO("no hash_file given, disable hash functionality\n");
00640    } else {
00641       if (MD5File(config_hash, hash_file) != 0) {
00642          LM_ERR("could not hash the config file");
00643          return -1;
00644       }
00645       LM_DBG("config file hash is %.*s", MD5_LEN, config_hash);
00646    }
00647 
00648    if (initial_prob > 100) {
00649       LM_ERR("invalid probability <%d>\n", initial_prob);
00650       return -1;
00651    }
00652    LM_DBG("initial probability %d percent\n", initial_prob);
00653 
00654    probability=(int *) shm_malloc(sizeof(int));
00655 
00656    if (!probability) {
00657       LM_ERR("no shmem available\n");
00658       return -1;
00659    }
00660    *probability = initial_prob;
00661 
00662    gflags=(unsigned int *) shm_malloc(sizeof(unsigned int));
00663    if (!gflags) {
00664       LM_ERR(" no shmem available\n");
00665       return -1;
00666    }
00667    *gflags=initial_gflags;
00668    if(_cfg_lock_size>0 && _cfg_lock_size<=10)
00669    {
00670       _cfg_lock_size = 1<<_cfg_lock_size;
00671       _cfg_lock_set = lock_set_alloc(_cfg_lock_size);
00672       if(_cfg_lock_set==NULL || lock_set_init(_cfg_lock_set)==NULL)
00673       {
00674          LM_ERR("cannot initiate lock set\n");
00675          return -1;
00676       }
00677    }
00678    return 0;
00679 }
00680 
00681 
00682 static void mod_destroy(void)
00683 {
00684    if (probability)
00685       shm_free(probability);
00686    if (gflags)
00687       shm_free(gflags);
00688    if(_cfg_lock_set!=NULL)
00689    {
00690       lock_set_destroy(_cfg_lock_set);
00691       lock_set_dealloc(_cfg_lock_set);
00692    }
00693 }

Generated on Mon May 21 16:00:24 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6