pkg/kamailio/fedora/16: Updated rel in .spec to dev2
[sip-router] / pvapi.c
1 /*
2  * Copyright (C) 2001-2003 FhG Fokus
3  *
4  * This file is part of SIP-Router, a free SIP server.
5  *
6  * SIP-Router is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * SIP-Router is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License 
17  * along with this program; if not, write to the Free Software 
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /*!
22  * \file
23  * \brief SIP-router core :: PV API specification
24  * \ingroup core
25  * Module: \ref core
26  */
27
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33
34 #include "mem/mem.h"
35 #include "mem/shm_mem.h"
36 #include "ut.h"
37 #include "dprint.h"
38 #include "hashes.h"
39 #include "route.h"
40 #include "pvapi.h"
41 #include "pvar.h"
42
43 #define PV_TABLE_SIZE   32  /*!< pseudo-variables table size */
44 #define PV_CACHE_SIZE   32  /*!< pseudo-variables table size */
45 #define TR_TABLE_SIZE   16  /*!< transformations table size */
46
47
48 void tr_destroy(trans_t *t);
49 void tr_free(trans_t *t);
50
51 typedef struct _pv_item
52 {
53         pv_export_t pve;
54         unsigned int pvid;
55         struct _pv_item *next;
56 } pv_item_t, *pv_item_p;
57
58 static pv_item_t* _pv_table[PV_TABLE_SIZE];
59 static int _pv_table_set = 0;
60
61 typedef struct _pv_cache
62 {
63         str pvname;
64         unsigned int pvid;
65         pv_spec_t spec;
66         struct _pv_cache *next;
67 } pv_cache_t;
68
69 static pv_cache_t* _pv_cache[PV_CACHE_SIZE];
70 static int _pv_cache_set = 0;
71
72 /**
73  *
74  */
75 void pv_init_table(void)
76 {
77         memset(_pv_table, 0, sizeof(pv_item_t*)*PV_TABLE_SIZE);
78         _pv_table_set = 1;
79 }
80
81 /**
82  *
83  */
84 void pv_init_cache(void)
85 {
86         memset(_pv_cache, 0, sizeof(pv_cache_t*)*PV_CACHE_SIZE);
87         _pv_cache_set = 1;
88 }
89
90
91 /**
92  * @brief Check if a char is valid according to the PV syntax
93  * @param c checked char
94  * @return 1 if char is valid, 0 if not valid
95  */
96 static int is_pv_valid_char(char c)
97 {
98         if((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')
99                         || (c=='_') || (c=='.') || (c=='?') /* ser $? */)
100                 return 1;
101         return 0;
102 }
103
104 /**
105  *
106  */
107 int pv_locate_name(str *in)
108 {
109         int i;
110         int pcount;
111
112         if(in==NULL || in->s==NULL || in->len<2)
113         {
114                 LM_ERR("bad parameters\n");
115                 return -1;
116         }
117
118         if(in->s[0]!=PV_MARKER)
119         {
120                 LM_ERR("missing pv marker [%.*s]\n", in->len, in->s);
121                 return -1;
122         }
123         pcount = 0;
124         if(in->s[1]==PV_LNBRACKET)
125         {
126                 /* name with parenthesis: $(...) */
127                 pcount = 1;
128                 for(i=2; i<in->len; i++)
129                 {
130                         if(in->s[i]==PV_LNBRACKET)
131                                 pcount++;
132                         else if(in->s[i]==PV_RNBRACKET)
133                                 pcount--;
134                         if(pcount==0)
135                                 return i+1;
136                 }
137                 /* non-closing name parenthesis */
138                 LM_ERR("non-closing name parenthesis [%.*s]\n",in->len,in->s);
139                 return -1;
140         }
141
142         /* name without parenthesis: $xyz(...) */
143         for(i=1; i<in->len; i++)
144         {
145                 if(!is_pv_valid_char(in->s[i]))
146                 {
147                         if(in->s[i]==PV_LNBRACKET)
148                         {
149                                 /* inner-name parenthesis */
150                                 pcount = 1;
151                                 break;
152                         } else {
153                                 return i;
154                         }
155                 }
156         }
157         if(pcount==0)
158                 return i;
159
160         i++;
161         for( ; i<in->len; i++)
162         {
163                 if(in->s[i]==PV_LNBRACKET)
164                         pcount++;
165                 else if(in->s[i]==PV_RNBRACKET)
166                         pcount--;
167                 if(pcount==0)
168                         return i+1;
169         }
170         /* non-closing inner-name parenthesis */
171         LM_ERR("non-closing inner-name parenthesis [%.*s]\n",in->len,in->s);
172         return -1;
173 }
174
175 /**
176  *
177  */
178 int pv_table_add(pv_export_t *e)
179 {
180         char *p;
181         str  *in;
182         pv_item_t *pvi = NULL;
183         pv_item_t *pvj = NULL;
184         pv_item_t *pvn = NULL;
185         int found;
186         unsigned int pvid;
187
188         if(e==NULL || e->name.s==NULL || e->getf==NULL || e->type==PVT_NONE)
189         {
190                 LM_ERR("invalid parameters\n");
191                 return -1;
192         }
193         
194         if(_pv_table_set==0)
195         {
196                 LM_DBG("PV table not initialized, doing it now\n");
197                 pv_init_table();
198         }
199         in = &(e->name);
200         p = in->s;      
201         while(is_in_str(p,in) && is_pv_valid_char(*p))
202                 p++;
203         if(is_in_str(p,in))
204         {
205                 LM_ERR("invalid char [%c] in [%.*s]\n", *p, in->len, in->s);
206                 return -1;
207         }
208         found = 0;
209         //pvid = get_hash1_raw(in->s, in->len);
210         pvid = get_hash1_raw(in->s, in->len);
211
212         pvi = _pv_table[pvid%PV_TABLE_SIZE];
213         while(pvi)
214         {
215                 if(pvi->pvid > pvid)
216                         break;
217                 if(pvi->pve.name.len==in->len)
218                 {
219                         found = strncmp(pvi->pve.name.s, in->s, in->len);
220
221                         if(found==0)
222                         {
223                                 LM_ERR("pvar [%.*s] already exists\n", in->len, in->s);
224                                 return -1;
225                         }
226                 }
227                 pvj = pvi;
228                 pvi = pvi->next;
229         }
230
231         pvn = (pv_item_t*)pkg_malloc(sizeof(pv_item_t));
232         if(pvn==0)
233         {
234                 LM_ERR("no more memory\n");
235                 return -1;
236         }
237         memset(pvn, 0, sizeof(pv_item_t));
238         memcpy(&(pvn->pve), e, sizeof(pv_export_t));
239         pvn->pvid = pvid;
240
241         if(pvj==0)
242         {
243                 pvn->next = _pv_table[pvid%PV_TABLE_SIZE];
244                 _pv_table[pvid%PV_TABLE_SIZE] = pvn;
245                 goto done;
246         }
247         pvn->next = pvj->next;
248         pvj->next = pvn;
249
250 done:
251         return 0;
252 }
253
254 /**
255  *
256  */
257 pv_spec_t* pv_cache_add(str *name)
258 {
259         pv_cache_t *pvn;
260         unsigned int pvid;
261         char *p;
262
263         if(_pv_cache_set==0)
264         {
265                 LM_DBG("PV cache not initialized, doing it now\n");
266                 pv_init_cache();
267         }
268         pvid = get_hash1_raw(name->s, name->len);
269         pvn = (pv_cache_t*)pkg_malloc(sizeof(pv_cache_t) + name->len + 1);
270         if(pvn==0)
271         {
272                 LM_ERR("no more memory\n");
273                 return NULL;
274         }
275         memset(pvn, 0, sizeof(pv_item_t) + name->len + 1);
276         p = pv_parse_spec(name, &pvn->spec);
277
278         if(p==NULL)
279         {
280                 pkg_free(pvn);
281                 return NULL;
282         }
283         pvn->pvname.len = name->len;
284         pvn->pvname.s = (char*)pvn + sizeof(pv_cache_t);
285         memcpy(pvn->pvname.s, name->s, name->len);
286         pvn->pvid = pvid;
287         pvn->next = _pv_cache[pvid%PV_CACHE_SIZE];
288         _pv_cache[pvid%PV_CACHE_SIZE] = pvn;
289
290         LM_DBG("pvar [%.*s] added in cache\n", name->len, name->s);
291         return &pvn->spec;
292 }
293
294 /**
295  *
296  */
297 pv_spec_t* pv_cache_lookup(str *name)
298 {
299         pv_cache_t *pvi;
300         unsigned int pvid;
301         int found;
302
303         if(_pv_cache_set==0)
304                 return NULL;
305
306         pvid = get_hash1_raw(name->s, name->len);
307         pvi = _pv_cache[pvid%PV_CACHE_SIZE];
308         while(pvi)
309         {
310                 if(pvi->pvid == pvid) {
311                         if(pvi->pvname.len==name->len)
312                         {
313                                 found = strncmp(pvi->pvname.s, name->s, name->len);
314
315                                 if(found==0)
316                                 {
317                                         LM_DBG("pvar [%.*s] found in cache\n",
318                                                         name->len, name->s);
319                                         return &pvi->spec;
320                                 }
321                         }
322                 }
323                 pvi = pvi->next;
324         }
325         return NULL;
326 }
327
328 /**
329  *
330  */
331 pv_spec_t* pv_cache_get(str *name)
332 {
333         pv_spec_t *pvs;
334         str tname;
335
336         if(name->s==NULL || name->len==0)
337         {
338                 LM_ERR("invalid parameters\n");
339                 return NULL;
340         }
341
342         tname.s = name->s;
343         tname.len = pv_locate_name(name);
344
345         if(tname.len < 0)
346                 return NULL;
347
348         pvs = pv_cache_lookup(&tname);
349
350         if(pvs!=NULL)
351                 return pvs;
352
353         return pv_cache_add(&tname);
354 }
355
356 /**
357  *
358  */
359 int register_pvars_mod(char *mod_name, pv_export_t *items)
360 {
361         int ret;
362         int i;
363
364         if (items==0)
365                 return 0;
366
367         for ( i=0 ; items[i].name.s ; i++ ) {
368                 ret = pv_table_add(&items[i]);
369                 if (ret!=0) {
370                         LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
371                                         items[i].name.len, items[i].name.s, mod_name);
372                 }
373         }
374         return 0;
375 }
376
377 /**
378  *
379  */
380 int pv_table_free(void)
381 {
382         pv_item_p xe;
383         pv_item_p xe1;
384         int i;
385
386         for(i=0; i<PV_TABLE_SIZE; i++)
387         {
388                 xe = _pv_table[i];
389                 while(xe!=0)
390                 {
391                         xe1 = xe;
392                         xe = xe->next;
393                         pkg_free(xe1);
394                 }
395         }
396         memset(_pv_table, 0, sizeof(pv_item_t*)*PV_TABLE_SIZE);
397         _pv_table_set = 0;
398         
399         return 0;
400 }
401
402 /********** helper functions ********/
403 /**
404  * convert unsigned int to pv_value_t
405  */
406 int pv_get_uintval(struct sip_msg *msg, pv_param_t *param,
407                 pv_value_t *res, unsigned int uival)
408 {
409         int l = 0;
410         char *ch = NULL;
411
412         if(res==NULL)
413                 return -1;
414
415         ch = int2str(uival, &l);
416         res->rs.s = ch;
417         res->rs.len = l;
418
419         res->ri = (int)uival;
420         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
421         return 0;
422 }
423
424 /**
425  * convert signed int to pv_value_t
426  */
427 int pv_get_sintval(struct sip_msg *msg, pv_param_t *param,
428                 pv_value_t *res, int sival)
429 {
430         int l = 0;
431         char *ch = NULL;
432
433         if(res==NULL)
434                 return -1;
435
436         ch = sint2str(sival, &l);
437         res->rs.s = ch;
438         res->rs.len = l;
439
440         res->ri = sival;
441         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
442         return 0;
443 }
444
445 /**
446  * convert str to pv_value_t
447  */
448 int pv_get_strval(struct sip_msg *msg, pv_param_t *param,
449                 pv_value_t *res, str *sval)
450 {
451         if(res==NULL)
452                 return -1;
453
454         res->rs = *sval;
455         res->flags = PV_VAL_STR;
456         return 0;
457 }
458
459 /**
460  * convert str-int to pv_value_t (type is str)
461  */
462 int pv_get_strintval(struct sip_msg *msg, pv_param_t *param,
463                 pv_value_t *res, str *sval, int ival)
464 {
465         if(res==NULL)
466                 return -1;
467
468         res->rs = *sval;
469         res->ri = ival;
470         res->flags = PV_VAL_STR|PV_VAL_INT;
471         return 0;
472 }
473
474 /**
475  * convert int-str to pv_value_t (type is int)
476  */
477 int pv_get_intstrval(struct sip_msg *msg, pv_param_t *param,
478                 pv_value_t *res, int ival, str *sval)
479 {
480         if(res==NULL)
481                 return -1;
482
483         res->rs = *sval;
484         res->ri = ival;
485         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
486         return 0;
487 }
488
489 /*** ============================= ***/
490 static str pv_str_marker = { PV_MARKER_STR, 1 };
491 static int pv_get_marker(struct sip_msg *msg, pv_param_t *param,
492                 pv_value_t *res)
493 {
494         return pv_get_strintval(msg, param, res, &pv_str_marker,
495                         (int)pv_str_marker.s[0]);
496 }
497
498 static str pv_str_empty  = { "", 0 };
499 static str pv_str_null   = { "<null>", 6 };
500 int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
501 {
502         if(res==NULL)
503                 return -1;
504         
505         res->rs = pv_str_empty;
506         res->ri = 0;
507         res->flags = PV_VAL_NULL;
508         return 0;
509 }
510
511 /**
512  *
513  */
514 pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e)
515 {
516         pv_item_t *pvi;
517         unsigned int pvid;
518
519         if(pvname==0 || e==0)
520         {
521                 LM_ERR("bad parameters\n");
522                 return NULL;
523         }
524
525         /* search in PV table */
526         // pvid = get_hash1_raw(pvname->s, pvname->len);
527         pvid = get_hash1_raw(pvname->s, pvname->len);
528         pvi = _pv_table[pvid%PV_TABLE_SIZE];
529         while(pvi)
530         {
531                 if(pvi->pvid > pvid)
532                         break;
533
534                 if(pvi->pvid==pvid && pvi->pve.name.len==pvname->len
535                         && memcmp(pvi->pve.name.s, pvname->s, pvname->len)==0)
536                 {
537                         /*LM_DBG("found [%.*s] [%d]\n", pvname->len, pvname->s,
538                                         _pv_names_table[i].type);*/
539                         /* copy data from table to spec */
540                         e->type = pvi->pve.type;
541                         e->getf = pvi->pve.getf;
542                         e->setf = pvi->pve.setf;
543                         return &(pvi->pve);
544                 }
545                 pvi = pvi->next;
546         }
547
548         return NULL;
549 }
550
551 /**
552  *
553  */
554 int pv_parse_index(pv_spec_p sp, str *in)
555 {
556         char *p;
557         char *s;
558         int sign;
559         pv_spec_p nsp = 0;
560
561         if(in==NULL || in->s==NULL || sp==NULL)
562                 return -1;
563         p = in->s;
564         if(*p==PV_MARKER)
565         {
566                 nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
567                 if(nsp==NULL)
568                 {
569                         LM_ERR("no more memory\n");
570                         return -1;
571                 }
572                 s = pv_parse_spec(in, nsp);
573                 if(s==NULL)
574                 {
575                         LM_ERR("invalid index [%.*s]\n", in->len, in->s);
576                         pv_spec_free(nsp);
577                         return -1;
578                 }
579                 sp->pvp.pvi.type = PV_IDX_PVAR;
580                 sp->pvp.pvi.u.dval = (void*)nsp;
581                 return 0;
582         }
583         if(*p=='*' && in->len==1)
584         {
585                 sp->pvp.pvi.type = PV_IDX_ALL;
586                 return 0;
587         }
588         sign = 1;
589         if(*p=='-')
590         {
591                 sign = -1;
592                 p++;
593         }
594         sp->pvp.pvi.u.ival = 0;
595         while(p<in->s+in->len && *p>='0' && *p<='9')
596         {
597                 sp->pvp.pvi.u.ival = sp->pvp.pvi.u.ival * 10 + *p - '0';
598                 p++;
599         }
600         if(p!=in->s+in->len)
601         {
602                 LM_ERR("invalid index [%.*s]\n", in->len, in->s);
603                 return -1;
604         }
605         sp->pvp.pvi.u.ival *= sign;
606         sp->pvp.pvi.type = PV_IDX_INT;
607         return 0;
608 }
609
610 /**
611  *
612  */
613 int pv_init_iname(pv_spec_p sp, int param)
614 {
615         if(sp==NULL)
616                 return -1;
617         sp->pvp.pvn.type = PV_NAME_INTSTR;
618         sp->pvp.pvn.u.isname.name.n = param;
619         return 0;
620 }
621
622 /**
623  *
624  */
625 char* pv_parse_spec2(str *in, pv_spec_p e, int silent)
626 {
627         char *p;
628         str s;
629         str pvname;
630         int pvstate;
631         trans_t *tr = NULL;
632         pv_export_t *pte = NULL;
633         int n=0;
634
635         if(in==NULL || in->s==NULL || e==NULL || *in->s!=PV_MARKER)
636         {
637                 if (!silent) LM_ERR("bad parameters\n");
638                 return NULL;
639         }
640         
641         /* LM_DBG("***** input [%.*s] (%d)\n", in->len, in->s, in->len); */
642         tr = 0;
643         pvstate = 0;
644         memset(e, 0, sizeof(pv_spec_t));
645         p = in->s;
646         p++;
647         if(*p==PV_LNBRACKET)
648         {
649                 p++;
650                 pvstate = 1;
651         }
652         pvname.s = p;
653         if(*p == PV_MARKER) {
654                 p++;
655                 if(pvstate==1)
656                 {
657                         if(*p!=PV_RNBRACKET)
658                                 goto error;
659                         p++;
660                 }
661                 e->getf = pv_get_marker;
662                 e->type = PVT_MARKER;
663                 pvname.len = 1;
664                 goto done_all;
665         }
666         while(is_in_str(p,in) && is_pv_valid_char(*p))
667                 p++;
668         pvname.len = p - pvname.s;
669         if(pvstate==1)
670         {
671                 if(*p==PV_RNBRACKET)
672                 { /* full pv name ended here*/
673                         goto done_inm;
674                 } else if(*p==PV_LNBRACKET) {
675                         p++;
676                         pvstate = 2;
677                 } else if(*p==PV_LIBRACKET) {
678                         p++;
679                         pvstate = 3;
680                 } else if(*p==TR_LBRACKET) {
681                         p++;
682                         pvstate = 4;
683                 } else {
684                         if (!silent)
685                                 LM_ERR("invalid char '%c' in [%.*s] (%d)\n",
686                                                         *p, in->len, in->s, pvstate);
687                         goto error;
688                 }
689         } else { 
690                 if(!is_in_str(p, in)) {
691                         p--;
692                         goto done_inm;
693                 } else if(*p==PV_LNBRACKET) {
694                         p++;
695                         pvstate = 5;
696                 } else {
697                         /* still in input str, but end of PV */
698                         /* p is increased at the end, so decrement here */
699                         p--;
700                         goto done_inm;
701                 }
702         }
703
704 done_inm:
705         if((pte = pv_lookup_spec_name(&pvname, e))==NULL)
706         {
707                 if (!silent) 
708                         LM_ERR("error searching pvar \"%.*s\"\n", pvname.len, pvname.s);
709                 goto error;
710         }
711         if(pte->parse_name!=NULL && pvstate!=2 && pvstate!=5)
712         {
713                 if (!silent) 
714                         LM_ERR("pvar \"%.*s\" expects an inner name\n",
715                                                 pvname.len, pvname.s);
716                 goto error;
717         }
718         if(pvstate==2 || pvstate==5)
719         {
720                 if(pte->parse_name==NULL)
721                 {
722                         if (!silent)
723                                 LM_ERR("pvar \"%.*s\" does not get name param\n",
724                                                 pvname.len, pvname.s);
725                         goto error;
726                 }
727                 s.s = p;
728                 n = 0;
729                 while(is_in_str(p, in))
730                 {
731                         if(*p==PV_RNBRACKET)
732                         {
733                                 if(n==0)
734                                         break;
735                                 n--;
736                         }
737                         if(*p == PV_LNBRACKET)
738                                 n++;
739                         p++;
740                 }
741
742                 if(!is_in_str(p, in))
743                         goto error;
744
745                 if(p==s.s)
746                 {
747                         if (!silent)
748                                 LM_ERR("pvar \"%.*s\" does not get empty name param\n",
749                                                 pvname.len, pvname.s);
750                         goto error;
751                 }
752                 s.len = p - s.s;
753                 if(pte->parse_name(e, &s)!=0)
754                 {
755                         if (!silent)
756                                 LM_ERR("pvar \"%.*s\" has an invalid name param [%.*s]\n",
757                                                 pvname.len, pvname.s, s.len, s.s);
758                         goto error;
759                 }
760                 if(pvstate==2)
761                 {
762                         p++;
763                         if(*p==PV_RNBRACKET)
764                         { /* full pv name ended here*/
765                                 goto done_vnm;
766                         } else if(*p==PV_LIBRACKET) {
767                                 p++;
768                                 pvstate = 3;
769                         } else if(*p==TR_LBRACKET) {
770                                 p++;
771                                 pvstate = 4;
772                         } else {
773                                 if (!silent)
774                                         LM_ERR("invalid char '%c' in [%.*s] (%d)\n",
775                                                                 *p, in->len, in->s, pvstate);
776                                 goto error;
777                         }
778                 } else {
779                         if(*p==PV_RNBRACKET)
780                         { /* full pv name ended here*/
781                                 p++;
782                                 goto done_all;
783                         } else {
784                                 if (!silent)
785                                         LM_ERR("invalid char '%c' in [%.*s] (%d)\n",
786                                                                 *p, in->len, in->s, pvstate);
787                                 goto error;
788                         }
789                 }
790         }
791 done_vnm:
792         if(pvstate==3)
793         {
794                 if(pte->parse_index==NULL)
795                 {
796                         if (!silent)
797                                 LM_ERR("pvar \"%.*s\" does not get index param\n",
798                                                 pvname.len, pvname.s);
799                         goto error;
800                 }
801                 s.s = p;
802                 n = 0;
803                 while(is_in_str(p, in))
804                 {
805                         if(*p==PV_RIBRACKET)
806                         {
807                                 if(n==0)
808                                         break;
809                                 n--;
810                         }
811                         if(*p == PV_LIBRACKET)
812                                 n++;
813                         p++;
814                 }
815                 if(!is_in_str(p, in))
816                         goto error;
817
818                 if(p==s.s)
819                 {
820                         if (!silent)
821                                 LM_ERR("pvar \"%.*s\" does not get empty index param\n",
822                                                 pvname.len, pvname.s);
823                         goto error;
824                 }
825                 s.len = p - s.s;
826                 if(pte->parse_index(e, &s)!=0)
827                 {
828                         if (!silent)
829                                 LM_ERR("pvar \"%.*s\" has an invalid index param [%.*s]\n",
830                                                 pvname.len, pvname.s, s.len, s.s);
831                         goto error;
832                 }
833                 p++;
834                 if(*p==PV_RNBRACKET)
835                 { /* full pv name ended here*/
836                         goto done_idx;
837                 } else if(*p==TR_LBRACKET) {
838                         p++;
839                         pvstate = 4;
840                 } else {
841                         if (!silent)
842                                 LM_ERR("invalid char '%c' in [%.*s] (%d)\n",
843                                                         *p, in->len, in->s, pvstate);
844                         goto error;
845                 }
846         }
847 done_idx:
848         if(pvstate==4)
849         {
850                 s.s = p-1;
851                 n = 0;
852                 while(is_in_str(p, in))
853                 {
854                         if(*p==TR_RBRACKET)
855                         {
856                                 if(n==0)
857                                 {
858                                         /* yet another transformation */
859                                         p++;
860                                         while(is_in_str(p, in) && (*p==' ' || *p=='\t')) p++;
861
862                                         if(!is_in_str(p, in) || *p != TR_LBRACKET)
863                                         {
864                                                 p--;
865                                                 break;
866                                         }
867                                 }
868                                 n--;
869                         }
870                         if(*p == TR_LBRACKET)
871                                 n++;
872                         p++;
873                 }
874                 if(!is_in_str(p, in))
875                         goto error;
876
877                 if(p==s.s)
878                 {
879                         if (!silent)
880                                 LM_ERR("pvar \"%.*s\" does not get empty index param\n",
881                                                 pvname.len, pvname.s);
882                         goto error;
883                 }
884                 s.len = p - s.s + 1;
885
886                 p = tr_lookup(&s, &tr);
887                 if(p==NULL)
888                 {
889                         if (!silent)
890                                 LM_ERR("bad tr in pvar name \"%.*s\"\n", pvname.len, pvname.s);
891                         goto error;
892                 }
893                 if(*p!=PV_RNBRACKET)
894                 {
895                         if (!silent)
896                                 LM_ERR("bad pvar name \"%.*s\" (%c)!\n", in->len, in->s, *p);
897                         goto error;
898                 }
899                 e->trans = (void*)tr;
900         }
901         p++;
902
903 done_all:
904         if(pte!=NULL && pte->init_param)
905                 pte->init_param(e, pte->iparam);
906         return p;
907
908 error:
909         if(p!=NULL){
910                 if (!silent)
911                         LM_ERR("wrong char [%c/%d] in [%.*s] at [%d (%d)]\n", *p, (int)*p,
912                                         in->len, in->s, (int)(p-in->s), pvstate);
913         }else{
914                 if (!silent)
915                         LM_ERR("invalid parsing in [%.*s] at (%d)\n",
916                                                 in->len, in->s, pvstate);
917         }
918         return NULL;
919
920 } /* end: pv_parse_spec */
921
922 /**
923  *
924  */
925 int pv_parse_format(str *in, pv_elem_p *el)
926 {
927         char *p, *p0;
928         int n = 0;
929         pv_elem_p e, e0;
930         str s;
931
932         if(in==NULL || in->s==NULL || el==NULL)
933                 return -1;
934
935         /*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/
936         
937         if(in->len == 0)
938         {
939                 *el = pkg_malloc(sizeof(pv_elem_t));
940                 if(*el == NULL)
941                         goto error;
942                 memset(*el, 0, sizeof(pv_elem_t));
943                 (*el)->text = *in;
944                 return 0;
945         }
946
947         p = in->s;
948         *el = NULL;
949         e = e0 = NULL;
950
951         while(is_in_str(p,in))
952         {
953                 e0 = e;
954                 e = pkg_malloc(sizeof(pv_elem_t));
955                 if(!e)
956                         goto error;
957                 memset(e, 0, sizeof(pv_elem_t));
958                 n++;
959                 if(*el == NULL)
960                         *el = e;
961                 if(e0)
962                         e0->next = e;
963         
964                 e->text.s = p;
965                 while(is_in_str(p,in) && *p!=PV_MARKER)
966                         p++;
967                 e->text.len = p - e->text.s;
968                 
969                 if(*p == '\0' || !is_in_str(p,in))
970                         break;
971                 s.s = p;
972                 s.len = in->s+in->len-p;
973                 p0 = pv_parse_spec(&s, &e->spec);
974                 
975                 if(p0==NULL)
976                         goto error;
977                 if(*p0 == '\0')
978                         break;
979                 p = p0;
980         }
981         /*LM_DBG("format parsed OK: [%d] items\n", n);*/
982
983         if(*el == NULL)
984                 return -1;
985
986         return 0;
987
988 error:
989         pv_elem_free_all(*el);
990         *el = NULL;
991         return -1;
992 }
993
994 /**
995  *
996  */
997 int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name)
998 {
999         if(msg==NULL || ip==NULL || name==NULL)
1000                 return -1;
1001         memset(name, 0, sizeof(pv_value_t));
1002
1003         if(ip->pvn.type==PV_NAME_INTSTR)
1004         {
1005                 if(ip->pvn.u.isname.type&AVP_NAME_STR)
1006                 {
1007                         name->rs = ip->pvn.u.isname.name.s;
1008                         name->flags = PV_VAL_STR;
1009                 } else {
1010                         name->ri = ip->pvn.u.isname.name.n;
1011                         name->flags = PV_VAL_INT|PV_TYPE_INT;
1012                 }
1013                 return 0;
1014         } else if(ip->pvn.type==PV_NAME_PVAR) {
1015                 /* pvar */
1016                 if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), name)!=0)
1017                 {
1018                         LM_ERR("cannot get name value\n");
1019                         return -1;
1020                 }
1021                 if(name->flags&PV_VAL_NULL || name->flags&PV_VAL_EMPTY)
1022                 {
1023                         LM_ERR("null or empty name\n");
1024                         return -1;
1025                 }
1026                 return 0;
1027         }
1028         LM_ERR("name type is PV_NAME_OTHER - cannot resolve\n");
1029         return -1;
1030 }
1031
1032 /**
1033  * parse AVP name
1034  * @return 0 on success, -1 on error
1035  */
1036 int pv_parse_avp_name(pv_spec_p sp, str *in)
1037 {
1038         char *p;
1039         char *s;
1040         pv_spec_p nsp = 0;
1041
1042         if(in==NULL || in->s==NULL || sp==NULL)
1043                 return -1;
1044         p = in->s;
1045         if(*p==PV_MARKER)
1046         {
1047                 nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
1048                 if(nsp==NULL)
1049                 {
1050                         LM_ERR("no more memory\n");
1051                         return -1;
1052                 }
1053                 s = pv_parse_spec(in, nsp);
1054                 if(s==NULL)
1055                 {
1056                         LM_ERR("invalid name [%.*s]\n", in->len, in->s);
1057                         pv_spec_free(nsp);
1058                         return -1;
1059                 }
1060                 //LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
1061                 //pv_print_spec(nsp);
1062                 sp->pvp.pvn.type = PV_NAME_PVAR;
1063                 sp->pvp.pvn.u.dname = (void*)nsp;
1064                 return 0;
1065         }
1066         /*LM_DBG("static name [%.*s]\n", in->len, in->s);*/
1067         if(km_parse_avp_spec(in, &sp->pvp.pvn.u.isname.type,
1068                                           &sp->pvp.pvn.u.isname.name)!=0)
1069         {
1070                 LM_ERR("bad avp name [%.*s]\n", in->len, in->s);
1071                 return -1;
1072         }
1073         sp->pvp.pvn.type = PV_NAME_INTSTR;
1074         return 0;
1075 }
1076
1077 /**
1078  * fill avp name details (id and type)
1079  * @return 0 on success, -1 on error
1080  */
1081 int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int_str *avp_name,
1082                 unsigned short *name_type)
1083 {
1084         pv_value_t tv;
1085         if(ip==NULL || avp_name==NULL || name_type==NULL)
1086                 return -1;
1087         memset(avp_name, 0, sizeof(int_str));
1088         *name_type = 0;
1089
1090         if(ip->pvn.type==PV_NAME_INTSTR)
1091         {
1092                 *name_type = ip->pvn.u.isname.type;
1093                 if(ip->pvn.u.isname.type&AVP_NAME_STR)
1094                 {
1095                         avp_name->s = ip->pvn.u.isname.name.s;
1096                         *name_type |= AVP_NAME_STR;
1097                 } else {
1098                         avp_name->n = ip->pvn.u.isname.name.n;
1099                         /* *name_type &= AVP_SCRIPT_MASK; */
1100                         *name_type = 0;
1101                 }
1102                 return 0;
1103         }
1104         /* pvar */
1105         if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), &tv)!=0)
1106         {
1107                 LM_ERR("cannot get avp value\n");
1108                 return -1;
1109         }
1110         if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY)
1111         {
1112                 LM_ERR("null or empty name\n");
1113                 return -1;
1114         }
1115                 
1116         if((tv.flags&PV_TYPE_INT) && (tv.flags&PV_VAL_INT))
1117         {
1118                 avp_name->n = tv.ri;
1119         } else {
1120                 avp_name->s = tv.rs;
1121                 *name_type = AVP_NAME_STR;
1122         }
1123         return 0;
1124 }
1125
1126 /**
1127  *
1128  */
1129 int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags)
1130 {
1131         pv_value_t tv;
1132         if(ip==NULL || idx==NULL || flags==NULL)
1133                 return -1;
1134
1135         *idx = 0;
1136         *flags = 0;
1137
1138         if(ip->pvi.type == PV_IDX_ALL) {
1139                 *flags = PV_IDX_ALL;
1140                 return 0;
1141         }
1142         
1143         if(ip->pvi.type == PV_IDX_INT)
1144         {
1145                 *idx = ip->pvi.u.ival;
1146                 return 0;
1147         }
1148
1149         /* pvar */
1150         if(pv_get_spec_value(msg, (pv_spec_p)ip->pvi.u.dval, &tv)!=0)
1151         {
1152                 LM_ERR("cannot get index value\n");
1153                 return -1;
1154         }
1155         if(!(tv.flags&PV_VAL_INT))
1156         {
1157                 LM_ERR("invalid index value\n");
1158                 return -1;
1159         }
1160         *idx = tv.ri;
1161         return 0;
1162 }
1163
1164 /**
1165  *
1166  */
1167 int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
1168 {
1169         int ret = 0;
1170
1171         if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
1172                         || sp->type==PVT_NONE)
1173         {
1174                 LM_ERR("bad parameters\n");
1175                 return -1;
1176         }
1177         
1178         memset(value, 0, sizeof(pv_value_t));
1179
1180         ret = (*sp->getf)(msg, &(sp->pvp), value);
1181         if(ret!=0)
1182                 return ret;
1183                 
1184         if(sp->trans)
1185                 return tr_exec(msg, (trans_t*)sp->trans, value);
1186         return ret;
1187 }
1188
1189 /**
1190  *
1191  */
1192 int pv_set_spec_value(struct sip_msg* msg, pv_spec_p sp, int op,
1193                 pv_value_t *value)
1194 {
1195         if(sp==NULL || !pv_is_w(sp))
1196                 return 0; /* no op */
1197         if(pv_alter_context(sp) && is_route_type(LOCAL_ROUTE))
1198                 return 0; /* no op */
1199         return sp->setf(msg, &sp->pvp, op, value);
1200 }
1201
1202 /**
1203  *
1204  */
1205 int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
1206 {
1207         int n;
1208         pv_value_t tok;
1209         pv_elem_p it;
1210         char *cur;
1211         
1212         if(msg==NULL || list==NULL || buf==NULL || len==NULL)
1213                 return -1;
1214
1215         if(*len <= 0)
1216                 return -1;
1217
1218         *buf = '\0';
1219         cur = buf;
1220         
1221         n = 0;
1222         for (it=list; it; it=it->next)
1223         {
1224                 /* put the text */
1225                 if(it->text.s && it->text.len>0)
1226                 {
1227                         if(n+it->text.len < *len)
1228                         {
1229                                 memcpy(cur, it->text.s, it->text.len);
1230                                 n += it->text.len;
1231                                 cur += it->text.len;
1232                         } else {
1233                                 LM_ERR("no more space for text [%d]\n", it->text.len);
1234                                 goto overflow;
1235                         }
1236                 }
1237                 /* put the value of the specifier */
1238                 if(it->spec.type!=PVT_NONE
1239                                 && pv_get_spec_value(msg, &(it->spec), &tok)==0)
1240                 {
1241                         if(tok.flags&PV_VAL_NULL)
1242                                 tok.rs = pv_str_null;
1243                         if(n+tok.rs.len < *len)
1244                         {
1245                                 if(tok.rs.len>0)
1246                                 {
1247                                         memcpy(cur, tok.rs.s, tok.rs.len);
1248                                         n += tok.rs.len;
1249                                         cur += tok.rs.len;
1250                                 }
1251                         } else {
1252                                 LM_ERR("no more space for spec value\n");
1253                                 goto overflow;
1254                         }
1255                 }
1256         }
1257
1258         goto done;
1259         
1260 overflow:
1261         LM_ERR("buffer overflow -- increase the buffer size...\n");
1262         return -1;
1263
1264 done:
1265 #ifdef EXTRA_DEBUG
1266         LM_DBG("final buffer length %d\n", n);
1267 #endif
1268         *cur = '\0';
1269         *len = n;
1270         return 0;
1271 }
1272
1273 /**
1274  *
1275  */
1276 pvname_list_t* parse_pvname_list(str *in, unsigned int type)
1277 {
1278         pvname_list_t* head = NULL;
1279         pvname_list_t* al = NULL;
1280         pvname_list_t* last = NULL;
1281         char *p;
1282         pv_spec_t spec;
1283         str s;
1284
1285         if(in==NULL || in->s==NULL)
1286         {
1287                 LM_ERR("bad parameters\n");
1288                 return NULL;
1289         }
1290
1291         p = in->s;
1292         while(is_in_str(p, in))
1293         {
1294                 while(is_in_str(p, in) && (*p==' '||*p=='\t'||*p==','||*p==';'||*p=='\n'))
1295                         p++;
1296                 if(!is_in_str(p, in))
1297                 {
1298                         if(head==NULL)
1299                                 LM_ERR("parse error in name list [%.*s]\n", in->len, in->s);
1300                         return head;
1301                 }
1302                 s.s = p;
1303                 s.len = in->s + in->len - p;
1304                 p = pv_parse_spec(&s, &spec);
1305                 if(p==NULL)
1306                 {
1307                         LM_ERR("parse error in item [%.*s]\n", s.len, s.s);
1308                         goto error;
1309                 }
1310                 if(type && spec.type!=type)
1311                 {
1312                         LM_ERR("wrong type for item [%.*s]\n", (int)(p-s.s), s.s);
1313                         goto error;
1314                 }
1315                 al = (pvname_list_t*)pkg_malloc(sizeof(pvname_list_t));
1316                 if(al==NULL)
1317                 {
1318                         LM_ERR("no more memory!\n");
1319                         goto error;
1320                 }
1321                 memset(al, 0, sizeof(pvname_list_t));
1322                 memcpy(&al->sname, &spec, sizeof(pv_spec_t));
1323
1324                 if(last==NULL)
1325                 {
1326                         head = al;
1327                         last = al;
1328                 } else {
1329                         last->next = al;
1330                         last = al;
1331                 }
1332         }
1333
1334         return head;
1335
1336 error:
1337         while(head)
1338         {
1339                 al = head;
1340                 head=head->next;
1341                 pkg_free(al);
1342         }
1343         return NULL;
1344 }
1345
1346
1347
1348 /** destroy the content of pv_spec_t structure.
1349  */
1350 void pv_spec_destroy(pv_spec_t *spec)
1351 {
1352         if(spec==0) return;
1353         /* free name if it is PV */
1354         if(spec->pvp.pvn.nfree)
1355                 spec->pvp.pvn.nfree((void*)(&spec->pvp.pvn));
1356         if(spec->trans)
1357                 tr_free((trans_t*)spec->trans);
1358 }
1359
1360 /** free the pv_spec_t structure.
1361  */
1362 void pv_spec_free(pv_spec_t *spec)
1363 {
1364         if(spec==0) return;
1365         pv_spec_destroy(spec);
1366         pkg_free(spec);
1367 }
1368
1369 /**
1370  *
1371  */
1372 int pv_elem_free_all(pv_elem_p log)
1373 {
1374         pv_elem_p t;
1375         while(log)
1376         {
1377                 t = log;
1378                 log = log->next;
1379                 pkg_free(t);
1380         }
1381         return 0;
1382 }
1383
1384 /**
1385  *
1386  */
1387 void pv_value_destroy(pv_value_t *val)
1388 {
1389         if(val==0) return;
1390         if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
1391         if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
1392         memset(val, 0, sizeof(pv_value_t));
1393 }
1394
1395 int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s)
1396 {
1397         s->s = pv_get_buffer();
1398         s->len = pv_get_buffer_size();
1399         return pv_printf( msg, list, s->s, &s->len);
1400 }
1401
1402 /********************************************************
1403  * Transformations API
1404  ********************************************************/
1405
1406 /**
1407  *
1408  */
1409 static inline char* tr_get_class(str *in, char *p, str *tclass)
1410 {
1411         tclass->s = p;
1412         while(is_in_str(p, in) && *p!=TR_CLASS_MARKER) p++;
1413         if(*p!=TR_CLASS_MARKER || tclass->s == p)
1414         {
1415                 LM_ERR("invalid transformation: %.*s (%c)!\n", in->len, in->s, *p);
1416                 return NULL;
1417         }
1418         tclass->len = p - tclass->s;
1419         p++;
1420
1421         return p;
1422 }
1423
1424 /**
1425  *
1426  */
1427 static inline trans_t* tr_new(void)
1428 {
1429         trans_t *t = NULL;
1430
1431         t = (trans_t*)pkg_malloc(sizeof(trans_t));
1432         if(t == NULL)
1433         {
1434                 LM_ERR("no more private memory\n");
1435                 return NULL;
1436         }
1437         memset(t, 0, sizeof(trans_t));
1438         return t;
1439 }
1440
1441 char* tr_lookup(str *in, trans_t **tr)
1442 {
1443         char *p;
1444         char *p0;
1445         str tclass;
1446         tr_export_t *te = NULL; 
1447         trans_t *t = NULL;
1448         trans_t *t0 = NULL;
1449         str s;
1450
1451         if(in==NULL || in->s==NULL || tr==NULL)
1452                 return NULL;
1453         
1454         p = in->s;
1455         do {
1456                 while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
1457                 if(*p != TR_LBRACKET)
1458                         break;
1459                 p++;
1460
1461                 if((t = tr_new())==NULL) return NULL;
1462
1463                 if(t0==NULL) *tr = t;
1464                 else t0->next = t;
1465                 t0 = t;
1466
1467                 /* find transformation class */
1468                 p = tr_get_class(in, p, &tclass);
1469                 if(p==NULL) goto error;
1470
1471                 /* locate transformation */
1472                 te = tr_lookup_class(&tclass);
1473                 if(te==NULL)
1474                 {
1475                         LM_ERR("unknown transformation: [%.*s] in [%.*s]\n",
1476                                 tclass.len, tclass.s, in->len, in->s);
1477                         goto error;
1478                 }
1479
1480                 s.s = p; s.len = in->s + in->len - p;
1481                 p0 = te->tparse(&s, t);
1482                 if(p0==NULL)
1483                         goto error;
1484                 p = p0;
1485
1486                 if(*p != TR_RBRACKET)
1487                 {
1488                         LM_ERR("invalid transformation: %.*s | %c !!\n", in->len,
1489                                         in->s, *p);
1490                         goto error;
1491                 }
1492
1493                 p++;
1494                 if(!is_in_str(p, in))
1495                         break;
1496         } while(1);
1497
1498         return p;
1499 error:
1500         LM_ERR("error parsing [%.*s]\n", in->len, in->s);
1501         t = *tr;
1502         while(t)
1503         {
1504                 t0 = t;
1505                 t = t->next;
1506                 tr_destroy(t0);
1507                 pkg_free(t0);
1508         }
1509         return NULL;
1510 }
1511
1512 /*!
1513  * \brief Destroy transformation including eventual parameter
1514  * \param t transformation
1515  */
1516 void tr_destroy(trans_t *t)
1517 {
1518         tr_param_t *tp;
1519         tr_param_t *tp0;
1520         if(t==NULL) return;
1521
1522         tp = t->params;
1523         while(tp)
1524         {
1525                 tp0 = tp;
1526                 tp = tp->next;
1527                 tr_param_free(tp0);
1528         }
1529         memset(t, 0, sizeof(trans_t));
1530 }
1531
1532 /*!
1533  * \brief Exec transformation on a pseudo-variable value
1534  * \param msg SIP message
1535  * \param t one or more transformations
1536  * \param v pseudo-variable value
1537  * \return 0 on success, -1 on error
1538  */
1539 int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v)
1540 {
1541         int r;
1542         trans_t *i;
1543
1544         if(t==NULL || v==NULL)
1545         {
1546                 LM_DBG("invalid parameters\n");
1547                 return -1;
1548         }
1549         
1550         for(i = t; i!=NULL; i=i->next)
1551         {
1552                 r = (*i->trf)(msg, i->params, i->subtype, v);
1553                 if(r!=0)
1554                         return r;
1555         }
1556         return 0;
1557 }
1558
1559 /*!
1560  * \brief Free allocated memory of transformation list
1561  * \param t transformation list
1562  */
1563 void tr_free(trans_t *t)
1564 {
1565         trans_t *t0;
1566
1567         while(t)
1568         {
1569                 t0 = t;
1570                 t = t->next;
1571                 tr_destroy(t0);
1572                 pkg_free(t0);
1573         }
1574 }
1575
1576
1577 /*!
1578  * \brief Free transformation parameter list
1579  * \param tp transformation list
1580  */
1581 void tr_param_free(tr_param_t *tp)
1582 {
1583         tr_param_t *tp0;
1584
1585         if(tp==NULL) return;
1586         while(tp)
1587         {
1588                 tp0 = tp;
1589                 tp = tp->next;
1590                 if(tp0->type==TR_PARAM_SPEC)
1591                         pv_spec_free((pv_spec_t*)tp0->v.data);
1592                 pkg_free(tp0);
1593         }
1594 }
1595
1596 typedef struct _tr_item
1597 {
1598         tr_export_t tre;
1599         unsigned int trid;
1600         struct _tr_item *next;
1601 } tr_item_t, *tr_item_p;
1602
1603 static tr_item_t* _tr_table[TR_TABLE_SIZE];
1604 static int _tr_table_set = 0;
1605
1606
1607 /**
1608  *
1609  */
1610 void tr_init_table(void)
1611 {
1612         memset(_tr_table, 0, sizeof(tr_item_t*)*TR_TABLE_SIZE);
1613         _tr_table_set = 1;
1614 }
1615
1616 /**
1617  *
1618  */
1619 int tr_table_add(tr_export_t *e)
1620 {
1621         tr_item_t *tri = NULL;
1622         tr_item_t *trj = NULL;
1623         tr_item_t *trn = NULL;
1624         int found;
1625         unsigned int trid;
1626
1627         if(e==NULL || e->tclass.s==NULL)
1628         {
1629                 LM_ERR("invalid parameters\n");
1630                 return -1;
1631         }
1632         
1633         if(_tr_table_set==0)
1634         {
1635                 LM_DBG("TR table not initialized, doing it now\n");
1636                 tr_init_table();
1637         }
1638
1639         found = 0;
1640         // trid = get_hash1_raw(e->tclass.s, e->tclass.len);
1641         trid = get_hash1_raw(e->tclass.s, e->tclass.len);
1642
1643         tri = _tr_table[trid%TR_TABLE_SIZE];
1644         while(tri)
1645         {
1646                 if(tri->tre.tclass.len==e->tclass.len)
1647                 {
1648                         found = strncmp(tri->tre.tclass.s, e->tclass.s, e->tclass.len);
1649                         if(found==0)
1650                         {
1651                                 LM_ERR("TR class [%.*s] already exists\n", e->tclass.len,
1652                                                 e->tclass.s);
1653                                 return -1;
1654                         }
1655                 }
1656                 trj = tri;
1657                 tri = tri->next;
1658         }
1659
1660         trn = (tr_item_t*)pkg_malloc(sizeof(tr_item_t));
1661         if(trn==0)
1662         {
1663                 LM_ERR("no more memory\n");
1664                 return -1;
1665         }
1666         memset(trn, 0, sizeof(tr_item_t));
1667         memcpy(&(trn->tre), e, sizeof(tr_export_t));
1668         trn->trid = trid;
1669
1670         //LM_DBG("TR class [%.*s] added to entry [%d]\n", e->tclass.len,
1671         //                                      e->tclass.s, trid%TR_TABLE_SIZE);
1672         if(trj==0)
1673         {
1674                 trn->next = _tr_table[trid%TR_TABLE_SIZE];
1675                 _tr_table[trid%TR_TABLE_SIZE] = trn;
1676                 goto done;
1677         }
1678         trn->next = trj->next;
1679         trj->next = trn;
1680
1681 done:
1682         return 0;
1683 }
1684
1685 /**
1686  *
1687  */
1688 int register_trans_mod(char *mod_name, tr_export_t *items)
1689 {
1690         int ret;
1691         int i;
1692
1693         if (items==0)
1694                 return 0;
1695
1696         for ( i=0 ; items[i].tclass.s ; i++ ) {
1697                 ret = tr_table_add(&items[i]);
1698                 if (ret!=0) {
1699                         LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
1700                                         items[i].tclass.len, items[i].tclass.s, mod_name);
1701                 }
1702         }
1703         return 0;
1704 }
1705
1706 /**
1707  *
1708  */
1709 int tr_table_free(void)
1710 {
1711         tr_item_p te;
1712         tr_item_p te1;
1713         int i;
1714
1715         for(i=0; i<TR_TABLE_SIZE; i++)
1716         {
1717                 te = _tr_table[i];
1718                 while(te!=0)
1719                 {
1720                         te1 = te;
1721                         te = te->next;
1722                         pkg_free(te1);
1723                 }
1724         }
1725         memset(_tr_table, 0, sizeof(tr_item_t*)*TR_TABLE_SIZE);
1726         _tr_table_set = 0;
1727         
1728         return 0;
1729 }
1730
1731 /**
1732  *
1733  */
1734 tr_export_t* tr_lookup_class(str *tclass)
1735 {
1736         tr_item_t *tri;
1737         unsigned int trid;
1738
1739         if(tclass==0 || tclass->s==0)
1740         {
1741                 LM_ERR("bad parameters\n");
1742                 return NULL;
1743         }
1744
1745         /* search in TR table */
1746         // trid = get_hash1_raw(tclass->s, tclass->len);
1747         trid = get_hash1_raw(tclass->s, tclass->len);
1748         tri = _tr_table[trid%TR_TABLE_SIZE];
1749         while(tri)
1750         {
1751                 if(tri->trid==trid && tri->tre.tclass.len==tclass->len
1752                                 && memcmp(tri->tre.tclass.s, tclass->s, tclass->len)==0)
1753                         return &(tri->tre);
1754                 tri = tri->next;
1755         }
1756
1757         return NULL;
1758 }
1759
1760
1761 /********************************************************
1762  * core PVs, initialization and destroy APIs
1763  ********************************************************/
1764
1765 static pv_export_t _core_pvs[] = {
1766         {{"null", (sizeof("null")-1)}, /* */
1767                 PVT_NULL, pv_get_null, 0,
1768                 0, 0, 0, 0},
1769
1770         { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
1771 };
1772
1773 /** init pv api (optional).
1774  * @return 0 on success, -1 on error
1775  */
1776 int pv_init_api(void)
1777 {
1778         pv_init_table();
1779         tr_init_table();
1780         if(pv_init_buffer()<0)
1781                 return -1;
1782         if(register_pvars_mod("core", _core_pvs)<0)
1783                 return -1;
1784         return 0;
1785 }
1786
1787
1788 /** destroy pv api. */
1789 void pv_destroy_api(void)
1790 {
1791         /* free PV and TR hash tables */
1792         pv_table_free();
1793         tr_table_free();
1794         pv_destroy_buffer();
1795         return;
1796 }
1797
1798 /**
1799  * - buffer to print PVs
1800  */
1801 static char **_pv_print_buffer = NULL;
1802 #define PV_DEFAULT_PRINT_BUFFER_SIZE 1024
1803 static int _pv_print_buffer_size  = PV_DEFAULT_PRINT_BUFFER_SIZE;
1804 /* 6 mod params + 4 direct usage from mods */
1805 #define PV_DEFAULT_PRINT_BUFFER_SLOTS 10
1806 static int _pv_print_buffer_slots = PV_DEFAULT_PRINT_BUFFER_SLOTS;
1807 static int _pv_print_buffer_index = 0;
1808
1809 /**
1810  *
1811  */
1812 int pv_init_buffer(void)
1813 {
1814         int i;
1815
1816         /* already initialized ?!? */
1817         if(_pv_print_buffer!=NULL)
1818                 return 0;
1819
1820         _pv_print_buffer =
1821                 (char**)pkg_malloc(_pv_print_buffer_slots*sizeof(char*));
1822         if(_pv_print_buffer==NULL)
1823         {
1824                 LM_ERR("cannot init PV print buffer slots\n");
1825                 return -1;
1826         }
1827         memset(_pv_print_buffer, 0, _pv_print_buffer_slots*sizeof(char*));
1828         for(i=0; i<_pv_print_buffer_slots; i++)
1829         {
1830                 _pv_print_buffer[i] =
1831                         (char*)pkg_malloc(_pv_print_buffer_size*sizeof(char));
1832                 if(_pv_print_buffer[i]==NULL)
1833                 {
1834                         LM_ERR("cannot init PV print buffer slot[%d]\n", i);
1835                         return -1;
1836                 }
1837         }
1838         LM_DBG("PV print buffer initialized to [%d][%d]\n",
1839                         _pv_print_buffer_slots, _pv_print_buffer_size);
1840         return 0;
1841 }
1842
1843 /**
1844  *
1845  */
1846 void pv_destroy_buffer(void)
1847 {
1848         int i;
1849
1850         if(_pv_print_buffer==NULL)
1851                 return;
1852         for(i=0; i<_pv_print_buffer_slots; i++)
1853         {
1854                 if(_pv_print_buffer[i]!=NULL)
1855                         pkg_free(_pv_print_buffer[i]);
1856         }
1857         pkg_free(_pv_print_buffer);
1858         _pv_print_buffer = NULL;
1859 }
1860
1861 /**
1862  *
1863  */
1864 int pv_reinit_buffer(void)
1865 {
1866         if(_pv_print_buffer_size==PV_DEFAULT_PRINT_BUFFER_SIZE
1867                         && _pv_print_buffer_slots==PV_DEFAULT_PRINT_BUFFER_SLOTS)
1868                 return 0;
1869         pv_destroy_buffer();
1870         return pv_init_buffer();
1871 }
1872
1873 /**
1874  *
1875  */
1876 char* pv_get_buffer(void)
1877 {
1878         char *p;
1879
1880         p = _pv_print_buffer[_pv_print_buffer_index];
1881         _pv_print_buffer_index = (_pv_print_buffer_index+1)%_pv_print_buffer_slots;
1882
1883         return p;
1884 }
1885
1886 /**
1887  *
1888  */
1889 int pv_get_buffer_size(void)
1890 {
1891         return _pv_print_buffer_size;
1892 }
1893
1894 /**
1895  *
1896  */
1897 int pv_get_buffer_slots(void)
1898 {
1899         return _pv_print_buffer_slots;
1900 }
1901
1902 /**
1903  *
1904  */
1905 void pv_set_buffer_size(int n)
1906 {
1907         _pv_print_buffer_size = n;
1908         if(_pv_print_buffer_size<=0)
1909                 _pv_print_buffer_size = PV_DEFAULT_PRINT_BUFFER_SIZE;
1910 }
1911
1912 /**
1913  *
1914  */
1915 void pv_set_buffer_slots(int n)
1916 {
1917         _pv_print_buffer_slots = n;
1918         if(_pv_print_buffer_slots<=0)
1919                 _pv_print_buffer_slots = PV_DEFAULT_PRINT_BUFFER_SLOTS;
1920 }