00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <math.h>
00035 #include "../../sr_module.h"
00036 #include "../../db/db.h"
00037 #include "../../dprint.h"
00038 #include "../../error.h"
00039 #include "../../ut.h"
00040 #include "../../action.h"
00041 #include "../../pvar.h"
00042 #include "../../dset.h"
00043 #include "../../mem/mem.h"
00044 #include "../../mi/mi.h"
00045 #include "../../parser/parse_to.h"
00046 #include "dialplan.h"
00047 #include "dp_db.h"
00048
00049 MODULE_VERSION
00050
00051 #define DEFAULT_PARAM "$ruri.user"
00052
00053 static int mod_init(void);
00054 static int child_init(int rank);
00055 static void mod_destroy();
00056 static int mi_child_init();
00057
00058 static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree,void *param);
00059 static struct mi_root * mi_translate(struct mi_root *cmd_tree, void *param);
00060 static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2);
00061 static int dp_trans_fixup(void ** param, int param_no);
00062
00063 str attr_pvar_s = {NULL,0};
00064 pv_spec_t * attr_pvar = NULL;
00065
00066 str default_param_s = str_init(DEFAULT_PARAM);
00067 dp_param_p default_par2 = NULL;
00068
00069 int dp_fetch_rows = 1000;
00070
00071 static param_export_t mod_params[]={
00072 { "db_url", STR_PARAM, &dp_db_url.s },
00073 { "table_name", STR_PARAM, &dp_table_name.s },
00074 { "dpid_col", STR_PARAM, &dpid_column.s },
00075 { "pr_col", STR_PARAM, &pr_column.s },
00076 { "match_op_col", STR_PARAM, &match_op_column.s },
00077 { "match_exp_col", STR_PARAM, &match_exp_column.s },
00078 { "match_len_col", STR_PARAM, &match_len_column.s },
00079 { "subst_exp_col", STR_PARAM, &subst_exp_column.s },
00080 { "repl_exp_col", STR_PARAM, &repl_exp_column.s },
00081 { "attrs_col", STR_PARAM, &attrs_column.s },
00082 { "attrs_pvar", STR_PARAM, &attr_pvar_s.s},
00083 { "attribute_pvar", STR_PARAM, &attr_pvar_s.s},
00084 { "fetch_rows", INT_PARAM, &dp_fetch_rows},
00085 {0,0,0}
00086 };
00087
00088 static mi_export_t mi_cmds[] = {
00089 { "dp_reload", mi_reload_rules, MI_NO_INPUT_FLAG, 0, mi_child_init},
00090 { "dp_translate", mi_translate, 0, 0, 0},
00091 { 0, 0, 0, 0, 0}
00092 };
00093
00094 static cmd_export_t cmds[]={
00095 {"dp_translate",(cmd_function)dp_translate_f, 2, dp_trans_fixup, 0,
00096 REQUEST_ROUTE|FAILURE_ROUTE|LOCAL_ROUTE|BRANCH_ROUTE},
00097 {"dp_translate",(cmd_function)dp_translate_f, 1, dp_trans_fixup, 0,
00098 REQUEST_ROUTE|FAILURE_ROUTE|LOCAL_ROUTE|BRANCH_ROUTE},
00099 {0,0,0,0,0,0}
00100 };
00101
00102 struct module_exports exports= {
00103 "dialplan",
00104 DEFAULT_DLFLAGS,
00105 cmds,
00106 mod_params,
00107 0,
00108 mi_cmds,
00109 0,
00110 0,
00111 mod_init,
00112 0,
00113 mod_destroy,
00114 child_init
00115 };
00116
00117
00118 static int mod_init(void)
00119 {
00120 dp_db_url.len = dp_db_url.s ? strlen(dp_db_url.s) : 0;
00121 LM_DBG("db_url=%s/%d/%p\n", ZSW(dp_db_url.s), dp_db_url.len,dp_db_url.s);
00122 dp_table_name.len = strlen(dp_table_name.s);
00123 dpid_column.len = strlen( dpid_column.s);
00124 pr_column.len = strlen(pr_column.s);
00125 match_op_column.len = strlen(match_op_column.s);
00126 match_exp_column.len= strlen(match_exp_column.s);
00127 match_len_column.len= strlen(match_len_column.s);
00128 subst_exp_column.len= strlen(subst_exp_column.s);
00129 repl_exp_column.len = strlen(repl_exp_column.s);
00130 attrs_column.len = strlen(attrs_column.s);
00131
00132 if(attr_pvar_s.s) {
00133 attr_pvar = (pv_spec_t *)shm_malloc(sizeof(pv_spec_t));
00134 if(!attr_pvar){
00135 LM_ERR("out of shm memory\n");
00136 return -1;
00137 }
00138
00139 attr_pvar_s.len = strlen(attr_pvar_s.s);
00140 if( (pv_parse_spec(&attr_pvar_s, attr_pvar)==NULL) ||
00141 ((attr_pvar->type != PVT_AVP) && (attr_pvar->type!=PVT_SCRIPTVAR))) {
00142 LM_ERR("invalid pvar name\n");
00143 return -1;
00144 }
00145 }
00146
00147 default_par2 = (dp_param_p)shm_malloc(sizeof(dp_param_t));
00148 if(default_par2 == NULL){
00149 LM_ERR("no shm more memory\n");
00150 return -1;
00151 }
00152 memset(default_par2, 0, sizeof(dp_param_t));
00153
00154 default_param_s.len = strlen(default_param_s.s);
00155 if (pv_parse_spec( &default_param_s, &default_par2->v.sp[0])==NULL) {
00156 LM_ERR("input pv is invalid\n");
00157 return -1;
00158 }
00159
00160 default_param_s.len = strlen(default_param_s.s);
00161 if (pv_parse_spec( &default_param_s, &default_par2->v.sp[1])==NULL) {
00162 LM_ERR("output pv is invalid\n");
00163 return -1;
00164 }
00165
00166 if(init_data() != 0) {
00167 LM_ERR("could not initialize data\n");
00168 return -1;
00169 }
00170
00171 if(dp_fetch_rows<=0)
00172 dp_fetch_rows = 1000;
00173
00174 return 0;
00175 }
00176
00177
00178 static int child_init(int rank)
00179 {
00180 if(rank>0)
00181 return dp_connect_db();
00182 return 0;
00183 }
00184
00185
00186 static void mod_destroy(void)
00187 {
00188
00189 if(default_par2){
00190 shm_free(default_par2);
00191 default_par2 = NULL;
00192 }
00193 if(attr_pvar){
00194 shm_free(attr_pvar);
00195 attr_pvar = NULL;
00196 }
00197 destroy_data();
00198
00199
00200 dp_disconnect_db();
00201 }
00202
00203
00204 static int mi_child_init(void)
00205 {
00206 return dp_connect_db();
00207 }
00208
00209
00210 static int dp_get_ivalue(struct sip_msg* msg, dp_param_p dp, int *val)
00211 {
00212 pv_value_t value;
00213
00214 if(dp->type==DP_VAL_INT) {
00215 LM_DBG("integer value\n");
00216 *val = dp->v.id;
00217 return 0;
00218 }
00219
00220 LM_DBG("searching %d\n",dp->v.sp[0].type);
00221
00222 if( pv_get_spec_value( msg, &dp->v.sp[0], &value)!=0
00223 || value.flags&(PV_VAL_NULL|PV_VAL_EMPTY) || !(value.flags&PV_VAL_INT)) {
00224 LM_ERR("no AVP or SCRIPTVAR found (error in scripts)\n");
00225 return -1;
00226 }
00227 *val = value.ri;
00228 return 0;
00229 }
00230
00231
00232 static int dp_get_svalue(struct sip_msg * msg, pv_spec_t spec, str* val)
00233 {
00234 pv_value_t value;
00235
00236 LM_DBG("searching %d \n", spec.type);
00237
00238 if ( pv_get_spec_value(msg,&spec,&value)!=0 || value.flags&PV_VAL_NULL
00239 || value.flags&PV_VAL_EMPTY || !(value.flags&PV_VAL_STR)){
00240 LM_ERR("no AVP or SCRIPTVAR found (error in scripts)\n");
00241 return -1;
00242 }
00243
00244 *val = value.rs;
00245 return 0;
00246 }
00247
00248
00249 static int dp_update(struct sip_msg * msg, pv_spec_t * src, pv_spec_t * dest,
00250 str * repl, str * attrs)
00251 {
00252 int no_change;
00253 pv_value_t val;
00254
00255 no_change = ((!repl->s) || (!repl->len)) && (src->type == dest->type)
00256 && ((src->type == PVT_RURI) || (src->type == PVT_RURI_USERNAME));
00257
00258 if (no_change)
00259 goto set_attr_pvar;
00260
00261 memset(&val, 0, sizeof(pv_value_t));
00262 val.flags = PV_VAL_STR;
00263 val.rs = *repl;
00264
00265 if(dest->setf(msg, &dest->pvp, (int)EQ_T, &val)<0)
00266 {
00267 LM_ERR("setting dst pseudo-variable failed\n");
00268 return -1;
00269 }
00270
00271 if(route_type==FAILURE_ROUTE
00272 && (dest->type==PVT_RURI || dest->type==PVT_RURI_USERNAME)) {
00273 if (append_branch(msg, 0, 0, 0, Q_UNSPECIFIED, 0, 0)!=1 ){
00274 LM_ERR("append_branch action failed\n");
00275 return -1;
00276 }
00277 }
00278
00279 set_attr_pvar:
00280
00281 if(!attr_pvar)
00282 return 0;
00283
00284 val.rs = *attrs;
00285 if(attr_pvar->setf(msg, &attr_pvar->pvp, (int)EQ_T, &val)<0)
00286 {
00287 LM_ERR("setting attr pseudo-variable failed\n");
00288 return -1;
00289 }
00290
00291 return 0;
00292 }
00293
00294
00295 static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2)
00296 {
00297 int dpid;
00298 str input, output;
00299 dpl_id_p idp;
00300 dp_param_p id_par, repl_par;
00301 str attrs, * attrs_par;
00302
00303 if(!msg)
00304 return -1;
00305
00306
00307 id_par = (dp_param_p) str1;
00308 if (dp_get_ivalue(msg, id_par, &dpid) != 0){
00309 LM_ERR("no dpid value\n");
00310 return -1;
00311 }
00312 LM_DBG("dpid is %i\n", dpid);
00313
00314 if ((idp = select_dpid(dpid)) ==0 ){
00315 LM_DBG("no information available for dpid %i\n", dpid);
00316 return -1;
00317 }
00318
00319 repl_par = (str2!=NULL)? ((dp_param_p)str2):default_par2;
00320 if (dp_get_svalue(msg, repl_par->v.sp[0], &input)!=0){
00321 LM_ERR("invalid param 2\n");
00322 return -1;
00323 }
00324
00325 LM_DBG("input is %.*s\n", input.len, input.s);
00326
00327 attrs_par = (!attr_pvar)?NULL:&attrs;
00328 if (translate(msg, input, &output, idp, attrs_par)!=0){
00329 LM_DBG("could not translate %.*s "
00330 "with dpid %i\n", input.len, input.s, idp->dp_id);
00331 return -1;
00332 }
00333 LM_DBG("input %.*s with dpid %i => output %.*s\n",
00334 input.len, input.s, idp->dp_id, output.len, output.s);
00335
00336
00337 if (dp_update(msg, &repl_par->v.sp[0], &repl_par->v.sp[1],
00338 &output, attrs_par) !=0){
00339 LM_ERR("cannot set the output\n");
00340 return -1;
00341 }
00342
00343 return 1;
00344
00345 }
00346
00347 #define verify_par_type(_par_no, _spec)\
00348 do{\
00349 if( ((_par_no == 1) \
00350 && ((_spec).type != PVT_AVP) && ((_spec).type!=PVT_SCRIPTVAR) )\
00351 ||((_par_no == 2) \
00352 && ((_spec).type != PVT_AVP) && ((_spec).type!=PVT_SCRIPTVAR) \
00353 && ((_spec).type!=PVT_RURI) && (_spec.type!=PVT_RURI_USERNAME))){\
00354 \
00355 LM_ERR("Unsupported Parameter TYPE\n");\
00356 return E_UNSPEC;\
00357 }\
00358 }while(0);
00359
00360
00361
00362
00363
00364
00365
00366 static int dp_trans_fixup(void ** param, int param_no){
00367
00368 int dpid, err;
00369 dp_param_p dp_par= NULL;
00370 char *p, *s=NULL;
00371 str lstr;
00372
00373 if(param_no!=1 && param_no!=2)
00374 return 0;
00375
00376 p = (char*)*param;
00377 if(!p || (*p == '\0')){
00378 LM_DBG("null param %i\n", param_no);
00379 return E_CFG;
00380 }
00381
00382 LM_DBG("param_no is %i\n", param_no);
00383
00384 dp_par = (dp_param_p)pkg_malloc(sizeof(dp_param_t));
00385 if(dp_par == NULL){
00386 LM_ERR("no more pkg memory\n");
00387 return E_OUT_OF_MEM;
00388 }
00389 memset(dp_par, 0, sizeof(dp_param_t));
00390
00391 if(param_no == 1) {
00392 if(*p != '$') {
00393 dp_par->type = DP_VAL_INT;
00394 dpid = str2s(*param, strlen(*param), &err);
00395 if (err != 0) {
00396 LM_ERR("bad number <%s>\n",(char *)(*param));
00397 pkg_free(dp_par);
00398 return E_CFG;
00399 }
00400
00401 dp_par->type = DP_VAL_INT;
00402 dp_par->v.id = dpid;
00403 }else{
00404 lstr.s = p; lstr.len = strlen(p);
00405 if (pv_parse_spec( &lstr, &dp_par->v.sp[0])==NULL)
00406 goto error;
00407
00408 verify_par_type(param_no, dp_par->v.sp[0]);
00409 dp_par->type = DP_VAL_SPEC;
00410 }
00411 } else {
00412 if( ((s = strchr(p, '/')) == 0) ||( *(s+1)=='\0'))
00413 goto error;
00414 *s = '\0'; s++;
00415
00416 lstr.s = p; lstr.len = strlen(p);
00417 if(pv_parse_spec( &lstr, &dp_par->v.sp[0])==NULL)
00418 goto error;
00419
00420 lstr.s = s; lstr.len = strlen(s);
00421 if (pv_parse_spec( &lstr, &dp_par->v.sp[1] )==NULL)
00422 goto error;
00423
00424 verify_par_type(param_no, dp_par->v.sp[1]);
00425
00426 dp_par->type = DP_VAL_SPEC;
00427 }
00428
00429 *param = (void *)dp_par;
00430
00431 return 0;
00432
00433 error:
00434 LM_ERR("failed to parse param %i\n", param_no);
00435 return E_INVALID_PARAMS;
00436 }
00437
00438
00439 static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree, void *param)
00440 {
00441 struct mi_root* rpl_tree= NULL;
00442
00443 if(dp_load_db() != 0){
00444 LM_ERR("failed to reload database data\n");
00445 return 0;
00446 }
00447
00448 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00449 if (rpl_tree==0)
00450 return 0;
00451
00452 return rpl_tree;
00453 }
00454
00455
00456
00457
00458
00459
00460
00461 static struct mi_root * mi_translate(struct mi_root *cmd, void *param)
00462 {
00463
00464 struct mi_root* rpl= NULL;
00465 struct mi_node* root, *node;
00466 dpl_id_p idp;
00467 str dpid_str;
00468 str input;
00469 int dpid;
00470 int err;
00471 str attrs;
00472 str output= {0, 0};
00473
00474 node = cmd->node.kids;
00475 if(node == NULL)
00476 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00477
00478
00479 dpid_str = node->value;
00480 if(dpid_str.s == NULL || dpid_str.len== 0) {
00481 LM_ERR( "empty idp parameter\n");
00482 return init_mi_tree(404, "Empty id parameter", 18);
00483 }
00484 dpid = str2s(dpid_str.s, dpid_str.len, &err);
00485 if(err != 0) {
00486 LM_ERR("Wrong id parameter - should be an integer\n");
00487 return init_mi_tree(404, "Wrong id parameter", 18);
00488 }
00489
00490 if ((idp = select_dpid(dpid)) ==0 ){
00491 LM_ERR("no information available for dpid %i\n", dpid);
00492 return init_mi_tree(404, "No information available for dpid", 33);
00493 }
00494
00495 node = node->next;
00496 if(node == NULL)
00497 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00498
00499 if(node->next!= NULL)
00500 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00501
00502 input= node->value;
00503 if(input.s == NULL || input.len== 0) {
00504 LM_ERR( "empty input parameter\n");
00505 return init_mi_tree(404, "Empty input parameter", 21);
00506 }
00507
00508 LM_DBG("input is %.*s\n", input.len, input.s);
00509
00510 if (translate(NULL, input, &output, idp, &attrs)!=0){
00511 LM_DBG("could not translate %.*s with dpid %i\n",
00512 input.len, input.s, idp->dp_id);
00513 return 0;
00514 }
00515 LM_DBG("input %.*s with dpid %i => output %.*s\n",
00516 input.len, input.s, idp->dp_id, output.len, output.s);
00517
00518 rpl = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00519 if (rpl==0)
00520 goto error;
00521
00522 root= &rpl->node;
00523
00524 node = add_mi_node_child(root, 0, "Output", 6, output.s, output.len );
00525 if( node == NULL)
00526 goto error;
00527
00528 node = add_mi_node_child(root, 0, "ATTRIBUTES", 10, attrs.s, attrs.len);
00529 if( node == NULL)
00530 goto error;
00531
00532 return rpl;
00533
00534 error:
00535 if(rpl)
00536 free_mi_tree(rpl);
00537 return 0;
00538 }
00539