/*compile the expressions, and if ok, build the rule */ dpl_node_t * build_rule(db_val_t * values) { tmrec_t *parsed_timerec; pcre * match_comp, *subst_comp; struct subst_expr * repl_comp; dpl_node_t * new_rule; str match_exp, subst_exp, repl_exp, attrs, timerec; int matchop; int namecount; matchop = VAL_INT(values+2); if((matchop != REGEX_OP) && (matchop!=EQUAL_OP)){ LM_ERR("invalid value for match operator\n"); return NULL; } parsed_timerec = 0; match_comp = subst_comp = 0; repl_comp = 0; new_rule = 0; GET_STR_VALUE(match_exp, values, 3); if(matchop == REGEX_OP){ LM_DBG("Compiling %.*s expression with flag: %d\n", match_exp.len, match_exp.s, VAL_INT(values+4)); match_comp = wrap_pcre_compile(match_exp.s, VAL_INT(values+4)); if(!match_comp){ LM_ERR("failed to compile match expression %.*s\n", match_exp.len, match_exp.s); goto err; } } LM_DBG("building subst rule\n"); GET_STR_VALUE(subst_exp, values, 5); if(subst_exp.s && subst_exp.len){ /* subst regexp */ subst_comp = wrap_pcre_compile(subst_exp.s, VAL_INT(values+4)); if(subst_comp == NULL){ LM_ERR("failed to compile subst expression\n"); goto err; } } /* replace exp */ GET_STR_VALUE(repl_exp, values, 6); if(repl_exp.len && repl_exp.s){ repl_comp = repl_exp_parse(repl_exp); if(!repl_comp){ LM_ERR("failed to compile replacing expression %.*s\n", repl_exp.len, repl_exp.s); goto err; } } pcre_fullinfo( subst_comp, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ PCRE_INFO_CAPTURECOUNT, /* number of named substrings */ &namecount); /* where to put the answer */ LM_DBG("references:%d , max:%d\n",namecount, repl_comp?repl_comp->max_pmatch:0); if ( (repl_comp!=NULL) && (namecount<repl_comp->max_pmatch) && (repl_comp->max_pmatch!=0) ){ LM_ERR("repl_exp uses a non existing subexpression\n"); goto err; } new_rule = (dpl_node_t *)shm_malloc(sizeof(dpl_node_t)); if(!new_rule){ LM_ERR("out of shm memory(new_rule)\n"); goto err; } memset(new_rule, 0, sizeof(dpl_node_t)); if(str_to_shm(match_exp, &new_rule->match_exp)!=0) goto err; if (subst_comp) if(str_to_shm(subst_exp, &new_rule->subst_exp)!=0) goto err; if (repl_comp) if(str_to_shm(repl_exp, &new_rule->repl_exp)!=0) goto err; /*set the rest of the rule fields*/ new_rule->dpid = VAL_INT(values); new_rule->pr = VAL_INT(values+1); new_rule->match_flags = VAL_INT(values+4); new_rule->matchop = matchop; GET_STR_VALUE(attrs, values, 7); if(str_to_shm(attrs, &new_rule->attrs)!=0) goto err; LM_DBG("attrs are %.*s\n", new_rule->attrs.len, new_rule->attrs.s); /* Retrieve and Parse Timerec Matching Pattern */ GET_STR_VALUE(timerec, values, 8); if(timerec.len && timerec.s) { parsed_timerec = parse_time_def(timerec.s); if(!parsed_timerec) { LM_ERR("failed to parse timerec pattern %.*s\n", timerec.len, timerec.s); goto err; } if(str_to_shm(timerec, &new_rule->timerec) != 0) goto err; new_rule->parsed_timerec = parsed_timerec; LM_DBG("timerecs are %.*s\n", new_rule->timerec.len, new_rule->timerec.s); } if (match_comp) new_rule->match_comp = match_comp; if (subst_comp) new_rule->subst_comp = subst_comp; if (repl_comp) new_rule->repl_comp = repl_comp; return new_rule; err: if(parsed_timerec) shm_free(parsed_timerec); if(match_comp) wrap_pcre_free(match_comp); if(subst_comp) wrap_pcre_free(subst_comp); if(repl_comp) repl_expr_free(repl_comp); if(new_rule) destroy_rule(new_rule); return NULL; }
/*compile the expressions, and if ok, build the rule */ dpl_node_t * build_rule(db_val_t * values) { pcre *match_comp, *subst_comp; struct subst_expr *repl_comp; dpl_node_t * new_rule; str match_exp, subst_exp, repl_exp, attrs; int matchop; int cap_cnt=0; unsigned int tflags=0; matchop = VAL_INT(values+2); if((matchop != DP_REGEX_OP) && (matchop!=DP_EQUAL_OP) && (matchop!=DP_FNMATCH_OP)){ LM_ERR("invalid value for match operator\n"); return NULL; } match_comp = subst_comp = 0; repl_comp = 0; new_rule = 0; GET_STR_VALUE(match_exp, values, 3); if(matchop == DP_REGEX_OP){ if(unlikely(dp_match_dynamic==1)) { if(dpl_check_pv(&match_exp)==0) { tflags |= DP_TFLAGS_PV_MATCH; } } if(!(tflags&DP_TFLAGS_PV_MATCH)) { match_comp = reg_ex_comp(match_exp.s, &cap_cnt, 0); if(!match_comp){ LM_ERR("failed to compile match expression %.*s\n", match_exp.len, match_exp.s); goto err; } } } GET_STR_VALUE(repl_exp, values, 6); if(repl_exp.len && repl_exp.s){ repl_comp = repl_exp_parse(repl_exp); if(!repl_comp){ LM_ERR("failed to compile replacing expression %.*s\n", repl_exp.len, repl_exp.s); goto err; } } cap_cnt = 0; GET_STR_VALUE(subst_exp, values, 5); if(subst_exp.s && subst_exp.len){ if(unlikely(dp_match_dynamic==1)) { if(dpl_check_pv(&subst_exp)==0) { tflags |= DP_TFLAGS_PV_SUBST; } } if(!(tflags&DP_TFLAGS_PV_SUBST)) { subst_comp = reg_ex_comp(subst_exp.s, &cap_cnt, 0); if(!subst_comp){ LM_ERR("failed to compile subst expression %.*s\n", subst_exp.len, subst_exp.s); goto err; } if (cap_cnt > MAX_REPLACE_WITH) { LM_ERR("subst expression %.*s has too many sub-expressions\n", subst_exp.len, subst_exp.s); goto err; } } } LM_DBG("building rule for [%d:%.*s/%.*s/%.*s]\n", matchop, match_exp.len, ZSW(match_exp.s), subst_exp.len, ZSW(subst_exp.s), repl_exp.len, ZSW(repl_exp.s)); if (!(tflags&(DP_TFLAGS_PV_SUBST|DP_TFLAGS_PV_MATCH)) && repl_comp && (cap_cnt < repl_comp->max_pmatch) && (repl_comp->max_pmatch != 0)) { LM_ERR("repl_exp %.*s refers to %d sub-expressions, but " "subst_exp %.*s has only %d\n", repl_exp.len, repl_exp.s, repl_comp->max_pmatch, subst_exp.len, subst_exp.s, cap_cnt); goto err; } new_rule = (dpl_node_t *)shm_malloc(sizeof(dpl_node_t)); if(!new_rule){ LM_ERR("out of shm memory(new_rule)\n"); goto err; } memset(new_rule, 0, sizeof(dpl_node_t)); if(dpl_str_to_shm(match_exp, &new_rule->match_exp, tflags&DP_TFLAGS_PV_MATCH)!=0) goto err; if(dpl_str_to_shm(subst_exp, &new_rule->subst_exp, tflags&DP_TFLAGS_PV_SUBST)!=0) goto err; if(dpl_str_to_shm(repl_exp, &new_rule->repl_exp, 0)!=0) goto err; /*set the rest of the rule fields*/ new_rule->dpid = VAL_INT(values); new_rule->pr = VAL_INT(values+1); new_rule->matchlen = VAL_INT(values+4); new_rule->matchop = matchop; GET_STR_VALUE(attrs, values, 7); if(dpl_str_to_shm(attrs, &new_rule->attrs, 0)!=0) goto err; LM_DBG("attrs are: '%.*s'\n", new_rule->attrs.len, new_rule->attrs.s); new_rule->match_comp = match_comp; new_rule->subst_comp = subst_comp; new_rule->repl_comp = repl_comp; new_rule->tflags = tflags; return new_rule; err: if(match_comp) shm_free(match_comp); if(subst_comp) shm_free(subst_comp); if(repl_comp) repl_expr_free(repl_comp); if(new_rule) destroy_rule(new_rule); return NULL; }
/*load rules from DB*/ int dp_load_db(dp_connection_list_p dp_conn) { int i, nr_rows; db_res_t * res = 0; db_val_t * values; db_row_t * rows; db_key_t query_cols[DP_TABLE_COL_NO] = { &dpid_column, &pr_column, &match_op_column, &match_exp_column, &match_flags_column, &subst_exp_column, &repl_exp_column, &attrs_column, &timerec_column }; db_key_t order = &pr_column; /* disabled condition */ db_key_t cond_cols[1] = { &disabled_column }; db_val_t cond_val[1]; dpl_node_t *rule; int no_rows = 10; lock_start_write( dp_conn->ref_lock ); if( dp_conn->crt_index != dp_conn->next_index){ LM_WARN("a load command already generated, aborting reload...\n"); lock_stop_write( dp_conn->ref_lock ); return 0; } dp_conn->next_index = dp_conn->crt_index == 0 ? 1 : 0; lock_stop_write( dp_conn->ref_lock ); if (dp_conn->dp_dbf.use_table(*dp_conn->dp_db_handle, &dp_conn->table_name) < 0){ LM_ERR("error in use_table\n"); goto err1; } VAL_TYPE(cond_val) = DB_INT; VAL_NULL(cond_val) = 0; VAL_INT(cond_val) = 0; if (DB_CAPABILITY(dp_conn->dp_dbf, DB_CAP_FETCH)) { if(dp_conn->dp_dbf.query(*dp_conn->dp_db_handle,cond_cols, 0,cond_val,query_cols,1, DP_TABLE_COL_NO, order, 0) < 0){ LM_ERR("failed to query database!\n"); goto err1; } no_rows = estimate_available_rows( 4+4+4+64+4+64+64+128, DP_TABLE_COL_NO); if (no_rows==0) no_rows = 10; if(dp_conn->dp_dbf.fetch_result(*dp_conn->dp_db_handle, &res, no_rows)<0) { LM_ERR("failed to fetch\n"); if (res) dp_conn->dp_dbf.free_result(*dp_conn->dp_db_handle, res); goto err1; } } else { /*select the whole table and all the columns*/ if(dp_conn->dp_dbf.query(*dp_conn->dp_db_handle, cond_cols,0,cond_val,query_cols,1, DP_TABLE_COL_NO, order, &res) < 0){ LM_ERR("failed to query database\n"); goto err1; } } nr_rows = RES_ROW_N(res); if(nr_rows == 0){ LM_WARN("no data in the db\n"); goto end; } do { for(i=0; i<RES_ROW_N(res); i++){ rows = RES_ROWS(res); values = ROW_VALUES(rows+i); if ((rule = build_rule(values)) == NULL) { LM_WARN(" failed to build rule -> skipping\n"); continue; } rule->table_id = i; if(add_rule2hash(rule , dp_conn, dp_conn->next_index) != 0) { LM_ERR("add_rule2hash failed\n"); goto err2; } } if (DB_CAPABILITY(dp_conn->dp_dbf, DB_CAP_FETCH)) { if(dp_conn->dp_dbf.fetch_result(*dp_conn->dp_db_handle, &res, no_rows)<0) { LM_ERR("failure while fetching!\n"); if (res) dp_conn->dp_dbf.free_result(*dp_conn->dp_db_handle, res); goto err1; } } else { break; } } while(RES_ROW_N(res)>0); end: /*update data*/ lock_start_write( dp_conn->ref_lock ); destroy_hash(&dp_conn->hash[dp_conn->crt_index]); dp_conn->crt_index = dp_conn->next_index; lock_stop_write( dp_conn->ref_lock ); list_hash(dp_conn->hash[dp_conn->crt_index], dp_conn->ref_lock); dp_conn->dp_dbf.free_result(*dp_conn->dp_db_handle, res); return 0; err1: lock_start_write( dp_conn->ref_lock ); dp_conn->next_index = dp_conn->crt_index; lock_stop_write( dp_conn->ref_lock ); return -1; err2: if(rule) destroy_rule(rule); destroy_hash(&dp_conn->hash[dp_conn->next_index]); dp_conn->dp_dbf.free_result(*dp_conn->dp_db_handle, res); lock_start_write( dp_conn->ref_lock ); dp_conn->next_index = dp_conn->crt_index; /* if lock defined - release the exclusive writing access */ lock_stop_write( dp_conn->ref_lock ); return -1; }
/*load rules from DB*/ int dp_load_db(void) { int i, nr_rows; db1_res_t * res = 0; db_val_t * values; db_row_t * rows; db_key_t query_cols[DP_TABLE_COL_NO] = { &dpid_column, &pr_column, &match_op_column, &match_exp_column, &match_len_column, &subst_exp_column, &repl_exp_column, &attrs_column }; db_key_t order = &pr_column; dpl_node_t *rule; LM_DBG("init\n"); if( (*crt_idx) != (*next_idx)){ LM_WARN("a load command already generated, aborting reload...\n"); return 0; } if (dp_dbf.use_table(dp_db_handle, &dp_table_name) < 0){ LM_ERR("error in use_table %.*s\n", dp_table_name.len, dp_table_name.s); return -1; } if (DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) { if(dp_dbf.query(dp_db_handle,0,0,0,query_cols, 0, DP_TABLE_COL_NO, order, 0) < 0){ LM_ERR("failed to query database!\n"); return -1; } if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows)<0) { LM_ERR("failed to fetch\n"); if (res) dp_dbf.free_result(dp_db_handle, res); return -1; } } else { /*select the whole table and all the columns*/ if(dp_dbf.query(dp_db_handle,0,0,0,query_cols, 0, DP_TABLE_COL_NO, order, &res) < 0){ LM_ERR("failed to query database\n"); return -1; } } nr_rows = RES_ROW_N(res); *next_idx = ((*crt_idx) == 0)? 1:0; destroy_hash(*next_idx); if(nr_rows == 0){ LM_WARN("no data in the db\n"); goto end; } do { for(i=0; i<RES_ROW_N(res); i++){ rows = RES_ROWS(res); values = ROW_VALUES(rows+i); if((rule = build_rule(values)) ==0 ) goto err2; if(add_rule2hash(rule , *next_idx) != 0) goto err2; } if (DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) { if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows)<0) { LM_ERR("failure while fetching!\n"); if (res) dp_dbf.free_result(dp_db_handle, res); return -1; } } else { break; } } while(RES_ROW_N(res)>0); end: /*update data*/ *crt_idx = *next_idx; list_hash(*crt_idx); dp_dbf.free_result(dp_db_handle, res); return 0; err2: if(rule) destroy_rule(rule); destroy_hash(*next_idx); dp_dbf.free_result(dp_db_handle, res); *next_idx = *crt_idx; return -1; }