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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <stdio.h>
00045 #include <unistd.h>
00046 #include <stdlib.h>
00047
00048 #include "../../sr_module.h"
00049 #include "../../lib/srdb2/db.h"
00050 #include "../../mem/shm_mem.h"
00051 #include "../../mem/mem.h"
00052 #include "../../dprint.h"
00053 #include "../../parser/parse_uri.h"
00054 #include "../../timer.h"
00055 #include "../../ut.h"
00056 #include "../../rpc.h"
00057 #include "../../action.h"
00058
00059 #include "domains.h"
00060 #include "pdtree.h"
00061
00062 MODULE_VERSION
00063
00064
00065 #define NR_KEYS 2
00066
00067 int hs_two_pow = 2;
00068
00070 pdt_hash_t *_dhash = NULL;
00071 pdt_tree_t *_ptree = NULL;
00072
00073 time_t last_sync;
00074
00076 static db_ctx_t* ctx = NULL;
00077 static db_cmd_t* db_load = NULL;
00078 static db_cmd_t* db_insert = NULL;
00079 static db_cmd_t* db_delete = NULL;
00080 static db_cmd_t* db_del_domain = NULL;
00081
00082
00084 static char *db_url = DEFAULT_DB_URL;
00085 char *db_table = "pdt";
00086 char *prefix_column = "prefix";
00087 char *domain_column = "domain";
00088
00090 str prefix = STR_STATIC_INIT("");
00091 int sync_time = 600;
00092 int clean_time = 900;
00093
00094 static int w_prefix2domain(struct sip_msg* msg, char* str1, char* str2);
00095 static int w_prefix2domain_1(struct sip_msg* msg, char* mode, char* str2);
00096 static int mod_init(void);
00097 static void mod_destroy(void);
00098 static int child_init(int r);
00099
00100 static int prefix2domain(struct sip_msg*, int mode);
00101
00102 int update_new_uri(struct sip_msg *msg, int plen, str *d, int mode);
00103 int pdt_load_db();
00104 int pdt_sync_cache();
00105 void pdt_clean_cache(unsigned int ticks, void *param);
00106
00107 static rpc_export_t pdt_rpc[];
00108
00109 static cmd_export_t cmds[]={
00110 {"prefix2domain", w_prefix2domain, 0, 0, REQUEST_ROUTE|FAILURE_ROUTE},
00111 {"prefix2domain", w_prefix2domain_1, 1, 0, REQUEST_ROUTE|FAILURE_ROUTE},
00112 {0, 0, 0, 0, 0}
00113 };
00114
00115 static param_export_t params[]={
00116 {"db_url", PARAM_STRING, &db_url},
00117 {"db_table", PARAM_STRING, &db_table},
00118 {"prefix_column", PARAM_STRING, &prefix_column},
00119 {"domain_column", PARAM_STRING, &domain_column},
00120 {"prefix", PARAM_STR, &prefix},
00121 {"hsize_2pow", PARAM_INT, &hs_two_pow},
00122 {"sync_time", PARAM_INT, &sync_time},
00123 {"clean_time", PARAM_INT, &clean_time},
00124 {0, 0, 0}
00125 };
00126
00127 struct module_exports exports = {
00128 "pdt",
00129 cmds,
00130 pdt_rpc,
00131 params,
00132
00133 mod_init,
00134 0,
00135 mod_destroy,
00136 0,
00137 child_init
00138 };
00139
00140
00141 static void pdt_db_close(void)
00142 {
00143 if (db_load) db_cmd_free(db_load);
00144 db_load = NULL;
00145
00146 if (db_insert) db_cmd_free(db_insert);
00147 db_insert = NULL;
00148
00149 if (db_delete) db_cmd_free(db_delete);
00150 db_delete = NULL;
00151
00152 if (db_del_domain) db_cmd_free(db_del_domain);
00153 db_del_domain = NULL;
00154
00155 if (ctx) {
00156 db_disconnect(ctx);
00157 db_ctx_free(ctx);
00158 ctx = NULL;
00159 }
00160 }
00161
00162
00163 static int pdt_db_init(void)
00164 {
00165 db_fld_t fields[] = {
00166 {.name = prefix_column, .type = DB_STR},
00167 {.name = domain_column, .type = DB_STR},
00168 {.name = 0}
00169 };
00170
00171 db_fld_t del_dom_param[] = {
00172 {.name = domain_column, .type = DB_STR},
00173 {.name = 0}
00174 };
00175
00176 ctx = db_ctx("pdt");
00177 if (!ctx) goto error;
00178 if (db_add_db(ctx, db_url) < 0) goto error;
00179 if (db_connect(ctx) < 0) goto error;
00180
00181 db_load = db_cmd(DB_GET, ctx, db_table, fields, NULL, NULL);
00182 if (!db_load) goto error;
00183
00184 db_insert = db_cmd(DB_PUT, ctx, db_table, NULL, NULL, fields);
00185 if (!db_insert) goto error;
00186
00187 db_delete = db_cmd(DB_DEL, ctx, db_table, NULL, fields, NULL);
00188 if (!db_delete) goto error;
00189
00190 db_del_domain = db_cmd(DB_DEL, ctx, db_table, NULL, del_dom_param, NULL);
00191 if (!db_del_domain) goto error;
00192
00193 return 0;
00194
00195 error:
00196 pdt_db_close();
00197 ERR("pdt: Error while initializing database layer\n");
00198 return -1;
00199 }
00200
00201
00202
00203
00204
00205
00206 static int mod_init(void)
00207 {
00208 DBG("PDT: initializing...\n");
00209
00210 if(hs_two_pow<0)
00211 {
00212 LOG(L_ERR, "PDT:mod_init: hash_size_two_pow must be"
00213 " positive and less than %d\n", MAX_HSIZE_TWO_POW);
00214 return -1;
00215 }
00216
00217 prefix.len = strlen(prefix.s);
00218
00219
00220 if (pdt_db_init() < 0) return -1;
00221
00222
00223 if( (_dhash = pdt_init_hash(hs_two_pow)) == NULL)
00224 {
00225 LOG(L_ERR, "PDT:mod_init: domain hash could not be allocated\n");
00226 goto error1;
00227 }
00228
00229 if( (_ptree = pdt_init_tree()) == NULL)
00230 {
00231 LOG(L_ERR, "PDT:mod_init: prefix tree could not be allocated\n");
00232 goto error2;
00233 }
00234
00235
00236 if(pdt_load_db()!=0)
00237 {
00238 LOG(L_ERR, "PDT:mod_init: cannot load info from database\n");
00239 goto error3;
00240 }
00241
00242 pdt_db_close();
00243
00244 pdt_print_tree(_ptree);
00245 DBG("PDT:mod_init: -------------------\n");
00246 pdt_print_hash(_dhash);
00247
00248 last_sync = time(NULL);
00249
00250 register_timer(pdt_clean_cache, 0, clean_time);
00251
00252
00253 return 0;
00254
00255 error3:
00256 if(_ptree!=NULL)
00257 {
00258 pdt_free_tree(_ptree);
00259 _ptree = 0;
00260 }
00261 error2:
00262 if(_dhash!=NULL)
00263 {
00264 pdt_free_hash(_dhash);
00265 _dhash = 0;
00266 }
00267 error1:
00268 pdt_db_close();
00269 return -1;
00270 }
00271
00272
00273 static int child_init(int rank)
00274 {
00275 DBG("PDT:child_init #%d / pid <%d>\n", rank, getpid());
00276
00277 if(rank>0)
00278 {
00279 if(_dhash==NULL)
00280 {
00281 LOG(L_ERR,"PDT:child_init #%d: ERROR no domain hash\n", rank);
00282 return -1;
00283 }
00284
00285 lock_get(&_dhash->diff_lock);
00286 _dhash->workers++;
00287 lock_release(&_dhash->diff_lock);
00288 } else {
00289 if(_ptree!=NULL)
00290 {
00291 pdt_free_tree(_ptree);
00292 _ptree = 0;
00293 }
00294 }
00295
00296 if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00297 return 0;
00298
00299 if (pdt_db_init() < 0) return -1;
00300
00301 if(sync_time<=0)
00302 sync_time = 300;
00303 sync_time += rank%60;
00304
00305 DBG("PDT:child_init #%d: Database connection opened successfully\n",rank);
00306
00307 return 0;
00308 }
00309
00310 static void mod_destroy(void)
00311 {
00312 DBG("PDT: mod_destroy : Cleaning up\n");
00313 if (_dhash!=NULL)
00314 pdt_free_hash(_dhash);
00315 if (_ptree!=NULL)
00316 pdt_free_tree(_ptree);
00317
00318 pdt_db_close();
00319 }
00320
00321
00322 static int w_prefix2domain(struct sip_msg* msg, char* str1, char* str2)
00323 {
00324 return prefix2domain(msg, 0);
00325 }
00326
00327 static int w_prefix2domain_1(struct sip_msg* msg, char* mode, char* str2)
00328 {
00329 if(mode!=NULL && *mode=='1')
00330 return prefix2domain(msg, 1);
00331 else if(mode!=NULL && *mode=='2')
00332 return prefix2domain(msg, 2);
00333 else return prefix2domain(msg, 0);
00334 }
00335
00336
00337 static int prefix2domain(struct sip_msg* msg, int mode)
00338 {
00339 str p;
00340 str *d;
00341 time_t crt_time;
00342 int plen;
00343
00344 if(msg==NULL)
00345 {
00346 LOG(L_ERR,"PDT:prefix2domain: weird error\n");
00347 return -1;
00348 }
00349
00350
00351 if(msg->parsed_uri_ok==0)
00352 if(parse_sip_msg_uri(msg)<0)
00353 {
00354 LOG(L_ERR,"PDT:prefix2domain: ERROR while parsing the R-URI\n");
00355 return -1;
00356 }
00357
00358
00359 if (msg->parsed_uri.user.len<=0)
00360 {
00361 DBG("PDT:prefix2domain: user part of the message is empty\n");
00362 return 1;
00363 }
00364
00365 if(prefix.len>0 && prefix.len < msg->parsed_uri.user.len
00366 && strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0)
00367 {
00368 DBG("PDT:prefix2domain: PSTN prefix did not matched\n");
00369 return 1;
00370
00371 }
00372
00373 p.s = msg->parsed_uri.user.s + prefix.len;
00374 p.len = msg->parsed_uri.user.len - prefix.len;
00375
00376
00377 crt_time = time(NULL);
00378 if(last_sync + sync_time < crt_time)
00379 {
00380 last_sync = crt_time;
00381 if(pdt_sync_cache())
00382 {
00383 LOG(L_ERR, "PDT:prefix2domain: cannot update the cache\n");
00384 return -1;
00385 }
00386 }
00387
00388
00389 plen = 0;
00390 if((d=pdt_get_domain(_ptree, &p, &plen))==NULL)
00391 {
00392 LOG(L_INFO, "PDT:prefix2domain: no prefix found in [%.*s]\n",
00393 p.len, p.s);
00394 return -1;
00395 }
00396
00397
00398 if(update_new_uri(msg, plen, d, mode)<0)
00399 {
00400 LOG(L_ERR, "PDT:prefix2domain: new_uri cannot be updated\n");
00401 return -1;
00402 }
00403 return 1;
00404 }
00405
00406
00407 int update_new_uri(struct sip_msg *msg, int plen, str *d, int mode)
00408 {
00409 struct action act;
00410 struct run_act_ctx ra_ctx;
00411 if(msg==NULL || d==NULL)
00412 {
00413 LOG(L_ERR, "PDT:update_new_uri: bad parameters\n");
00414 return -1;
00415 }
00416
00417 memset(&act, 0, sizeof(act));
00418 if(mode==0 || (mode==1 && prefix.len>0))
00419 {
00420 act.type = STRIP_T;
00421 act.val[0].type = NUMBER_ST;
00422 if(mode==0)
00423 act.val[0].u.number = plen + prefix.len;
00424 else
00425 act.val[0].u.number = prefix.len;
00426 act.next = 0;
00427
00428 init_run_actions_ctx(&ra_ctx);
00429 if (do_action(&ra_ctx, &act, msg) < 0)
00430 {
00431 LOG(L_ERR, "PDT:update_new_uri:Error removing prefix\n");
00432 return -1;
00433 }
00434 }
00435
00436 act.type = SET_HOSTPORT_T;
00437 act.val[0].type = STRING_ST;
00438 act.val[0].u.string = d->s;
00439 act.next = 0;
00440
00441 init_run_actions_ctx(&ra_ctx);
00442 if (do_action(&ra_ctx, &act, msg) < 0)
00443 {
00444 LOG(L_ERR, "PDT:update_new_uri:Error changing domain\n");
00445 return -1;
00446 }
00447
00448 DBG("PDT: update_new_uri: len=%d uri=%.*s\n", msg->new_uri.len,
00449 msg->new_uri.len, msg->new_uri.s);
00450
00451 return 0;
00452 }
00453
00454 int pdt_load_db()
00455 {
00456 db_res_t* res = NULL;
00457 db_rec_t* rec;
00458
00459 if (db_exec(&res, db_load) < 0) {
00460 ERR("pdt: Error while loading data from database\n");
00461 return -1;
00462 }
00463 if (res == NULL) return 0;
00464
00465 for(rec = db_first(res); rec; rec = db_next(res)) {
00466 if (rec->fld[0].flags & DB_NULL ||
00467 rec->fld[1].flags & DB_NULL) {
00468 INFO("pdt: Record with NULL value(s) found in database, skipping\n");
00469 continue;
00470 }
00471
00472 if (pdt_check_pd(_dhash, &rec->fld[0].v.lstr,
00473 &rec->fld[1].v.lstr) != 0) {
00474 ERR("pdt: Prefix [%.*s] or domain <%.*s> duplicated\n",
00475 STR_FMT(&rec->fld[0].v.lstr),
00476 STR_FMT(&rec->fld[1].v.lstr));
00477 goto error;
00478 }
00479
00480 if (pdt_add_to_tree(_ptree, &rec->fld[0].v.lstr,
00481 &rec->fld[1].v.lstr) != 0) {
00482 ERR("pdt: Error adding info in tree\n");
00483 goto error;
00484 }
00485
00486 if(pdt_add_to_hash(_dhash, &rec->fld[0].v.lstr,
00487 &rec->fld[1].v.lstr) != 0) {
00488 ERR("pdt: Error adding info in hash\n");
00489 goto error;
00490 }
00491 }
00492
00493 db_res_free(res);
00494 return 0;
00495
00496 error:
00497 if (res) db_res_free(res);
00498 return -1;
00499 }
00500
00501
00502 int pdt_sync_cache()
00503 {
00504 pd_op_t *ito;
00505
00506 DBG("PDT:pdt_sync_cache: ...\n");
00507
00508 if(_dhash==NULL || _ptree==NULL)
00509 {
00510 LOG(L_ERR, "PDT:pdt_sync_cache: strange situation\n");
00511 return -1;
00512 }
00513
00514 lock_get(&_dhash->diff_lock);
00515
00516 if(_ptree->idsync >= _dhash->max_id)
00517 goto done;
00518
00519 ito = _dhash->diff;
00520
00521 while(ito!=NULL && _ptree->idsync >= ito->id)
00522 ito = ito->n;
00523
00524 while(ito!=NULL)
00525 {
00526 DBG("PDT:pdt_sync_cache: sync op[%d]=%d...\n",
00527 ito->id, ito->op);
00528 switch(ito->op)
00529 {
00530 case PDT_ADD:
00531 if(pdt_add_to_tree(_ptree, &ito->cell->prefix,
00532 &ito->cell->domain)!=0)
00533 {
00534 LOG(L_ERR, "PDT:pdt_sync_cache: Error to insert in tree\n");
00535 goto error;
00536 }
00537 break;
00538 case PDT_DELETE:
00539 if(pdt_remove_from_tree(_ptree, &ito->cell->prefix)!=0)
00540 {
00541 LOG(L_ERR,
00542 "PDT:pdt_sync_cache: Error to remove from tree\n");
00543 goto error;
00544 }
00545 break;
00546 default:
00547 LOG(L_ERR, "PDT:pdt_sync_cache: unknown operation\n");
00548 }
00549 _ptree->idsync = ito->id;
00550 ito->count++;
00551 ito = ito->n;
00552 }
00553
00554 done:
00555 lock_release(&_dhash->diff_lock);
00556 return 0;
00557 error:
00558 lock_release(&_dhash->diff_lock);
00559 return -1;
00560 }
00561
00562 void pdt_clean_cache(unsigned int ticks, void *param)
00563 {
00564 pd_op_t *ito, *tmp;
00565
00566
00567
00568 if(_dhash==NULL)
00569 {
00570 LOG(L_ERR, "PDT:pdt_clean_cache: strange situation\n");
00571 return;
00572 }
00573
00574 lock_get(&_dhash->diff_lock);
00575
00576 ito = _dhash->diff;
00577
00578 while(ito!=NULL)
00579 {
00580 if(ito->count >= _dhash->workers)
00581 {
00582 DBG("PDT:pdt_clean_cache: cleaning op[%d]=%d...\n",
00583 ito->id, ito->op);
00584 free_cell(ito->cell);
00585 if(ito->p!=NULL)
00586 (ito->p)->n = ito->n;
00587 else
00588 _dhash->diff = ito->n;
00589 if(ito->n!=NULL)
00590 (ito->n)->p = ito->p;
00591 tmp = ito;
00592 ito = ito->n;
00593 shm_free(tmp);
00594 } else
00595 ito = ito->n;
00596 }
00597
00598 lock_release(&_dhash->diff_lock);
00599 return;
00600 }
00601
00602
00603
00604 static const char* rpc_add_doc[2] = {
00605 "Add new prefix/domain translation rule.",
00606 0
00607 };
00608
00609 static void rpc_add(rpc_t* rpc, void* c)
00610 {
00611 pd_t* cell;
00612 pd_op_t *ito, *tmp;
00613 str sd, sp;
00614 char* t;
00615
00616 if(_dhash==NULL) {
00617 LOG(L_ERR, "PDT:pdt_fifo_add: strange situation\n");
00618 rpc->fault(c, 500, "Server Error");
00619 return;
00620 }
00621
00622
00623 if (rpc->scan(c, "ss", &sp.s, &sd.s) < 2) {
00624 rpc->fault(c, 400, "Invalid Parameter Value");
00625 return;
00626 }
00627 sp.len = strlen(sp.s);
00628 sd.len = strlen(sd.s);
00629
00630 t = sp.s;
00631 while(t!=NULL && *t!='\0') {
00632 if(*t < '0' || *t > '9') {
00633 LOG(L_ERR, "PDT:pdt_fifo_add: bad prefix [%s]\n", sp.s);
00634 rpc->fault(c, 400, "Bad Prefix");
00635 return;
00636 }
00637 t++;
00638 }
00639
00640 if(pdt_check_pd(_dhash, &sp, &sd)!=0) {
00641 LOG(L_ERR, "PDT:pdt_fifo_add: prefix or domain exists\n");
00642 rpc->fault(c, 400, "Prefix Or Domain Exists");
00643 return;
00644 }
00645
00646 db_insert->vals[0].v.lstr = sp;
00647 db_insert->vals[1].v.lstr = sd;
00648
00649 DBG("PDT:pdt_fifo_add: [%.*s] <%.*s>\n", STR_FMT(&sp), STR_FMT(&sd));
00650
00651
00652 if (db_exec(NULL, db_insert) < 0) {
00653 LOG(L_ERR, "PDT:pdt_fifo_add: error storing new prefix/domain\n");
00654 rpc->fault(c, 430, "Cannot Store Prefix/domain");
00655 return;
00656 }
00657
00658
00659 cell = new_cell(&sp, &sd);
00660 if(cell==NULL) {
00661 LOG(L_ERR, "PDT:pdt_fifo_add: no more shm\n");
00662 rpc->fault(c, 431, "Out Of Shared Memory");
00663 goto error1;
00664 }
00665 tmp = new_pd_op(cell, 0, PDT_ADD);
00666 if(tmp==NULL) {
00667 LOG(L_ERR, "PDT:pdt_fifo_add: no more shm!\n");
00668 rpc->fault(c, 431, "Out Of Shared Memory");
00669 goto error2;
00670 }
00671
00672 lock_get(&_dhash->diff_lock);
00673
00674 if(pdt_add_to_hash(_dhash, &sp, &sd)!=0) {
00675 LOG(L_ERR, "PDT:pdt_fifo_add: could not add to cache\n");
00676 rpc->fault(c, 431, "Could Not Add To Cache");
00677 goto error3;
00678 }
00679
00680 _dhash->max_id++;
00681 tmp->id = _dhash->max_id;
00682 if(_dhash->diff==NULL) {
00683 _dhash->diff = tmp;
00684 goto done;
00685 }
00686 ito = _dhash->diff;
00687 while(ito->n!=NULL)
00688 ito = ito->n;
00689
00690 ito->n = tmp;
00691 tmp->p = ito;
00692
00693 done:
00694 DBG("PDT:pdt_fifo_add: op[%d]=%d...\n", tmp->id, tmp->op);
00695 lock_release(&_dhash->diff_lock);
00696 return;
00697
00698 error3:
00699 lock_release(&_dhash->diff_lock);
00700 free_pd_op(tmp);
00701 error2:
00702 free_cell(cell);
00703 error1:
00704
00705 db_delete->vals[0].v.lstr = sp;
00706 db_delete->vals[1].v.lstr = sd;
00707 if (db_exec(NULL, db_delete) < 0) {
00708 LOG(L_ERR,"PDT:pdt_fifo_add: database/cache are inconsistent\n");
00709 }
00710 }
00711
00712
00713
00714 static const char* rpc_delete_doc[2] = {
00715 "Delete prefix/domain translation rule.",
00716 0
00717 };
00718
00719 static void rpc_delete(rpc_t* rpc, void* c)
00720 {
00721 str sd;
00722 unsigned int dhash;
00723 int hash_entry;
00724 pd_t *it;
00725 pd_op_t *ito, *tmp;
00726
00727 if(_dhash==NULL) {
00728 LOG(L_ERR, "PDT:pdt_fifo_delete: strange situation\n");
00729 rpc->fault(c, 500, "Server Error");
00730 return;
00731 }
00732
00733
00734 if (rpc->scan(c, "s", &sd.s) < 1) {
00735 rpc->fault(c, 400, "Parameter Missing");
00736 return;
00737 }
00738 sd.len = strlen(sd.s);
00739
00740 if(*sd.s=='\0') {
00741 LOG(L_INFO, "PDT:pdt_fifo_delete: empty domain\n");
00742 rpc->fault(c, 400, "Empty Parameter");
00743 return;
00744 }
00745
00746 dhash = pdt_compute_hash(sd.s);
00747 hash_entry = get_hash_entry(dhash, _dhash->hash_size);
00748
00749 lock_get(&_dhash->diff_lock);
00750
00751 lock_get(&_dhash->dhash[hash_entry].lock);
00752
00753 it = _dhash->dhash[hash_entry].e;
00754 while(it!=NULL && it->dhash<=dhash) {
00755 if(it->dhash==dhash && it->domain.len==sd.len
00756 && strncasecmp(it->domain.s, sd.s, sd.len)==0)
00757 break;
00758 it = it->n;
00759 }
00760
00761 if(it!=NULL) {
00762 if(it->p!=NULL)
00763 (it->p)->n = it->n;
00764 else
00765 _dhash->dhash[hash_entry].e = it->n;
00766 if(it->n)
00767 (it->n)->p = it->p;
00768 }
00769 lock_release(&_dhash->dhash[hash_entry].lock);
00770
00771 if(it!=NULL) {
00772 tmp = new_pd_op(it, 0, PDT_DELETE);
00773 if(tmp==NULL) {
00774 LOG(L_ERR, "PDT:pdt_fifo_delete: no more shm!\n");
00775 rpc->fault(c, 431, "No Shared Memory Left");
00776 lock_release(&_dhash->diff_lock);
00777 return;
00778 }
00779
00780 _dhash->max_id++;
00781 tmp->id = _dhash->max_id;
00782 if(_dhash->diff==NULL) {
00783 _dhash->diff = tmp;
00784 DBG("PDT:pdt_fifo_delete: op[%d]=%d...\n", tmp->id, tmp->op);
00785 goto done;
00786 }
00787 ito = _dhash->diff;
00788 while(ito->n!=NULL)
00789 ito = ito->n;
00790
00791 ito->n = tmp;
00792 tmp->p = ito;
00793 DBG("PDT:pdt_fifo_delete: op[%d]=%d...\n", tmp->id, tmp->op);
00794 dhash = 1;
00795 } else {
00796 dhash = 0;
00797 }
00798
00799 done:
00800 lock_release(&_dhash->diff_lock);
00801 if(dhash==0) {
00802 DBG("PDT:pdt_fifo_delete: prefix for domain [%s] not found\n", sd.s);
00803 rpc->fault(c, 404, "Domain Not Found");
00804 } else {
00805 db_del_domain->match[0].v.lstr = sd;
00806 if (db_exec(NULL, db_del_domain) < 0) {
00807 LOG(L_ERR,"PDT:pdt_fifo_delete: database/cache are inconsistent\n");
00808 rpc->fault(c, 502, "Database And Cache Are Inconsistent");
00809 }
00810 }
00811 }
00812
00813
00814
00815 static const char* rpc_list_doc[2] = {
00816 "List existin prefix/domain translation rules",
00817 0
00818 };
00819
00835 static void rpc_list(rpc_t* rpc, void* c)
00836 {
00837 str sd, sp;
00838 pd_t *it;
00839 int i;
00840 char* buf1, *buf2, *t;
00841
00842 if(_dhash==NULL) {
00843 LOG(L_ERR, "PDT:pdt_fifo_list: strange situation\n");
00844 rpc->fault(c, 500, "Server Error");
00845 return;
00846 }
00847
00848 if (rpc->scan(c, "ss", &sp.s, &sd.s) < 2) {
00849 rpc->fault(c, 400, "Invalid parameter value");
00850 return;
00851 }
00852 sp.len = strlen(sp.s);
00853 sd.len = strlen(sd.s);
00854
00855 t = sp.s;
00856 if(*t!='\0' && *t!='.') {
00857 while(t!=NULL && *t!='\0') {
00858 if(*t < '0' || *t > '9') {
00859 LOG(L_ERR, "PDT:pdt_fifo_add: bad prefix [%s]\n", sp.s);
00860 rpc->fault(c, 400, "Bad Prefix");
00861 return;
00862 }
00863 t++;
00864 }
00865 } else {
00866 sp.s = NULL;
00867 sp.len = 0;
00868 }
00869
00870 if(*sd.s=='\0' || *sd.s=='.') {
00871 sd.s = NULL;
00872 sd.len = 0;
00873 }
00874
00875 lock_get(&_dhash->diff_lock);
00876
00877 for(i=0; i<_dhash->hash_size; i++) {
00878 lock_get(&_dhash->dhash[i].lock);
00879
00880 it = _dhash->dhash[i].e;
00881 for (it = _dhash->dhash[i].e; it; it = it->n) {
00882 if((sp.s==NULL && sd.s==NULL)
00883 || (sp.s!=NULL && it->prefix.len>=sp.len &&
00884 strncmp(it->prefix.s, sp.s, sp.len)==0)
00885 || (sd.s!=NULL && it->domain.len>=sd.len &&
00886 strncasecmp(it->domain.s, sd.s, sd.len)==0)) {
00887
00888 buf1 = pkg_malloc(it->prefix.len + 1);
00889 if (!buf1) continue;
00890 memcpy(buf1, it->prefix.s, it->prefix.len);
00891 buf1[it->prefix.len] = '\0';
00892
00893 buf2 = pkg_malloc(it->domain.len + 1);
00894 if (!buf2) {
00895 pkg_free(buf1);
00896 continue;
00897 }
00898 memcpy(buf2, it->domain.s, it->domain.len);
00899 buf2[it->domain.len] = '\0';
00900
00901 rpc->add(c, "ss", buf1, buf2);
00902 pkg_free(buf1);
00903 pkg_free(buf2);
00904 }
00905 }
00906
00907 lock_release(&_dhash->dhash[i].lock);
00908 }
00909
00910 lock_release(&_dhash->diff_lock);
00911 }
00912
00913
00914 static rpc_export_t pdt_rpc[] = {
00915 {"pdt.add", rpc_add, rpc_add_doc, 0},
00916 {"pdt.delete", rpc_delete, rpc_delete_doc, 0},
00917 {"pdt.list", rpc_list, rpc_list_doc, RET_ARRAY},
00918 {0, 0, 0, 0}
00919 };