• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

lvalue.c

Go to the documentation of this file.
00001 /* 
00002  * Copyright (C) 2008 iptelorg GmbH
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00024 /* 
00025  * History:
00026  * --------
00027  *  2008-11-30  initial version (andrei)
00028  *  2009-04-24  delete avps after finding their new value and not before
00029  *               (fixed $avp=$avp)
00030  *              when assigning something undefined (e.g. non-existing avp),
00031  *              delete the lvalue (similar to perl)  (andrei)
00032  */
00033 
00034 
00035 #include "lvalue.h"
00036 #include "dprint.h"
00037 #include "route.h"
00038 
00039 
00040 
00052 inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
00053                                                                         struct lvalue* lv, struct rvalue* rv)
00054 {
00055         avp_spec_t* avp;
00056         avp_t* r_avp;
00057         avp_t* avp_mark;
00058         pv_value_t pval;
00059         int_str value;
00060         unsigned short flags;
00061         struct search_state st;
00062         int ret, v, destroy_pval;
00063         int avp_add;
00064 
00065 #if 0
00066         #define AVP_ASSIGN_NOVAL() \
00067                 /* unknown value => reset the avp in function of its type */ \
00068                 flags=avp->type; \
00069                 if (flags & AVP_VAL_STR){ \
00070                         value.s.s=""; \
00071                         value.s.len=0; \
00072                 }else{ \
00073                         value.n=0; \
00074                 }
00075 #endif
00076         #define AVP_ASSIGN_NOVAL() \
00077                 /* no value => delete avp */ \
00078                 avp_add=0
00079         
00080         destroy_pval=0;
00081         flags = 0;
00082         avp=&lv->lv.avps;
00083         ret=0;
00084         avp_add=1;
00085         
00086         switch(rv->type){
00087                 case RV_NONE:
00088                         BUG("non-intialized rval / rval expr \n");
00089                         /* unknown value => reset the avp in function of its type */
00090                         flags=avp->type;
00091                         AVP_ASSIGN_NOVAL();
00092                         ret=-1;
00093                         break;
00094                 case RV_INT:
00095                         value.n=rv->v.l;
00096                         flags=avp->type & ~AVP_VAL_STR;
00097                         ret=!(!value.n);
00098                         break;
00099                 case RV_STR:
00100                         value.s=rv->v.s;
00101                         flags=avp->type | AVP_VAL_STR;
00102                         ret=(value.s.len>0);
00103                         break;
00104                 case RV_ACTION_ST:
00105                         flags=avp->type & ~AVP_VAL_STR;
00106                         if (rv->v.action) {
00107                                 value.n=run_actions_safe(h, rv->v.action, msg);
00108                                 h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
00109                                                                                                                     break in expr*/
00110                         } else
00111                                 value.n=-1;
00112                         ret=value.n;
00113                         break;
00114                 case RV_BEXPR: /* logic/boolean expr. */
00115                         value.n=eval_expr(h, rv->v.bexpr, msg);
00116                         if (unlikely(value.n<0)){
00117                                 if (value.n==EXPR_DROP) /* hack to quit on drop */
00118                                         goto drop;
00119                                 WARN("error in expression\n");
00120                                 value.n=0; /* expr. is treated as false */
00121                         }
00122                         flags=avp->type & ~AVP_VAL_STR;
00123                         ret=value.n;
00124                         break;
00125                 case RV_SEL:
00126                         flags=avp->type|AVP_VAL_STR;
00127                         v=run_select(&value.s, &rv->v.sel, msg);
00128                         if (unlikely(v!=0)){
00129                                 value.s.s="";
00130                                 value.s.len=0;
00131                                 if (v<0){
00132                                         ret=-1;
00133                                         break;
00134                                 } /* v>0 */
00135                         }
00136                         ret=(value.s.len>0);
00137                         break;
00138                 case RV_AVP:
00139                         avp_mark=0;
00140                         if (unlikely((rv->v.avps.type & AVP_INDEX_ALL) == AVP_INDEX_ALL)){
00141                                 /* special case: add the value to the avp */
00142                                 r_avp = search_first_avp(rv->v.avps.type, rv->v.avps.name,
00143                                                                                         &value, &st);
00144                                 while(r_avp){
00145                                         /* We take only the val type  from the source avp
00146                                          * and reset the class, track flags and name type  */
00147                                         flags=(avp->type & ~(AVP_INDEX_ALL|AVP_VAL_STR)) | 
00148                                                         (r_avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL|
00149                                                                                                 AVP_NAME_STR|AVP_NAME_RE));
00150                                         if (add_avp_before(avp_mark, flags, avp->name, value)<0){
00151                                                 ERR("failed to assign avp\n");
00152                                                 ret=-1;
00153                                                 goto error;
00154                                         }
00155                                         /* move the mark, so the next found AVP will come before
00156                                            the one currently added so they will have the same 
00157                                            order as in the source list */
00158                                         if (avp_mark) avp_mark=avp_mark->next;
00159                                         else
00160                                                 avp_mark=search_first_avp(flags, avp->name, 0, 0);
00161                                         r_avp=search_next_avp(&st, &value);
00162                                 }
00163                                 ret=1;
00164                                 goto end;
00165                         }else{
00166                                 /* normal case, value is replaced */
00167                                 r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
00168                                                                                         &value, rv->v.avps.index);
00169                                 if (likely(r_avp)){
00170                                         /* take only the val type from the source avp
00171                                          * and reset the class, track flags and name type  */
00172                                         flags=(avp->type & ~AVP_VAL_STR) | (r_avp->flags & 
00173                                                                 ~(AVP_CLASS_ALL|AVP_TRACK_ALL|AVP_NAME_STR|
00174                                                                         AVP_NAME_RE));
00175                                         ret=1;
00176                                 }else{
00177                                         /* on error, keep the type of the assigned avp, but
00178                                            reset it to an empty value */
00179                                         AVP_ASSIGN_NOVAL();
00180                                         ret=0;
00181                                         break;
00182                                 }
00183                         }
00184                         break;
00185                 case RV_PVAR:
00186                         memset(&pval, 0, sizeof(pval));
00187                         if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
00188                                 destroy_pval=1;
00189                                 if (pval.flags & PV_TYPE_INT){
00190                                         value.n=pval.ri;
00191                                         ret=value.n;
00192                                         flags=avp->type & ~AVP_VAL_STR;
00193                                 }else if (pval.flags & PV_VAL_STR){
00194                                         value.s=pval.rs;
00195                                         ret=(value.s.len>0);
00196                                         flags=avp->type | AVP_VAL_STR;
00197                                 }else if (pval.flags==PV_VAL_NONE ||
00198                                                         (pval.flags & (PV_VAL_NULL|PV_VAL_EMPTY))){
00199                                         AVP_ASSIGN_NOVAL();
00200                                         ret=0;
00201                                 }
00202                         }else{
00203                                 /* non existing pvar */
00204                                 /* on error, keep the type of the assigned avp, but
00205                                    reset it to an empty value */
00206                                 AVP_ASSIGN_NOVAL();
00207                                 ret=0;
00208                         }
00209                         break;
00210         }
00211         /* If the left attr was specified without indexing brackets delete
00212          * existing AVPs before adding the new value */
00213         delete_avp(avp->type, avp->name);
00214         if (avp_add && (add_avp(flags & ~AVP_INDEX_ALL, avp->name, value) < 0)) {
00215                 ERR("failed to assign value to avp\n");
00216                 goto error;
00217         }
00218 end:
00219         if (destroy_pval) pv_value_destroy(&pval);
00220         return ret;
00221 error:
00222         if (destroy_pval) pv_value_destroy(&pval);
00223         return -1;
00224 drop:
00225         if (destroy_pval) pv_value_destroy(&pval);
00226         return EXPR_DROP;
00227 }
00228 
00229 
00230 
00242 inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
00243                                                                         struct lvalue* lv, struct rvalue* rv)
00244 {
00245         pv_spec_t* pvar;
00246         pv_value_t pval;
00247         avp_t* r_avp;
00248         int_str avp_val;
00249         int ret;
00250         int v;
00251         int destroy_pval;
00252         
00253         #define PVAR_ASSIGN_NOVAL() \
00254                 /* no value found => "undefine" */ \
00255                 pv_get_null(msg, 0, &pval)
00256         
00257         destroy_pval=0;
00258         pvar=&lv->lv.pvs;
00259         if (unlikely(!pv_is_w(pvar))){
00260                 ERR("read only pvar\n");
00261                 goto error;
00262         }
00263         memset(&pval, 0, sizeof(pval));
00264         ret=0;
00265         switch(rv->type){
00266                 case RV_NONE:
00267                         BUG("non-intialized rval / rval expr \n");
00268                         PVAR_ASSIGN_NOVAL();
00269                         ret=-1;
00270                         break;
00271                 case RV_INT:
00272                         pval.flags=PV_TYPE_INT|PV_VAL_INT;
00273                         pval.ri=rv->v.l;
00274                         ret=!(!pval.ri);
00275                         break;
00276                 case RV_STR:
00277                         pval.flags=PV_VAL_STR;
00278                         pval.rs=rv->v.s;
00279                         ret=(pval.rs.len>0);
00280                         break;
00281                 case RV_ACTION_ST:
00282                         pval.flags=PV_TYPE_INT|PV_VAL_INT;
00283                         if (rv->v.action) {
00284                                 pval.ri=run_actions_safe(h, rv->v.action, msg);
00285                                 h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
00286                                                                                                                     break in expr*/
00287                         } else
00288                                 pval.ri=0;
00289                         ret=!(!pval.ri);
00290                         break;
00291                 case RV_BEXPR: /* logic/boolean expr. */
00292                         pval.flags=PV_TYPE_INT|PV_VAL_INT;
00293                         pval.ri=eval_expr(h, rv->v.bexpr, msg);
00294                         if (unlikely(pval.ri<0)){
00295                                 if (pval.ri==EXPR_DROP) /* hack to quit on drop */
00296                                         goto drop;
00297                                 WARN("error in expression\n");
00298                                 pval.ri=0; /* expr. is treated as false */
00299                         }
00300                         ret=!(!pval.ri);
00301                         break;
00302                 case RV_SEL:
00303                         pval.flags=PV_VAL_STR;
00304                         v=run_select(&pval.rs, &rv->v.sel, msg);
00305                         if (unlikely(v!=0)){
00306                                 pval.flags|=PV_VAL_EMPTY;
00307                                 pval.rs.s="";
00308                                 pval.rs.len=0;
00309                                 if (v<0){
00310                                         ret=-1;
00311                                         break;
00312                                 }
00313                         }
00314                         ret=(pval.rs.len>0);
00315                         break;
00316                 case RV_AVP:
00317                                 r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
00318                                                                                         &avp_val, rv->v.avps.index);
00319                                 if (likely(r_avp)){
00320                                         if (r_avp->flags & AVP_VAL_STR){
00321                                                 pval.flags=PV_VAL_STR;
00322                                                 pval.rs=avp_val.s;
00323                                                 ret=(pval.rs.len>0);
00324                                         }else{
00325                                                 pval.flags=PV_TYPE_INT|PV_VAL_INT;
00326                                                 pval.ri=avp_val.n;
00327                                                 ret=!(!pval.ri);
00328                                         }
00329                                 }else{
00330                                         PVAR_ASSIGN_NOVAL();
00331                                         ret=0; /* avp not defined (valid case) */
00332                                         break;
00333                                 }
00334                         break;
00335                 case RV_PVAR:
00336                         if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
00337                                 destroy_pval=1;
00338                                 if (pval.flags & PV_TYPE_INT){
00339                                         ret=!(!pval.ri);
00340                                 }else if (pval.flags & PV_VAL_STR){
00341                                         ret=(pval.rs.len>0);
00342                                 }else{
00343                                         /* no value / not defined (e.g. avp) -> keep the flags */
00344                                         ret=0;
00345                                 }
00346                         }else{
00347                                 ERR("non existing right pvar\n");
00348                                 PVAR_ASSIGN_NOVAL();
00349                                 ret=-1;
00350                         }
00351                         break;
00352         }
00353         if (unlikely(pvar->setf(msg, &pvar->pvp, EQ_T, &pval)<0)){
00354                 ERR("setting pvar failed\n");
00355                 goto error;
00356         }
00357         if (destroy_pval) pv_value_destroy(&pval);
00358         return ret;
00359 error:
00360         if (destroy_pval) pv_value_destroy(&pval);
00361         return -1;
00362 drop:
00363         if (destroy_pval) pv_value_destroy(&pval);
00364         return EXPR_DROP;
00365 }
00366 
00367 
00368 
00378 int lval_assign(struct run_act_ctx* h, struct sip_msg* msg, 
00379                                 struct lvalue* lv, struct rval_expr* rve)
00380 {
00381         struct rvalue* rv;
00382         int ret;
00383         
00384         ret=0;
00385         rv=rval_expr_eval(h, msg, rve);
00386         if (unlikely(rv==0)){
00387                 ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
00388                                 rve->fpos.s_line, rve->fpos.s_col,
00389                                 rve->fpos.e_line, rve->fpos.e_col);
00390                 goto error;
00391         }
00392         switch(lv->type){
00393                 case LV_NONE:
00394                         BUG("uninitialized/invalid lvalue (%d) (cfg line: %d)\n",
00395                                         lv->type, rve->fpos.s_line);
00396                         goto error;
00397                 case LV_AVP:
00398                         ret=lval_avp_assign(h, msg, lv, rv);
00399                         break;
00400                 case LV_PVAR:
00401                         ret=lval_pvar_assign(h, msg, lv, rv);
00402                         break;
00403         }
00404         if (unlikely(ret<0)){
00405                 ERR("assignment failed at pos: (%d,%d-%d,%d)\n",
00406                         rve->fpos.s_line, rve->fpos.s_col,
00407                         rve->fpos.e_line, rve->fpos.e_col);
00408         }
00409         rval_destroy(rv);
00410         return ret;
00411 error:
00412         if (rv) rval_destroy(rv);
00413         return -1;
00414 }

Generated on Tue May 22 2012 13:10:10 for SIP Router by  doxygen 1.7.1