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
00036 #include <stdlib.h>
00037 #include <string.h>
00038
00039 #include "../../dprint.h"
00040 #include "../../ut.h"
00041 #include "../../lib/srdb1/db.h"
00042 #include "../../re.h"
00043 #include "dp_db.h"
00044 #include "dialplan.h"
00045
00046 str dp_db_url = {DEFAULT_RODB_URL, DEFAULT_RODB_URL_LEN};
00047 str dp_table_name = str_init(DP_TABLE_NAME);
00048 str dpid_column = str_init(DPID_COL);
00049 str pr_column = str_init(PR_COL);
00050 str match_op_column = str_init(MATCH_OP_COL);
00051 str match_exp_column= str_init(MATCH_EXP_COL);
00052 str match_len_column= str_init(MATCH_LEN_COL);
00053 str subst_exp_column= str_init(SUBST_EXP_COL);
00054 str repl_exp_column = str_init(REPL_EXP_COL);
00055 str attrs_column = str_init(ATTRS_COL);
00056
00057 extern int dp_fetch_rows;
00058
00059 static db1_con_t* dp_db_handle = 0;
00060 static db_func_t dp_dbf;
00061
00062 #define GET_STR_VALUE(_res, _values, _index)\
00063 do{\
00064 if ( VAL_NULL((_values)+ (_index)) ) { \
00065 LM_ERR(" values %d is NULL - not allowed\n",_index);\
00066 (_res).s = 0; (_res).len = 0;\
00067 goto err;\
00068 } \
00069 (_res).s = VAL_STR((_values)+ (_index)).s;\
00070 (_res).len = strlen(VAL_STR((_values)+ (_index)).s);\
00071 }while(0);
00072
00073 void destroy_rule(dpl_node_t * rule);
00074 void destroy_hash(int);
00075
00076 dpl_node_t * build_rule(db_val_t * values);
00077 int add_rule2hash(dpl_node_t *, int);
00078
00079 void list_rule(dpl_node_t * );
00080 void list_hash(int h_index);
00081
00082
00083 dpl_id_p* rules_hash = NULL;
00084 int * crt_idx, *next_idx;
00085
00086
00087
00088 int init_db_data(void)
00089 {
00090 if(dp_table_name.s == 0){
00091 LM_ERR("invalid database table name\n");
00092 return -1;
00093 }
00094
00095
00096 if (db_bind_mod(&dp_db_url, &dp_dbf) < 0){
00097 LM_ERR("unable to bind to a database driver\n");
00098 return -1;
00099 }
00100
00101 if(dp_connect_db() !=0)
00102 return -1;
00103
00104 if(db_check_table_version(&dp_dbf, dp_db_handle, &dp_table_name,
00105 DP_TABLE_VERSION) < 0) {
00106 LM_ERR("error during table version check.\n");
00107 goto error;
00108 }
00109
00110 if(dp_load_db() != 0){
00111 LM_ERR("failed to load database data\n");
00112 goto error;
00113 }
00114
00115 dp_disconnect_db();
00116
00117 return 0;
00118 error:
00119
00120 dp_disconnect_db();
00121 return -1;
00122 }
00123
00124
00125 int dp_connect_db(void)
00126 {
00127 if (dp_dbf.init==0){
00128 LM_CRIT("null dp_dbf\n");
00129 return -1;
00130 }
00131
00132 if(dp_db_handle){
00133 LM_CRIT("BUG: connection to database already open\n");
00134 return -1;
00135 }
00136
00137 if ((dp_db_handle = dp_dbf.init(&dp_db_url)) == 0){
00138 LM_ERR("unable to connect to the database\n");
00139 return -1;
00140 }
00141
00142 return 0;
00143 }
00144
00145
00146 void dp_disconnect_db(void)
00147 {
00148 if(dp_db_handle){
00149 dp_dbf.close(dp_db_handle);
00150 dp_db_handle = 0;
00151 }
00152 }
00153
00154
00155 int init_data(void)
00156 {
00157 int *p;
00158
00159 rules_hash = (dpl_id_p *)shm_malloc(2*sizeof(dpl_id_p));
00160 if(!rules_hash) {
00161 LM_ERR("out of shm memory\n");
00162 return -1;
00163 }
00164 rules_hash[0] = rules_hash[1] = 0;
00165
00166 p = (int *)shm_malloc(2*sizeof(int));
00167 if(!p){
00168 LM_ERR("out of shm memory\n");
00169 return -1;
00170 }
00171 crt_idx = p;
00172 next_idx = p+1;
00173 *crt_idx = *next_idx = 0;
00174
00175 LM_DBG("trying to initialize data from db\n");
00176 if(init_db_data() != 0)
00177 return -1;
00178
00179 return 0;
00180 }
00181
00182
00183 void destroy_data(void)
00184 {
00185 if(rules_hash){
00186 destroy_hash(0);
00187 destroy_hash(1);
00188 shm_free(rules_hash);
00189 rules_hash = 0;
00190 }
00191
00192 if(crt_idx)
00193 shm_free(crt_idx);
00194 }
00195
00196
00197
00198 int dp_load_db(void)
00199 {
00200 int i, nr_rows;
00201 db1_res_t * res = 0;
00202 db_val_t * values;
00203 db_row_t * rows;
00204 db_key_t query_cols[DP_TABLE_COL_NO] = {
00205 &dpid_column, &pr_column,
00206 &match_op_column, &match_exp_column, &match_len_column,
00207 &subst_exp_column, &repl_exp_column, &attrs_column };
00208
00209 db_key_t order = &pr_column;
00210
00211 dpl_node_t *rule;
00212
00213 LM_DBG("init\n");
00214 if( (*crt_idx) != (*next_idx)){
00215 LM_WARN("a load command already generated, aborting reload...\n");
00216 return 0;
00217 }
00218
00219 if (dp_dbf.use_table(dp_db_handle, &dp_table_name) < 0){
00220 LM_ERR("error in use_table %.*s\n", dp_table_name.len, dp_table_name.s);
00221 return -1;
00222 }
00223
00224 if (DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) {
00225 if(dp_dbf.query(dp_db_handle,0,0,0,query_cols, 0,
00226 DP_TABLE_COL_NO, order, 0) < 0){
00227 LM_ERR("failed to query database!\n");
00228 return -1;
00229 }
00230 if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows)<0) {
00231 LM_ERR("failed to fetch\n");
00232 if (res)
00233 dp_dbf.free_result(dp_db_handle, res);
00234 return -1;
00235 }
00236 } else {
00237
00238 if(dp_dbf.query(dp_db_handle,0,0,0,query_cols, 0,
00239 DP_TABLE_COL_NO, order, &res) < 0){
00240 LM_ERR("failed to query database\n");
00241 return -1;
00242 }
00243 }
00244
00245 nr_rows = RES_ROW_N(res);
00246
00247 *next_idx = ((*crt_idx) == 0)? 1:0;
00248 destroy_hash(*next_idx);
00249
00250 if(nr_rows == 0){
00251 LM_WARN("no data in the db\n");
00252 goto end;
00253 }
00254
00255 do {
00256 for(i=0; i<RES_ROW_N(res); i++){
00257 rows = RES_ROWS(res);
00258
00259 values = ROW_VALUES(rows+i);
00260
00261 if((rule = build_rule(values)) ==0 )
00262 goto err2;
00263
00264 if(add_rule2hash(rule , *next_idx) != 0)
00265 goto err2;
00266
00267 }
00268 if (DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) {
00269 if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows)<0) {
00270 LM_ERR("failure while fetching!\n");
00271 if (res)
00272 dp_dbf.free_result(dp_db_handle, res);
00273 return -1;
00274 }
00275 } else {
00276 break;
00277 }
00278 } while(RES_ROW_N(res)>0);
00279
00280
00281 end:
00282
00283 *crt_idx = *next_idx;
00284 list_hash(*crt_idx);
00285 dp_dbf.free_result(dp_db_handle, res);
00286 return 0;
00287
00288 err2:
00289 if(rule) destroy_rule(rule);
00290 destroy_hash(*next_idx);
00291 dp_dbf.free_result(dp_db_handle, res);
00292 *next_idx = *crt_idx;
00293 return -1;
00294 }
00295
00296
00297 int str_to_shm(str src, str * dest)
00298 {
00299 if(src.len ==0 || src.s ==0)
00300 return 0;
00301
00302 dest->s = (char*)shm_malloc((src.len+1) * sizeof(char));
00303 if(!dest->s){
00304 LM_ERR("out of shm memory\n");
00305 return -1;
00306 }
00307
00308 memcpy(dest->s, src.s, src.len);
00309 dest->s[src.len] = '\0';
00310 dest->len = src.len;
00311
00312 return 0;
00313 }
00314
00315
00316
00317 static pcre *reg_ex_comp(const char *pattern, int *cap_cnt)
00318 {
00319 pcre *re, *result;
00320 const char *error;
00321 int rc, err_offset;
00322 size_t size;
00323
00324 re = pcre_compile(pattern, 0, &error, &err_offset, NULL);
00325 if (re == NULL) {
00326 LM_ERR("PCRE compilation of '%s' failed at offset %d: %s\n",
00327 pattern, err_offset, error);
00328 return (pcre *)0;
00329 }
00330 rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
00331 if (rc != 0) {
00332 pcre_free(re);
00333 LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
00334 pattern, rc);
00335 return (pcre *)0;
00336 }
00337 rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, cap_cnt);
00338 if (rc != 0) {
00339 pcre_free(re);
00340 LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
00341 pattern, rc);
00342 return (pcre *)0;
00343 }
00344 result = (pcre *)shm_malloc(size);
00345 if (result == NULL) {
00346 pcre_free(re);
00347 LM_ERR("not enough shared memory for compiled PCRE pattern\n");
00348 return (pcre *)0;
00349 }
00350 memcpy(result, re, size);
00351 pcre_free(re);
00352 return result;
00353 }
00354
00355
00356
00357 dpl_node_t * build_rule(db_val_t * values)
00358 {
00359 pcre *match_comp, *subst_comp;
00360 struct subst_expr *repl_comp;
00361 dpl_node_t * new_rule;
00362 str match_exp, subst_exp, repl_exp, attrs;
00363 int matchop, cap_cnt;
00364
00365 matchop = VAL_INT(values+2);
00366
00367 if((matchop != DP_REGEX_OP) && (matchop!=DP_EQUAL_OP)
00368 && (matchop!=DP_FNMATCH_OP)){
00369 LM_ERR("invalid value for match operator\n");
00370 return NULL;
00371 }
00372
00373 match_comp = subst_comp =0;
00374 repl_comp = 0;
00375 new_rule = 0;
00376
00377 GET_STR_VALUE(match_exp, values, 3);
00378 if(matchop == DP_REGEX_OP){
00379 match_comp = reg_ex_comp(match_exp.s, &cap_cnt);
00380 if(!match_comp){
00381 LM_ERR("failed to compile match expression %.*s\n",
00382 match_exp.len, match_exp.s);
00383 goto err;
00384 }
00385 }
00386
00387 LM_DBG("build_rule\n");
00388 GET_STR_VALUE(repl_exp, values, 6);
00389 if(repl_exp.len && repl_exp.s){
00390 repl_comp = repl_exp_parse(repl_exp);
00391 if(!repl_comp){
00392 LM_ERR("failed to compile replacing expression %.*s\n",
00393 repl_exp.len, repl_exp.s);
00394 goto err;
00395 }
00396 }
00397
00398 GET_STR_VALUE(subst_exp, values, 5);
00399 if(subst_exp.s && subst_exp.len){
00400 subst_comp = reg_ex_comp(subst_exp.s, &cap_cnt);
00401 if(!subst_comp){
00402 LM_ERR("failed to compile subst expression %.*s\n",
00403 subst_exp.len, subst_exp.s);
00404 goto err;
00405 }
00406 if (cap_cnt > MAX_REPLACE_WITH) {
00407 LM_ERR("subst expression %.*s has too many sub-expressions\n",
00408 subst_exp.len, subst_exp.s);
00409 goto err;
00410 }
00411 }
00412
00413 if (repl_comp && (cap_cnt < repl_comp->max_pmatch) &&
00414 (repl_comp->max_pmatch != 0)) {
00415 LM_ERR("repl_exp %.*s refers to %d sub-expressions, but "
00416 "subst_exp %.*s has only %d\n",
00417 repl_exp.len, repl_exp.s, repl_comp->max_pmatch,
00418 subst_exp.len, subst_exp.s, cap_cnt);
00419 goto err;
00420 }
00421
00422 new_rule = (dpl_node_t *)shm_malloc(sizeof(dpl_node_t));
00423 if(!new_rule){
00424 LM_ERR("out of shm memory(new_rule)\n");
00425 goto err;
00426 }
00427 memset(new_rule, 0, sizeof(dpl_node_t));
00428
00429 if(str_to_shm(match_exp, &new_rule->match_exp)!=0)
00430 goto err;
00431
00432 if(str_to_shm(subst_exp, &new_rule->subst_exp)!=0)
00433 goto err;
00434
00435 if(str_to_shm(repl_exp, &new_rule->repl_exp)!=0)
00436 goto err;
00437
00438
00439 new_rule->dpid = VAL_INT(values);
00440 new_rule->pr = VAL_INT(values+1);
00441 new_rule->matchlen = VAL_INT(values+4);
00442 new_rule->matchop = matchop;
00443 GET_STR_VALUE(attrs, values, 7);
00444 if(str_to_shm(attrs, &new_rule->attrs)!=0)
00445 goto err;
00446
00447 LM_DBG("attrs are %.*s\n", new_rule->attrs.len, new_rule->attrs.s);
00448
00449 new_rule->match_comp = match_comp;
00450 new_rule->subst_comp = subst_comp;
00451 new_rule->repl_comp = repl_comp;
00452
00453 return new_rule;
00454
00455 err:
00456 if(match_comp) shm_free(match_comp);
00457 if(subst_comp) shm_free(subst_comp);
00458 if(repl_comp) repl_expr_free(repl_comp);
00459 if(new_rule) destroy_rule(new_rule);
00460 return NULL;
00461 }
00462
00463
00464 int add_rule2hash(dpl_node_t * rule, int h_index)
00465 {
00466 dpl_id_p crt_idp, last_idp;
00467 dpl_index_p indexp, last_indexp, new_indexp;
00468 int new_id;
00469
00470 if(!rules_hash){
00471 LM_ERR("data not allocated\n");
00472 return -1;
00473 }
00474
00475 new_id = 0;
00476
00477
00478 for(crt_idp = last_idp =rules_hash[h_index]; crt_idp!= NULL;
00479 last_idp = crt_idp, crt_idp = crt_idp->next)
00480 if(crt_idp->dp_id == rule->dpid)
00481 break;
00482
00483
00484 if(!crt_idp){
00485 crt_idp = (dpl_id_t*)shm_malloc(sizeof(dpl_id_t));
00486 if(!crt_idp){
00487 LM_ERR("out of shm memory (crt_idp)\n");
00488 return -1;
00489 }
00490 memset(crt_idp, 0, sizeof(dpl_id_t));
00491 crt_idp->dp_id = rule->dpid;
00492 new_id = 1;
00493 LM_DBG("new dpl_id %i\n", rule->dpid);
00494 }
00495
00496
00497 for(indexp = last_indexp =crt_idp->first_index; indexp!=NULL;
00498 last_indexp = indexp, indexp = indexp->next){
00499 if(indexp->len == rule->matchlen)
00500 goto add_rule;
00501 if((rule->matchlen!=0)&&((indexp->len)?(indexp->len>rule->matchlen):1))
00502 goto add_index;
00503 }
00504
00505 add_index:
00506 LM_DBG("new index , len %i\n", rule->matchlen);
00507
00508 new_indexp = (dpl_index_t *)shm_malloc(sizeof(dpl_index_t));
00509 if(!new_indexp){
00510 LM_ERR("out of shm memory\n");
00511 goto err;
00512 }
00513 memset(new_indexp , 0, sizeof(dpl_index_t));
00514 new_indexp->next = indexp;
00515 new_indexp->len = rule->matchlen;
00516
00517
00518 if(last_indexp == indexp){
00519 crt_idp->first_index = new_indexp;
00520 }else{
00521 last_indexp->next = new_indexp;
00522 }
00523
00524 indexp = new_indexp;
00525
00526 add_rule:
00527 rule->next = 0;
00528 if(!indexp->first_rule)
00529 indexp->first_rule = rule;
00530
00531 if(indexp->last_rule)
00532 indexp->last_rule->next = rule;
00533
00534 indexp->last_rule = rule;
00535
00536 if(new_id){
00537 crt_idp->next = rules_hash[h_index];
00538 rules_hash[h_index] = crt_idp;
00539 }
00540 LM_DBG("added the rule id %i index %i pr %i next %p to the "
00541 "index with %i len\n", rule->dpid, rule->matchlen,
00542 rule->pr, rule->next, indexp->len);
00543
00544 return 0;
00545
00546 err:
00547 if(new_id)
00548 shm_free(crt_idp);
00549 return -1;
00550 }
00551
00552
00553 void destroy_hash(int index)
00554 {
00555 dpl_id_p crt_idp;
00556 dpl_index_p indexp;
00557 dpl_node_p rulep;
00558
00559 if(!rules_hash[index])
00560 return;
00561
00562 for(crt_idp = rules_hash[index]; crt_idp != NULL;){
00563
00564 for(indexp = crt_idp->first_index; indexp != NULL;){
00565
00566 for(rulep = indexp->first_rule; rulep!= NULL;){
00567
00568 destroy_rule(rulep);
00569
00570 indexp->first_rule = rulep->next;
00571 shm_free(rulep);
00572 rulep=0;
00573 rulep= indexp->first_rule;
00574 }
00575 crt_idp->first_index= indexp->next;
00576 shm_free(indexp);
00577 indexp=0;
00578 indexp = crt_idp->first_index;
00579
00580 }
00581
00582 rules_hash[index] = crt_idp->next;
00583 shm_free(crt_idp);
00584 crt_idp = 0;
00585 crt_idp = rules_hash[index];
00586 }
00587
00588 rules_hash[index] = 0;
00589 }
00590
00591
00592 void destroy_rule(dpl_node_t * rule){
00593
00594 if(!rule)
00595 return;
00596
00597 LM_DBG("destroying rule with priority %i\n",
00598 rule->pr);
00599
00600 if(rule->match_comp)
00601 shm_free(rule->match_comp);
00602
00603 if(rule->subst_comp)
00604 shm_free(rule->subst_comp);
00605
00606
00607 if(rule->repl_comp)
00608 repl_expr_free(rule->repl_comp);
00609
00610 if(rule->match_exp.s)
00611 shm_free(rule->match_exp.s);
00612
00613 if(rule->subst_exp.s)
00614 shm_free(rule->subst_exp.s);
00615
00616 if(rule->repl_exp.s)
00617 shm_free(rule->repl_exp.s);
00618
00619 if(rule->attrs.s)
00620 shm_free(rule->attrs.s);
00621 }
00622
00623
00624 dpl_id_p select_dpid(int id)
00625 {
00626 dpl_id_p idp;
00627
00628 if(!rules_hash || !crt_idx)
00629 return NULL;
00630
00631 for(idp = rules_hash[*crt_idx]; idp!=NULL; idp = idp->next)
00632 if(idp->dp_id == id)
00633 return idp;
00634
00635 return NULL;
00636 }
00637
00638
00639
00640 void list_hash(int h_index)
00641 {
00642 dpl_id_p crt_idp;
00643 dpl_index_p indexp;
00644 dpl_node_p rulep;
00645
00646
00647 if(!rules_hash[h_index])
00648 return;
00649
00650 for(crt_idp=rules_hash[h_index]; crt_idp!=NULL; crt_idp = crt_idp->next){
00651 LM_DBG("DPID: %i, pointer %p\n", crt_idp->dp_id, crt_idp);
00652 for(indexp=crt_idp->first_index; indexp!=NULL;indexp= indexp->next){
00653 LM_DBG("INDEX LEN: %i\n", indexp->len);
00654 for(rulep = indexp->first_rule; rulep!= NULL;rulep = rulep->next){
00655 list_rule(rulep);
00656 }
00657 }
00658 }
00659 }
00660
00661
00662 void list_rule(dpl_node_t * rule)
00663 {
00664 LM_DBG("RULE %p: pr %i next %p op %d match_exp %.*s, "
00665 "subst_exp %.*s, repl_exp %.*s and attrs %.*s\n", rule,
00666 rule->pr, rule->next,
00667 rule->matchop,
00668 rule->match_exp.len, rule->match_exp.s,
00669 rule->subst_exp.len, rule->subst_exp.s,
00670 rule->repl_exp.len, rule->repl_exp.s,
00671 rule->attrs.len, rule->attrs.s);
00672
00673 }