5d433f2060f8206131d3a5ed7748f83e0257192c
[sip-router] / lvalue.c
1 /* 
2  * $Id$
3  * 
4  * Copyright (C) 2008 iptelorg GmbH
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /**
19  * @file 
20  * @brief lvalues (assignment)
21  */
22 /* 
23  * History:
24  * --------
25  *  2008-11-30  initial version (andrei)
26  *  2009-04-24  delete avps after finding their new value and not before
27  *               (fixed $avp=$avp)
28  *              when assigning something undefined (e.g. non-existing avp),
29  *              delete the lvalue (similar to perl)  (andrei)
30  */
31
32 /*!
33  * \file
34  * \brief SIP-router core :: 
35  * \ingroup core
36  * Module: \ref core
37  */
38
39 #include "lvalue.h"
40 #include "dprint.h"
41 #include "route.h"
42
43
44
45 /** eval rve and assign the result to an avp
46  * lv->lv.avp=eval(rve)
47  *
48  * based on do_action() ASSIGN_T
49  *
50  * @param h  - script context
51  * @param msg - sip msg
52  * @param lv - lvalue
53  * @param rve - rvalue expression
54  * @return >= 0 on success (expr. bool value), -1 on error
55  */
56 inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
57                                                                         struct lvalue* lv, struct rvalue* rv)
58 {
59         avp_spec_t* avp;
60         avp_t* r_avp;
61         avp_t* avp_mark;
62         pv_value_t pval;
63         int_str value;
64         unsigned short flags;
65         struct search_state st;
66         int ret, v, destroy_pval;
67         int avp_add;
68
69 #if 0
70         #define AVP_ASSIGN_NOVAL() \
71                 /* unknown value => reset the avp in function of its type */ \
72                 flags=avp->type; \
73                 if (flags & AVP_VAL_STR){ \
74                         value.s.s=""; \
75                         value.s.len=0; \
76                 }else{ \
77                         value.n=0; \
78                 }
79 #endif
80         #define AVP_ASSIGN_NOVAL() \
81                 /* no value => delete avp */ \
82                 avp_add=0
83         
84         destroy_pval=0;
85         flags = 0;
86         avp=&lv->lv.avps;
87         ret=0;
88         avp_add=1;
89         
90         switch(rv->type){
91                 case RV_NONE:
92                         BUG("non-intialized rval / rval expr \n");
93                         /* unknown value => reset the avp in function of its type */
94                         flags=avp->type;
95                         AVP_ASSIGN_NOVAL();
96                         ret=-1;
97                         break;
98                 case RV_INT:
99                         value.n=rv->v.l;
100                         flags=avp->type & ~AVP_VAL_STR;
101                         ret=!(!value.n);
102                         break;
103                 case RV_STR:
104                         value.s=rv->v.s;
105                         flags=avp->type | AVP_VAL_STR;
106                         ret=(value.s.len>0);
107                         break;
108                 case RV_ACTION_ST:
109                         flags=avp->type & ~AVP_VAL_STR;
110                         if (rv->v.action) {
111                                 value.n=run_actions_safe(h, rv->v.action, msg);
112                                 h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
113                                                                                                                     break in expr*/
114                         } else
115                                 value.n=-1;
116                         ret=value.n;
117                         break;
118                 case RV_BEXPR: /* logic/boolean expr. */
119                         value.n=eval_expr(h, rv->v.bexpr, msg);
120                         if (unlikely(value.n<0)){
121                                 if (value.n==EXPR_DROP) /* hack to quit on drop */
122                                         goto drop;
123                                 WARN("error in expression\n");
124                                 value.n=0; /* expr. is treated as false */
125                         }
126                         flags=avp->type & ~AVP_VAL_STR;
127                         ret=value.n;
128                         break;
129                 case RV_SEL:
130                         flags=avp->type|AVP_VAL_STR;
131                         v=run_select(&value.s, &rv->v.sel, msg);
132                         if (unlikely(v!=0)){
133                                 value.s.s="";
134                                 value.s.len=0;
135                                 if (v<0){
136                                         ret=-1;
137                                         break;
138                                 } /* v>0 */
139                         }
140                         ret=(value.s.len>0);
141                         break;
142                 case RV_AVP:
143                         avp_mark=0;
144                         if (unlikely((rv->v.avps.type & AVP_INDEX_ALL) == AVP_INDEX_ALL)){
145                                 /* special case: add the value to the avp */
146                                 r_avp = search_first_avp(rv->v.avps.type, rv->v.avps.name,
147                                                                                         &value, &st);
148                                 while(r_avp){
149                                         /* We take only the val type  from the source avp
150                                          * and reset the class, track flags and name type  */
151                                         flags=(avp->type & ~(AVP_INDEX_ALL|AVP_VAL_STR)) | 
152                                                         (r_avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL|
153                                                                                                 AVP_NAME_STR|AVP_NAME_RE));
154                                         if (add_avp_before(avp_mark, flags, avp->name, value)<0){
155                                                 ERR("failed to assign avp\n");
156                                                 ret=-1;
157                                                 goto error;
158                                         }
159                                         /* move the mark, so the next found AVP will come before
160                                            the one currently added so they will have the same 
161                                            order as in the source list */
162                                         if (avp_mark) avp_mark=avp_mark->next;
163                                         else
164                                                 avp_mark=search_first_avp(flags, avp->name, 0, 0);
165                                         r_avp=search_next_avp(&st, &value);
166                                 }
167                                 ret=1;
168                                 goto end;
169                         }else{
170                                 /* normal case, value is replaced */
171                                 r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
172                                                                                         &value, rv->v.avps.index);
173                                 if (likely(r_avp)){
174                                         /* take only the val type from the source avp
175                                          * and reset the class, track flags and name type  */
176                                         flags=(avp->type & ~AVP_VAL_STR) | (r_avp->flags & 
177                                                                 ~(AVP_CLASS_ALL|AVP_TRACK_ALL|AVP_NAME_STR|
178                                                                         AVP_NAME_RE));
179                                         ret=1;
180                                 }else{
181                                         /* on error, keep the type of the assigned avp, but
182                                            reset it to an empty value */
183                                         AVP_ASSIGN_NOVAL();
184                                         ret=0;
185                                         break;
186                                 }
187                         }
188                         break;
189                 case RV_PVAR:
190                         memset(&pval, 0, sizeof(pval));
191                         if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
192                                 destroy_pval=1;
193                                 if (pval.flags & PV_TYPE_INT){
194                                         value.n=pval.ri;
195                                         ret=value.n;
196                                         flags=avp->type & ~AVP_VAL_STR;
197                                 }else if (pval.flags & PV_VAL_STR){
198                                         value.s=pval.rs;
199                                         ret=(value.s.len>0);
200                                         flags=avp->type | AVP_VAL_STR;
201                                 }else if (pval.flags==PV_VAL_NONE ||
202                                                         (pval.flags & (PV_VAL_NULL|PV_VAL_EMPTY))){
203                                         AVP_ASSIGN_NOVAL();
204                                         ret=0;
205                                 }
206                         }else{
207                                 /* non existing pvar */
208                                 /* on error, keep the type of the assigned avp, but
209                                    reset it to an empty value */
210                                 AVP_ASSIGN_NOVAL();
211                                 ret=0;
212                         }
213                         break;
214         }
215         /* If the left attr was specified without indexing brackets delete
216          * existing AVPs before adding the new value */
217         delete_avp(avp->type, avp->name);
218         if (avp_add && (add_avp(flags & ~AVP_INDEX_ALL, avp->name, value) < 0)) {
219                 ERR("failed to assign value to avp\n");
220                 goto error;
221         }
222 end:
223         if (destroy_pval) pv_value_destroy(&pval);
224         return ret;
225 error:
226         if (destroy_pval) pv_value_destroy(&pval);
227         return -1;
228 drop:
229         if (destroy_pval) pv_value_destroy(&pval);
230         return EXPR_DROP;
231 }
232
233
234
235 /** eval rve and assign the result to a pvar
236  * lv->lv.pvar=eval(rve)
237  *
238  * based on do_action() ASSIGN_T
239  *
240  * @param h  - script context
241  * @param msg - sip msg
242  * @param lv - lvalue
243  * @param rve - rvalue expression
244  * @return >= 0 on success (expr. bool value), -1 on error
245  */
246 inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
247                                                                         struct lvalue* lv, struct rvalue* rv)
248 {
249         pv_spec_t* pvar;
250         pv_value_t pval;
251         avp_t* r_avp;
252         int_str avp_val;
253         int ret;
254         int v;
255         int destroy_pval;
256         
257         #define PVAR_ASSIGN_NOVAL() \
258                 /* no value found => "undefine" */ \
259                 pv_get_null(msg, 0, &pval)
260         
261         destroy_pval=0;
262         pvar=&lv->lv.pvs;
263         if (unlikely(!pv_is_w(pvar))){
264                 ERR("read only pvar\n");
265                 goto error;
266         }
267         memset(&pval, 0, sizeof(pval));
268         ret=0;
269         switch(rv->type){
270                 case RV_NONE:
271                         BUG("non-intialized rval / rval expr \n");
272                         PVAR_ASSIGN_NOVAL();
273                         ret=-1;
274                         break;
275                 case RV_INT:
276                         pval.flags=PV_TYPE_INT|PV_VAL_INT;
277                         pval.ri=rv->v.l;
278                         ret=!(!pval.ri);
279                         break;
280                 case RV_STR:
281                         pval.flags=PV_VAL_STR;
282                         pval.rs=rv->v.s;
283                         ret=(pval.rs.len>0);
284                         break;
285                 case RV_ACTION_ST:
286                         pval.flags=PV_TYPE_INT|PV_VAL_INT;
287                         if (rv->v.action) {
288                                 pval.ri=run_actions_safe(h, rv->v.action, msg);
289                                 h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
290                                                                                                                     break in expr*/
291                         } else
292                                 pval.ri=0;
293                         ret=!(!pval.ri);
294                         break;
295                 case RV_BEXPR: /* logic/boolean expr. */
296                         pval.flags=PV_TYPE_INT|PV_VAL_INT;
297                         pval.ri=eval_expr(h, rv->v.bexpr, msg);
298                         if (unlikely(pval.ri<0)){
299                                 if (pval.ri==EXPR_DROP) /* hack to quit on drop */
300                                         goto drop;
301                                 WARN("error in expression\n");
302                                 pval.ri=0; /* expr. is treated as false */
303                         }
304                         ret=!(!pval.ri);
305                         break;
306                 case RV_SEL:
307                         pval.flags=PV_VAL_STR;
308                         v=run_select(&pval.rs, &rv->v.sel, msg);
309                         if (unlikely(v!=0)){
310                                 pval.flags|=PV_VAL_EMPTY;
311                                 pval.rs.s="";
312                                 pval.rs.len=0;
313                                 if (v<0){
314                                         ret=-1;
315                                         break;
316                                 }
317                         }
318                         ret=(pval.rs.len>0);
319                         break;
320                 case RV_AVP:
321                                 r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
322                                                                                         &avp_val, rv->v.avps.index);
323                                 if (likely(r_avp)){
324                                         if (r_avp->flags & AVP_VAL_STR){
325                                                 pval.flags=PV_VAL_STR;
326                                                 pval.rs=avp_val.s;
327                                                 ret=(pval.rs.len>0);
328                                         }else{
329                                                 pval.flags=PV_TYPE_INT|PV_VAL_INT;
330                                                 pval.ri=avp_val.n;
331                                                 ret=!(!pval.ri);
332                                         }
333                                 }else{
334                                         PVAR_ASSIGN_NOVAL();
335                                         ret=0; /* avp not defined (valid case) */
336                                         break;
337                                 }
338                         break;
339                 case RV_PVAR:
340                         if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
341                                 destroy_pval=1;
342                                 if (pval.flags & PV_TYPE_INT){
343                                         ret=!(!pval.ri);
344                                 }else if (pval.flags & PV_VAL_STR){
345                                         ret=(pval.rs.len>0);
346                                 }else{
347                                         /* no value / not defined (e.g. avp) -> keep the flags */
348                                         ret=0;
349                                 }
350                         }else{
351                                 ERR("non existing right pvar\n");
352                                 PVAR_ASSIGN_NOVAL();
353                                 ret=-1;
354                         }
355                         break;
356         }
357         if (unlikely(pvar->setf(msg, &pvar->pvp, EQ_T, &pval)<0)){
358                 ERR("setting pvar failed\n");
359                 goto error;
360         }
361         if (destroy_pval) pv_value_destroy(&pval);
362         return ret;
363 error:
364         if (destroy_pval) pv_value_destroy(&pval);
365         return -1;
366 drop:
367         if (destroy_pval) pv_value_destroy(&pval);
368         return EXPR_DROP;
369 }
370
371
372
373 /** eval rve and assign the result to lv
374  * lv=eval(rve)
375  *
376  * @param h  - script context
377  * @param msg - sip msg
378  * @param lv - lvalue
379  * @param rve - rvalue expression
380  * @return >= 0 on success (expr. bool value), -1 on error
381  */
382 int lval_assign(struct run_act_ctx* h, struct sip_msg* msg, 
383                                 struct lvalue* lv, struct rval_expr* rve)
384 {
385         struct rvalue* rv;
386         int ret;
387         
388         ret=0;
389         rv=rval_expr_eval(h, msg, rve);
390         if (unlikely(rv==0)){
391                 ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
392                                 rve->fpos.s_line, rve->fpos.s_col,
393                                 rve->fpos.e_line, rve->fpos.e_col);
394                 goto error;
395         }
396         switch(lv->type){
397                 case LV_NONE:
398                         BUG("uninitialized/invalid lvalue (%d) (cfg line: %d)\n",
399                                         lv->type, rve->fpos.s_line);
400                         goto error;
401                 case LV_AVP:
402                         ret=lval_avp_assign(h, msg, lv, rv);
403                         break;
404                 case LV_PVAR:
405                         ret=lval_pvar_assign(h, msg, lv, rv);
406                         break;
407         }
408         if (unlikely(ret<0)){
409                 ERR("assignment failed at pos: (%d,%d-%d,%d)\n",
410                         rve->fpos.s_line, rve->fpos.s_col,
411                         rve->fpos.e_line, rve->fpos.e_col);
412         }
413         rval_destroy(rv);
414         return ret;
415 error:
416         if (rv) rval_destroy(rv);
417         return -1;
418 }