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 #include <stdio.h>
00029 #include <string.h>
00030 #include <sys/types.h>
00031 #include <unistd.h>
00032
00033 #include "mem/mem.h"
00034 #include "mem/shm_mem.h"
00035 #include "ut.h"
00036 #include "dprint.h"
00037 #include "route.h"
00038 #include "hash_func.h"
00039 #include "pvar.h"
00040
00041 #define is_in_str(p, in) (p<in->s+in->len && *p)
00042
00043 #define PV_TABLE_SIZE 16
00044 #define TR_TABLE_SIZE 4
00045
00046
00047 void tr_destroy(trans_t *t);
00048 void tr_free(trans_t *t);
00049
00050 typedef struct _pv_item
00051 {
00052 pv_export_t pve;
00053 unsigned int pvid;
00054 struct _pv_item *next;
00055 } pv_item_t, *pv_item_p;
00056
00057 static pv_item_t* _pv_table[PV_TABLE_SIZE];
00058 static int _pv_table_set = 0;
00059
00060
00061
00062
00063
00064 void pv_init_table(void)
00065 {
00066 memset(_pv_table, 0, sizeof(pv_item_t*)*PV_TABLE_SIZE);
00067 _pv_table_set = 1;
00068 }
00069
00070
00071
00072
00073 static int is_pv_valid_char(char c)
00074 {
00075 if((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')
00076 || (c=='_') || (c=='.'))
00077 return 1;
00078 return 0;
00079 }
00080
00081
00082
00083
00084 int pv_table_add(pv_export_t *e)
00085 {
00086 char *p;
00087 str *in;
00088 pv_item_t *pvi = NULL;
00089 pv_item_t *pvj = NULL;
00090 pv_item_t *pvn = NULL;
00091 int found;
00092 unsigned int pvid;
00093
00094 if(e==NULL || e->name.s==NULL || e->getf==NULL || e->type==PVT_NONE)
00095 {
00096 LM_ERR("invalid parameters\n");
00097 return -1;
00098 }
00099
00100 if(_pv_table_set==0)
00101 {
00102 LM_DBG("PV table not initialized, doing it now\n");
00103 pv_init_table();
00104 }
00105 in = &(e->name);
00106 p = in->s;
00107 while(is_in_str(p,in) && is_pv_valid_char(*p))
00108 p++;
00109 if(is_in_str(p,in))
00110 {
00111 LM_ERR("invalid char [%c] in [%.*s]\n", *p, in->len, in->s);
00112 return -1;
00113 }
00114 found = 0;
00115
00116 pvid = core_hash(in, 0, 0);
00117
00118 pvi = _pv_table[pvid%PV_TABLE_SIZE];
00119 while(pvi)
00120 {
00121 if(pvi->pvid > pvid)
00122 break;
00123
00124 if(pvi->pve.name.len==in->len)
00125 {
00126 found = strncmp(pvi->pve.name.s, in->s, in->len);
00127 if(found==0)
00128 {
00129 LM_ERR("pvar [%.*s] already exists\n", in->len, in->s);
00130 return -1;
00131 }
00132 }
00133 pvj = pvi;
00134 pvi = pvi->next;
00135 }
00136
00137 pvn = (pv_item_t*)pkg_malloc(sizeof(pv_item_t));
00138 if(pvn==0)
00139 {
00140 LM_ERR("no more memory\n");
00141 return -1;
00142 }
00143 memset(pvn, 0, sizeof(pv_item_t));
00144 memcpy(&(pvn->pve), e, sizeof(pv_export_t));
00145 pvn->pvid = pvid;
00146
00147 if(pvj==0)
00148 {
00149 pvn->next = _pv_table[pvid%PV_TABLE_SIZE];
00150 _pv_table[pvid%PV_TABLE_SIZE] = pvn;
00151 goto done;
00152 }
00153 pvn->next = pvj->next;
00154 pvj->next = pvn;
00155
00156 done:
00157 return 0;
00158 }
00159
00160
00161
00162
00163 int register_pvars_mod(char *mod_name, pv_export_t *items)
00164 {
00165 int ret;
00166 int i;
00167
00168 if (items==0)
00169 return 0;
00170
00171 for ( i=0 ; items[i].name.s ; i++ ) {
00172 ret = pv_table_add(&items[i]);
00173 if (ret!=0) {
00174 LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
00175 items[i].name.len, items[i].name.s, mod_name);
00176 }
00177 }
00178 return 0;
00179 }
00180
00181
00182
00183
00184 int pv_table_free(void)
00185 {
00186 pv_item_p xe;
00187 pv_item_p xe1;
00188 int i;
00189
00190 for(i=0; i<PV_TABLE_SIZE; i++)
00191 {
00192 xe = _pv_table[i];
00193 while(xe!=0)
00194 {
00195 xe1 = xe;
00196 xe = xe->next;
00197 pkg_free(xe1);
00198 }
00199 memset(_pv_table, 0, sizeof(pv_item_t*)*PV_TABLE_SIZE);
00200 _pv_table_set = 0;
00201 }
00202
00203 return 0;
00204 }
00205
00206
00207
00208
00209
00210 int pv_get_uintval(struct sip_msg *msg, pv_param_t *param,
00211 pv_value_t *res, unsigned int uival)
00212 {
00213 int l = 0;
00214 char *ch = NULL;
00215
00216 if(res==NULL)
00217 return -1;
00218
00219 ch = int2str(uival, &l);
00220 res->rs.s = ch;
00221 res->rs.len = l;
00222
00223 res->ri = (int)uival;
00224 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00225 return 0;
00226 }
00227
00228
00229
00230
00231 int pv_get_sintval(struct sip_msg *msg, pv_param_t *param,
00232 pv_value_t *res, int sival)
00233 {
00234 int l = 0;
00235 char *ch = NULL;
00236
00237 if(res==NULL)
00238 return -1;
00239
00240 ch = sint2str(sival, &l);
00241 res->rs.s = ch;
00242 res->rs.len = l;
00243
00244 res->ri = sival;
00245 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00246 return 0;
00247 }
00248
00249
00250
00251
00252 int pv_get_strval(struct sip_msg *msg, pv_param_t *param,
00253 pv_value_t *res, str *sval)
00254 {
00255 if(res==NULL)
00256 return -1;
00257
00258 res->rs = *sval;
00259 res->flags = PV_VAL_STR;
00260 return 0;
00261 }
00262
00263
00264
00265
00266 int pv_get_strintval(struct sip_msg *msg, pv_param_t *param,
00267 pv_value_t *res, str *sval, int ival)
00268 {
00269 if(res==NULL)
00270 return -1;
00271
00272 res->rs = *sval;
00273 res->ri = ival;
00274 res->flags = PV_VAL_STR|PV_VAL_INT;
00275 return 0;
00276 }
00277
00278
00279
00280
00281 int pv_get_intstrval(struct sip_msg *msg, pv_param_t *param,
00282 pv_value_t *res, int ival, str *sval)
00283 {
00284 if(res==NULL)
00285 return -1;
00286
00287 res->rs = *sval;
00288 res->ri = ival;
00289 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00290 return 0;
00291 }
00292
00293
00294 static str pv_str_marker = { PV_MARKER_STR, 1 };
00295 static int pv_get_marker(struct sip_msg *msg, pv_param_t *param,
00296 pv_value_t *res)
00297 {
00298 return pv_get_strintval(msg, param, res, &pv_str_marker,
00299 (int)pv_str_marker.s[0]);
00300 }
00301
00302 static str pv_str_empty = { "", 0 };
00303 static str pv_str_null = { "<null>", 6 };
00304 int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
00305 {
00306 if(res==NULL)
00307 return -1;
00308
00309 res->rs = pv_str_empty;
00310 res->ri = 0;
00311 res->flags = PV_VAL_NULL;
00312 return 0;
00313 }
00314
00315 pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e)
00316 {
00317 pv_item_t *pvi;
00318 unsigned int pvid;
00319
00320 if(pvname==0 || e==0)
00321 {
00322 LM_ERR("bad parameters\n");
00323 return NULL;
00324 }
00325
00326
00327
00328 pvid = core_hash(pvname, 0, 0);
00329 pvi = _pv_table[pvid%PV_TABLE_SIZE];
00330 while(pvi)
00331 {
00332 if(pvi->pvid > pvid)
00333 break;
00334
00335 if(pvi->pvid==pvid && pvi->pve.name.len==pvname->len
00336 && memcmp(pvi->pve.name.s, pvname->s, pvname->len)==0)
00337 {
00338
00339
00340
00341 e->type = pvi->pve.type;
00342 e->getf = pvi->pve.getf;
00343 e->setf = pvi->pve.setf;
00344 return &(pvi->pve);
00345 }
00346 pvi = pvi->next;
00347 }
00348
00349 return NULL;
00350 }
00351
00352 int pv_parse_index(pv_spec_p sp, str *in)
00353 {
00354 char *p;
00355 char *s;
00356 int sign;
00357 pv_spec_p nsp = 0;
00358
00359 if(in==NULL || in->s==NULL || sp==NULL)
00360 return -1;
00361 p = in->s;
00362 if(*p==PV_MARKER)
00363 {
00364 nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
00365 if(nsp==NULL)
00366 {
00367 LM_ERR("no more memory\n");
00368 return -1;
00369 }
00370 s = pv_parse_spec(in, nsp);
00371 if(s==NULL)
00372 {
00373 LM_ERR("invalid index [%.*s]\n", in->len, in->s);
00374 pv_spec_free(nsp);
00375 return -1;
00376 }
00377 sp->pvp.pvi.type = PV_IDX_PVAR;
00378 sp->pvp.pvi.u.dval = (void*)nsp;
00379 return 0;
00380 }
00381 if(*p=='*' && in->len==1)
00382 {
00383 sp->pvp.pvi.type = PV_IDX_ALL;
00384 return 0;
00385 }
00386 sign = 1;
00387 if(*p=='-')
00388 {
00389 sign = -1;
00390 p++;
00391 }
00392 sp->pvp.pvi.u.ival = 0;
00393 while(p<in->s+in->len && *p>='0' && *p<='9')
00394 {
00395 sp->pvp.pvi.u.ival = sp->pvp.pvi.u.ival * 10 + *p - '0';
00396 p++;
00397 }
00398 if(p!=in->s+in->len)
00399 {
00400 LM_ERR("invalid index [%.*s]\n", in->len, in->s);
00401 return -1;
00402 }
00403 sp->pvp.pvi.u.ival *= sign;
00404 sp->pvp.pvi.type = PV_IDX_INT;
00405 return 0;
00406 }
00407
00408 int pv_init_iname(pv_spec_p sp, int param)
00409 {
00410 if(sp==NULL)
00411 return -1;
00412 sp->pvp.pvn.type = PV_NAME_INTSTR;
00413 sp->pvp.pvn.u.isname.name.n = param;
00414 return 0;
00415 }
00416
00417 char* pv_parse_spec(str *in, pv_spec_p e)
00418 {
00419 char *p;
00420 str s;
00421 str pvname;
00422 int pvstate;
00423 trans_t *tr = NULL;
00424 pv_export_t *pte = NULL;
00425 int n=0;
00426
00427 if(in==NULL || in->s==NULL || e==NULL || *in->s!=PV_MARKER)
00428 {
00429 LM_ERR("bad parameters\n");
00430 return NULL;
00431 }
00432
00433
00434 tr = 0;
00435 pvstate = 0;
00436 memset(e, 0, sizeof(pv_spec_t));
00437 p = in->s;
00438 p++;
00439 if(*p==PV_LNBRACKET)
00440 {
00441 p++;
00442 pvstate = 1;
00443 }
00444 pvname.s = p;
00445 if(*p == PV_MARKER) {
00446 p++;
00447 if(pvstate==1)
00448 {
00449 if(*p!=PV_RNBRACKET)
00450 goto error;
00451 p++;
00452 }
00453 e->getf = pv_get_marker;
00454 e->type = PVT_MARKER;
00455 pvname.len = 1;
00456 goto done_all;
00457 }
00458 while(is_in_str(p,in) && is_pv_valid_char(*p))
00459 p++;
00460 pvname.len = p - pvname.s;
00461 if(pvstate==1)
00462 {
00463 if(*p==PV_RNBRACKET)
00464 {
00465 goto done_inm;
00466 } else if(*p==PV_LNBRACKET) {
00467 p++;
00468 pvstate = 2;
00469 } else if(*p==PV_LIBRACKET) {
00470 p++;
00471 pvstate = 3;
00472 } else if(*p==TR_LBRACKET) {
00473 p++;
00474 pvstate = 4;
00475 } else {
00476 LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
00477 pvstate);
00478 goto error;
00479 }
00480 } else {
00481 if(!is_in_str(p, in)) {
00482 p--;
00483 goto done_inm;
00484 } else if(*p==PV_LNBRACKET) {
00485 p++;
00486 pvstate = 5;
00487 } else {
00488
00489
00490 p--;
00491 goto done_inm;
00492 }
00493 }
00494
00495 done_inm:
00496 if((pte = pv_lookup_spec_name(&pvname, e))==NULL)
00497 {
00498 LM_ERR("error searching pvar \"%.*s\"\n", pvname.len, pvname.s);
00499 goto error;
00500 }
00501 if(pte->parse_name!=NULL && pvstate!=2 && pvstate!=5)
00502 {
00503 LM_ERR("pvar \"%.*s\" expects an inner name\n",
00504 pvname.len, pvname.s);
00505 goto error;
00506 }
00507 if(pvstate==2 || pvstate==5)
00508 {
00509 if(pte->parse_name==NULL)
00510 {
00511 LM_ERR("pvar \"%.*s\" does not get name param\n",
00512 pvname.len, pvname.s);
00513 goto error;
00514 }
00515 s.s = p;
00516 n = 0;
00517 while(is_in_str(p, in))
00518 {
00519 if(*p==PV_RNBRACKET)
00520 {
00521 if(n==0)
00522 break;
00523 n--;
00524 }
00525 if(*p == PV_LNBRACKET)
00526 n++;
00527 p++;
00528 }
00529
00530 if(!is_in_str(p, in))
00531 goto error;
00532
00533 if(p==s.s)
00534 {
00535 LM_ERR("pvar \"%.*s\" does not get empty name param\n",
00536 pvname.len, pvname.s);
00537 goto error;
00538 }
00539 s.len = p - s.s;
00540 if(pte->parse_name(e, &s)!=0)
00541 {
00542 LM_ERR("pvar \"%.*s\" has an invalid name param [%.*s]\n",
00543 pvname.len, pvname.s, s.len, s.s);
00544 goto error;
00545 }
00546 if(pvstate==2)
00547 {
00548 p++;
00549 if(*p==PV_RNBRACKET)
00550 {
00551 goto done_vnm;
00552 } else if(*p==PV_LIBRACKET) {
00553 p++;
00554 pvstate = 3;
00555 } else if(*p==TR_LBRACKET) {
00556 p++;
00557 pvstate = 4;
00558 } else {
00559 LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
00560 pvstate);
00561 goto error;
00562 }
00563 } else {
00564 if(*p==PV_RNBRACKET)
00565 {
00566 p++;
00567 goto done_all;
00568 } else {
00569 LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
00570 pvstate);
00571 goto error;
00572 }
00573 }
00574 }
00575 done_vnm:
00576 if(pvstate==3)
00577 {
00578 if(pte->parse_index==NULL)
00579 {
00580 LM_ERR("pvar \"%.*s\" does not get index param\n",
00581 pvname.len, pvname.s);
00582 goto error;
00583 }
00584 s.s = p;
00585 n = 0;
00586 while(is_in_str(p, in))
00587 {
00588 if(*p==PV_RIBRACKET)
00589 {
00590 if(n==0)
00591 break;
00592 n--;
00593 }
00594 if(*p == PV_LIBRACKET)
00595 n++;
00596 p++;
00597 }
00598 if(!is_in_str(p, in))
00599 goto error;
00600
00601 if(p==s.s)
00602 {
00603 LM_ERR("pvar \"%.*s\" does not get empty index param\n",
00604 pvname.len, pvname.s);
00605 goto error;
00606 }
00607 s.len = p - s.s;
00608 if(pte->parse_index(e, &s)!=0)
00609 {
00610 LM_ERR("pvar \"%.*s\" has an invalid index param [%.*s]\n",
00611 pvname.len, pvname.s, s.len, s.s);
00612 goto error;
00613 }
00614 p++;
00615 if(*p==PV_RNBRACKET)
00616 {
00617 goto done_idx;
00618 } else if(*p==TR_LBRACKET) {
00619 p++;
00620 pvstate = 4;
00621 } else {
00622 LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
00623 pvstate);
00624 goto error;
00625 }
00626 }
00627 done_idx:
00628 if(pvstate==4)
00629 {
00630 s.s = p-1;
00631 n = 0;
00632 while(is_in_str(p, in))
00633 {
00634 if(*p==TR_RBRACKET)
00635 {
00636 if(n==0)
00637 {
00638
00639 p++;
00640 while(is_in_str(p, in) && (*p==' ' || *p=='\t')) p++;
00641
00642 if(!is_in_str(p, in) || *p != TR_LBRACKET)
00643 {
00644 p--;
00645 break;
00646 }
00647 }
00648 n--;
00649 }
00650 if(*p == TR_LBRACKET)
00651 n++;
00652 p++;
00653 }
00654 if(!is_in_str(p, in))
00655 goto error;
00656
00657 if(p==s.s)
00658 {
00659 LM_ERR("pvar \"%.*s\" does not get empty index param\n",
00660 pvname.len, pvname.s);
00661 goto error;
00662 }
00663 s.len = p - s.s + 1;
00664
00665 p = tr_lookup(&s, &tr);
00666 if(p==NULL)
00667 {
00668 LM_ERR("bad tr in pvar name \"%.*s\"\n", pvname.len, pvname.s);
00669 goto error;
00670 }
00671 if(*p!=PV_RNBRACKET)
00672 {
00673 LM_ERR("bad pvar name \"%.*s\" (%c)!\n", in->len, in->s, *p);
00674 goto error;
00675 }
00676 e->trans = (void*)tr;
00677 }
00678 p++;
00679
00680 done_all:
00681 if(pte!=NULL && pte->init_param)
00682 pte->init_param(e, pte->iparam);
00683 return p;
00684
00685 error:
00686 if(p!=NULL)
00687 LM_ERR("wrong char [%c/%d] in [%.*s] at [%d (%d)]\n", *p, (int)*p,
00688 in->len, in->s, (int)(p-in->s), pvstate);
00689 else
00690 LM_ERR("invalid parsing in [%.*s] at (%d)\n", in->len, in->s, pvstate);
00691 return NULL;
00692
00693 }
00694
00695
00696
00697
00698 int pv_parse_format(str *in, pv_elem_p *el)
00699 {
00700 char *p, *p0;
00701 int n = 0;
00702 pv_elem_p e, e0;
00703 str s;
00704
00705 if(in==NULL || in->s==NULL || el==NULL)
00706 return -1;
00707
00708
00709
00710 if(in->len == 0)
00711 {
00712 *el = pkg_malloc(sizeof(pv_elem_t));
00713 if(*el == NULL)
00714 goto error;
00715 memset(*el, 0, sizeof(pv_elem_t));
00716 (*el)->text = *in;
00717 return 0;
00718 }
00719
00720 p = in->s;
00721 *el = NULL;
00722 e = e0 = NULL;
00723
00724 while(is_in_str(p,in))
00725 {
00726 e0 = e;
00727 e = pkg_malloc(sizeof(pv_elem_t));
00728 if(!e)
00729 goto error;
00730 memset(e, 0, sizeof(pv_elem_t));
00731 n++;
00732 if(*el == NULL)
00733 *el = e;
00734 if(e0)
00735 e0->next = e;
00736
00737 e->text.s = p;
00738 while(is_in_str(p,in) && *p!=PV_MARKER)
00739 p++;
00740 e->text.len = p - e->text.s;
00741
00742 if(*p == '\0' || !is_in_str(p,in))
00743 break;
00744 s.s = p;
00745 s.len = in->s+in->len-p;
00746 p0 = pv_parse_spec(&s, &e->spec);
00747
00748 if(p0==NULL)
00749 goto error;
00750 if(*p0 == '\0')
00751 break;
00752 p = p0;
00753 }
00754
00755
00756 if(*el == NULL)
00757 return -1;
00758
00759 return 0;
00760
00761 error:
00762 pv_elem_free_all(*el);
00763 *el = NULL;
00764 return -1;
00765 }
00766
00767 int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name)
00768 {
00769 if(msg==NULL || ip==NULL || name==NULL)
00770 return -1;
00771 memset(name, 0, sizeof(pv_value_t));
00772
00773 if(ip->pvn.type==PV_NAME_INTSTR)
00774 {
00775 if(ip->pvn.u.isname.type&AVP_NAME_STR)
00776 {
00777 name->rs = ip->pvn.u.isname.name.s;
00778 name->flags = PV_VAL_STR;
00779 } else {
00780 name->ri = ip->pvn.u.isname.name.n;
00781 name->flags = PV_VAL_INT|PV_TYPE_INT;
00782 }
00783 return 0;
00784 } else if(ip->pvn.type==PV_NAME_INTSTR) {
00785
00786 if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), name)!=0)
00787 {
00788 LM_ERR("cannot get name value\n");
00789 return -1;
00790 }
00791 if(name->flags&PV_VAL_NULL || name->flags&PV_VAL_EMPTY)
00792 {
00793 LM_ERR("null or empty name\n");
00794 return -1;
00795 }
00796 return 0;
00797 }
00798 LM_ERR("name type is PV_NAME_OTHER - cannot resolve\n");
00799 return -1;
00800 }
00801
00802 int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int_str *avp_name,
00803 unsigned short *name_type)
00804 {
00805 pv_value_t tv;
00806 if(ip==NULL || avp_name==NULL || name_type==NULL)
00807 return -1;
00808 memset(avp_name, 0, sizeof(int_str));
00809 *name_type = 0;
00810
00811 if(ip->pvn.type==PV_NAME_INTSTR)
00812 {
00813 *name_type = ip->pvn.u.isname.type;
00814 if(ip->pvn.u.isname.type&AVP_NAME_STR)
00815 {
00816 avp_name->s = ip->pvn.u.isname.name.s;
00817 *name_type |= AVP_NAME_STR;
00818 } else {
00819 avp_name->n = ip->pvn.u.isname.name.n;
00820 *name_type &= AVP_SCRIPT_MASK;
00821 }
00822 return 0;
00823 }
00824
00825 if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), &tv)!=0)
00826 {
00827 LM_ERR("cannot get avp value\n");
00828 return -1;
00829 }
00830 if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY)
00831 {
00832 LM_ERR("null or empty name\n");
00833 return -1;
00834 }
00835
00836 if((tv.flags&PV_TYPE_INT) && (tv.flags&PV_VAL_INT))
00837 {
00838 avp_name->n = tv.ri;
00839 } else {
00840 avp_name->s = tv.rs;
00841 *name_type = AVP_NAME_STR;
00842 }
00843 return 0;
00844 }
00845
00846
00847 int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags)
00848 {
00849 pv_value_t tv;
00850 if(ip==NULL || idx==NULL || flags==NULL)
00851 return -1;
00852
00853 *idx = 0;
00854 *flags = 0;
00855
00856 if(ip->pvi.type == PV_IDX_ALL) {
00857 *flags = PV_IDX_ALL;
00858 return 0;
00859 }
00860
00861 if(ip->pvi.type == PV_IDX_INT)
00862 {
00863 *idx = ip->pvi.u.ival;
00864 return 0;
00865 }
00866
00867
00868 if(pv_get_spec_value(msg, (pv_spec_p)ip->pvi.u.dval, &tv)!=0)
00869 {
00870 LM_ERR("cannot get index value\n");
00871 return -1;
00872 }
00873 if(!(tv.flags&PV_VAL_INT))
00874 {
00875 LM_ERR("invalid index value\n");
00876 return -1;
00877 }
00878 *idx = tv.ri;
00879 return 0;
00880 }
00881
00882 int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
00883 {
00884 int ret = 0;
00885
00886 if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
00887 || sp->type==PVT_NONE)
00888 {
00889 LM_ERR("bad parameters\n");
00890 return -1;
00891 }
00892
00893 memset(value, 0, sizeof(pv_value_t));
00894
00895 if(pv_alter_context(sp) && route_type==LOCAL_ROUTE)
00896 return pv_get_null(msg, &(sp->pvp), value);
00897
00898 ret = (*sp->getf)(msg, &(sp->pvp), value);
00899 if(ret!=0)
00900 return ret;
00901
00902 if(sp->trans)
00903 return tr_exec(msg, (trans_t*)sp->trans, value);
00904 return ret;
00905 }
00906
00907
00908
00909
00910 int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
00911 {
00912 int n, h;
00913 pv_value_t tok;
00914 pv_elem_p it;
00915 char *cur;
00916
00917 if(msg==NULL || list==NULL || buf==NULL || len==NULL)
00918 return -1;
00919
00920 if(*len <= 0)
00921 return -1;
00922
00923 *buf = '\0';
00924 cur = buf;
00925
00926 h = 0;
00927 n = 0;
00928 for (it=list; it; it=it->next)
00929 {
00930
00931 if(it->text.s && it->text.len>0)
00932 {
00933 if(n+it->text.len < *len)
00934 {
00935 memcpy(cur, it->text.s, it->text.len);
00936 n += it->text.len;
00937 cur += it->text.len;
00938 } else {
00939 LM_ERR("no more space for text [%d]\n", it->text.len);
00940 goto overflow;
00941 }
00942 }
00943
00944 if(it->spec.type!=PVT_NONE
00945 && pv_get_spec_value(msg, &(it->spec), &tok)==0)
00946 {
00947 if(tok.flags&PV_VAL_NULL)
00948 tok.rs = pv_str_null;
00949 if(n+tok.rs.len < *len)
00950 {
00951 if(tok.rs.len>0)
00952 {
00953 memcpy(cur, tok.rs.s, tok.rs.len);
00954 n += tok.rs.len;
00955 cur += tok.rs.len;
00956 }
00957 } else {
00958 LM_ERR("no more space for spec value\n");
00959 goto overflow;
00960 }
00961 }
00962 }
00963
00964 goto done;
00965
00966 overflow:
00967 LM_ERR("buffer overflow -- increase the buffer size...\n");
00968 return -1;
00969
00970 done:
00971 #ifdef EXTRA_DEBUG
00972 LM_DBG("final buffer length %d\n", n);
00973 #endif
00974 *cur = '\0';
00975 *len = n;
00976 return 0;
00977 }
00978
00979 int pv_set_spec_value(struct sip_msg* msg, pv_spec_p sp, int op,
00980 pv_value_t *value)
00981 {
00982 if(sp==NULL || !pv_is_w(sp))
00983 return 0;
00984 if(pv_alter_context(sp) && route_type==LOCAL_ROUTE)
00985 return 0;
00986 return sp->setf(msg, &sp->pvp, op, value);
00987 }
00988
00989
00990
00991
00992 pvname_list_t* parse_pvname_list(str *in, unsigned int type)
00993 {
00994 pvname_list_t* head = NULL;
00995 pvname_list_t* al = NULL;
00996 pvname_list_t* last = NULL;
00997 char *p;
00998 pv_spec_t spec;
00999 str s;
01000
01001 if(in==NULL || in->s==NULL)
01002 {
01003 LM_ERR("bad parameters\n");
01004 return NULL;
01005 }
01006
01007 p = in->s;
01008 while(is_in_str(p, in))
01009 {
01010 while(is_in_str(p, in) && (*p==' '||*p=='\t'||*p==','||*p==';'))
01011 p++;
01012 if(!is_in_str(p, in))
01013 {
01014 if(head==NULL)
01015 LM_ERR("wrong item name list [%.*s]\n", in->len, in->s);
01016 return head;
01017 }
01018 s.s=p;
01019 s.len = in->s+in->len-p;
01020 p = pv_parse_spec(&s, &spec);
01021 if(p==NULL || (type && spec.type!=type))
01022 {
01023 LM_ERR("wrong item name list [%.*s]!\n", in->len, in->s);
01024 goto error;
01025 }
01026 al = (pvname_list_t*)pkg_malloc(sizeof(pvname_list_t));
01027 if(al==NULL)
01028 {
01029 LM_ERR("no more memory!\n");
01030 goto error;
01031 }
01032 memset(al, 0, sizeof(pvname_list_t));
01033 memcpy(&al->sname, &spec, sizeof(pv_spec_t));
01034
01035 if(last==NULL)
01036 {
01037 head = al;
01038 last = al;
01039 } else {
01040 last->next = al;
01041 last = al;
01042 }
01043 }
01044
01045 return head;
01046
01047 error:
01048 while(head)
01049 {
01050 al = head;
01051 head=head->next;
01052 pkg_free(al);
01053 }
01054 return NULL;
01055 }
01056
01057
01058
01059
01060 void pv_spec_free(pv_spec_t *spec)
01061 {
01062 if(spec==0) return;
01063
01064 if(spec->trans)
01065 tr_free((trans_t*)spec->trans);
01066 pkg_free(spec);
01067 }
01068
01069
01070
01071
01072 int pv_elem_free_all(pv_elem_p log)
01073 {
01074 pv_elem_p t;
01075 while(log)
01076 {
01077 t = log;
01078 log = log->next;
01079 pkg_free(t);
01080 }
01081 return 0;
01082 }
01083
01084
01085
01086
01087 void pv_value_destroy(pv_value_t *val)
01088 {
01089 if(val==0) return;
01090 if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
01091 if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
01092 memset(val, 0, sizeof(pv_value_t));
01093 }
01094
01095 #define PV_PRINT_BUF_SIZE 1024
01096 #define PV_PRINT_BUF_NO 3
01097 int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s)
01098 {
01099 static int buf_itr = 0;
01100 static char buf[PV_PRINT_BUF_NO][PV_PRINT_BUF_SIZE];
01101
01102 if (list->next==0 && list->spec.getf==0) {
01103 *s = list->text;
01104 return 0;
01105 } else {
01106 s->s = buf[buf_itr];
01107 s->len = PV_PRINT_BUF_SIZE;
01108 buf_itr = (buf_itr+1)%PV_PRINT_BUF_NO;
01109 return pv_printf( msg, list, s->s, &s->len);
01110 }
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120 static inline char* tr_get_class(str *in, char *p, str *tclass)
01121 {
01122 tclass->s = p;
01123 while(is_in_str(p, in) && *p!=TR_CLASS_MARKER) p++;
01124 if(*p!=TR_CLASS_MARKER || tclass->s == p)
01125 {
01126 LM_ERR("invalid transformation: %.*s (%c)!\n", in->len, in->s, *p);
01127 return NULL;
01128 }
01129 tclass->len = p - tclass->s;
01130 p++;
01131
01132 return p;
01133 }
01134
01135
01136
01137
01138 static inline trans_t* tr_new(void)
01139 {
01140 trans_t *t = NULL;
01141
01142 t = (trans_t*)pkg_malloc(sizeof(trans_t));
01143 if(t == NULL)
01144 {
01145 LM_ERR("no more private memory\n");
01146 return NULL;
01147 }
01148 memset(t, 0, sizeof(trans_t));
01149 return t;
01150 }
01151
01152 char* tr_lookup(str *in, trans_t **tr)
01153 {
01154 char *p;
01155 char *p0;
01156 str tclass;
01157 tr_export_t *te = NULL;
01158 trans_t *t = NULL;
01159 trans_t *t0 = NULL;
01160 str s;
01161
01162 if(in==NULL || in->s==NULL || tr==NULL)
01163 return NULL;
01164
01165 p = in->s;
01166 do {
01167 while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
01168 if(*p != TR_LBRACKET)
01169 break;
01170 p++;
01171
01172 if((t = tr_new())==NULL) return NULL;
01173
01174 if(t0==NULL) *tr = t;
01175 else t0->next = t;
01176 t0 = t;
01177
01178
01179 p = tr_get_class(in, p, &tclass);
01180 if(p==NULL) goto error;
01181
01182
01183 te = tr_lookup_class(&tclass);
01184 if(te==NULL)
01185 {
01186 LM_ERR("unknown transformation: [%.*s] in [%.*s]\n",
01187 tclass.len, tclass.s, in->len, in->s);
01188 goto error;
01189 }
01190
01191 s.s = p; s.len = in->s + in->len - p;
01192 p0 = te->tparse(&s, t);
01193 if(p0==NULL)
01194 goto error;
01195 p = p0;
01196
01197 if(*p != TR_RBRACKET)
01198 {
01199 LM_ERR("invalid transformation: %.*s | %c !!\n", in->len,
01200 in->s, *p);
01201 goto error;
01202 }
01203
01204 p++;
01205 if(!is_in_str(p, in))
01206 break;
01207 } while(1);
01208
01209 return p;
01210 error:
01211 LM_ERR("error parsing [%.*s]\n", in->len, in->s);
01212 t = *tr;
01213 while(t)
01214 {
01215 t0 = t;
01216 t = t->next;
01217 tr_destroy(t0);
01218 pkg_free(t0);
01219 }
01220 return NULL;
01221 }
01222
01223
01224
01225
01226
01227 void tr_destroy(trans_t *t)
01228 {
01229 tr_param_t *tp;
01230 tr_param_t *tp0;
01231 if(t==NULL) return;
01232
01233 tp = t->params;
01234 while(tp)
01235 {
01236 tp0 = tp;
01237 tp = tp->next;
01238 tr_param_free(tp0);
01239 }
01240 memset(t, 0, sizeof(trans_t));
01241 }
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251 int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v)
01252 {
01253 int r;
01254 trans_t *i;
01255
01256 if(t==NULL || v==NULL)
01257 {
01258 LM_DBG("invalid parameters\n");
01259 return -1;
01260 }
01261
01262 for(i = t; i!=NULL; i=i->next)
01263 {
01264 r = (*i->trf)(msg, i->params, i->subtype, v);
01265 if(r!=0)
01266 return r;
01267 }
01268 return 0;
01269 }
01270
01271
01272
01273
01274
01275 void tr_free(trans_t *t)
01276 {
01277 trans_t *t0;
01278
01279 while(t)
01280 {
01281 t0 = t;
01282 t = t->next;
01283 tr_destroy(t0);
01284 pkg_free(t0);
01285 }
01286 }
01287
01288
01289
01290
01291
01292
01293 void tr_param_free(tr_param_t *tp)
01294 {
01295 tr_param_t *tp0;
01296
01297 if(tp==NULL) return;
01298 while(tp)
01299 {
01300 tp0 = tp;
01301 tp = tp->next;
01302 if(tp0->type==TR_PARAM_SPEC)
01303 pv_spec_free((pv_spec_t*)tp0->v.data);
01304 pkg_free(tp0);
01305 }
01306 }
01307
01308 typedef struct _tr_item
01309 {
01310 tr_export_t tre;
01311 unsigned int trid;
01312 struct _tr_item *next;
01313 } tr_item_t, *tr_item_p;
01314
01315 static tr_item_t* _tr_table[TR_TABLE_SIZE];
01316 static int _tr_table_set = 0;
01317
01318
01319
01320
01321
01322 void tr_init_table(void)
01323 {
01324 memset(_tr_table, 0, sizeof(tr_item_t*)*TR_TABLE_SIZE);
01325 _tr_table_set = 1;
01326 }
01327
01328
01329
01330
01331 int tr_table_add(tr_export_t *e)
01332 {
01333 tr_item_t *tri = NULL;
01334 tr_item_t *trj = NULL;
01335 tr_item_t *trn = NULL;
01336 int found;
01337 unsigned int trid;
01338
01339 if(e==NULL || e->tclass.s==NULL)
01340 {
01341 LM_ERR("invalid parameters\n");
01342 return -1;
01343 }
01344
01345 if(_tr_table_set==0)
01346 {
01347 LM_DBG("TR table not initialized, doing it now\n");
01348 tr_init_table();
01349 }
01350
01351 found = 0;
01352
01353 trid = core_hash(&e->tclass, 0, 0);
01354
01355 tri = _tr_table[trid%TR_TABLE_SIZE];
01356 while(tri)
01357 {
01358 if(tri->tre.tclass.len==e->tclass.len)
01359 {
01360 found = strncmp(tri->tre.tclass.s, e->tclass.s, e->tclass.len);
01361 if(found==0)
01362 {
01363 LM_ERR("TR class [%.*s] already exists\n", e->tclass.len,
01364 e->tclass.s);
01365 return -1;
01366 }
01367 }
01368 trj = tri;
01369 tri = tri->next;
01370 }
01371
01372 trn = (tr_item_t*)pkg_malloc(sizeof(tr_item_t));
01373 if(trn==0)
01374 {
01375 LM_ERR("no more memory\n");
01376 return -1;
01377 }
01378 memset(trn, 0, sizeof(tr_item_t));
01379 memcpy(&(trn->tre), e, sizeof(tr_export_t));
01380 trn->trid = trid;
01381
01382
01383
01384 if(trj==0)
01385 {
01386 trn->next = _tr_table[trid%TR_TABLE_SIZE];
01387 _tr_table[trid%TR_TABLE_SIZE] = trn;
01388 goto done;
01389 }
01390 trn->next = trj->next;
01391 trj->next = trn;
01392
01393 done:
01394 return 0;
01395 }
01396
01397
01398
01399
01400 int register_trans_mod(char *mod_name, tr_export_t *items)
01401 {
01402 int ret;
01403 int i;
01404
01405 if (items==0)
01406 return 0;
01407
01408 for ( i=0 ; items[i].tclass.s ; i++ ) {
01409 ret = tr_table_add(&items[i]);
01410 if (ret!=0) {
01411 LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
01412 items[i].tclass.len, items[i].tclass.s, mod_name);
01413 }
01414 }
01415 return 0;
01416 }
01417
01418
01419
01420
01421 int tr_table_free(void)
01422 {
01423 tr_item_p te;
01424 tr_item_p te1;
01425 int i;
01426
01427 for(i=0; i<TR_TABLE_SIZE; i++)
01428 {
01429 te = _tr_table[i];
01430 while(te!=0)
01431 {
01432 te1 = te;
01433 te = te->next;
01434 pkg_free(te1);
01435 }
01436 memset(_tr_table, 0, sizeof(tr_item_t*)*TR_TABLE_SIZE);
01437 _tr_table_set = 0;
01438 }
01439
01440 return 0;
01441 }
01442
01443 tr_export_t* tr_lookup_class(str *tclass)
01444 {
01445 tr_item_t *tri;
01446 unsigned int trid;
01447
01448 if(tclass==0 || tclass->s==0)
01449 {
01450 LM_ERR("bad parameters\n");
01451 return NULL;
01452 }
01453
01454
01455
01456 trid = core_hash(tclass, 0, 0);
01457 tri = _tr_table[trid%TR_TABLE_SIZE];
01458 while(tri)
01459 {
01460 if(tri->trid==trid && tri->tre.tclass.len==tclass->len
01461 && memcmp(tri->tre.tclass.s, tclass->s, tclass->len)==0)
01462 return &(tri->tre);
01463 tri = tri->next;
01464 }
01465
01466 return NULL;
01467 }
01468
01469 void pv_api_destroy(void)
01470 {
01471
01472 return;
01473 }