[SR-Dev] git:master: core: avp & pvars assignment fixes & changes

Andrei Pelinescu-Onciul andrei at iptel.org
Fri Apr 24 21:52:44 CEST 2009


Module: sip-router
Branch: master
Commit: 0789fd246548cb8287777bbe9f8322cffedc8ad4
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0789fd246548cb8287777bbe9f8322cffedc8ad4

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Fri Apr 24 21:40:26 2009 +0200

core: avp & pvars assignment fixes & changes

- fix: delete avps after finding their new value and not before
  (fixes $v=$v or $v=$avp(v) deleting $v's value)

- when assigning something undefined (like a non-existing avp),
  delete the lvalue.
  E.g.:  $v=$foo  and $ foo undefined => delete/undefine $v
  An expr is undefined only if it consists only on an undefined
  avp or pvar. If it contains more elements it's always defined
  (even if all the elements are undefined).
  E.g: $foo and $bar are undefined => defined $foo == 0, defined
  $bar == 0, but defined ($foo+$bar) == 1.
  An avp is undefined if it doesn't exist or there is some error
  accessing it.
  A pvar is undefined if it's PV_VAL_NULL or there is an error
  getting it's value.

---

 lvalue.c |   95 +++++++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 64 insertions(+), 31 deletions(-)

diff --git a/lvalue.c b/lvalue.c
index 3c409ff..56b7496 100644
--- a/lvalue.c
+++ b/lvalue.c
@@ -23,6 +23,10 @@
  * History:
  * --------
  *  2008-11-30  initial version (andrei)
+ *  2009-04-24  delete avps after finding their new value and not before
+ *               (fixed $avp=$avp)
+ *              when assigning something undefined (e.g. non-existing avp),
+ *              delete the lvalue (similar to perl)  (andrei)
  */
 
 #include "lvalue.h"
@@ -53,19 +57,37 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
 	unsigned short flags;
 	struct search_state st;
 	int ret, v, destroy_pval;
+	int avp_add;
+
+#if 0
+	#define AVP_ASSIGN_NOVAL() \
+		/* unknown value => reset the avp in function of its type */ \
+		flags=avp->type; \
+		if (flags & AVP_VAL_STR){ \
+			value.s.s=""; \
+			value.s.len=0; \
+		}else{ \
+			value.n=0; \
+		}
+#endif
+	#define AVP_ASSIGN_NOVAL() \
+		/* no value => delete avp */ \
+		avp_add=0
 	
 	destroy_pval=0;
 	flags = 0;
 	avp=&lv->lv.avps;
 	ret=0;
-	/* If the left attr was specified without indexing brackets delete
-	 * existing AVPs before adding new ones */
-	if ((avp->type & AVP_INDEX_ALL) != AVP_INDEX_ALL)
-		delete_avp(avp->type, avp->name);
+	avp_add=1;
+	
 	switch(rv->type){
 		case RV_NONE:
 			BUG("non-intialized rval / rval expr \n");
-			goto error;
+			/* unknown value => reset the avp in function of its type */
+			flags=avp->type;
+			AVP_ASSIGN_NOVAL();
+			ret=-1;
+			break;
 		case RV_INT:
 			value.n=rv->v.l;
 			flags=avp->type & ~AVP_VAL_STR;
@@ -96,22 +118,22 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
 			ret=value.n;
 			break;
 		case RV_SEL:
+			flags=avp->type|AVP_VAL_STR;
 			v=run_select(&value.s, &rv->v.sel, msg);
 			if (unlikely(v!=0)){
+				value.s.s="";
+				value.s.len=0;
 				if (v<0){
 					ret=-1;
-					goto error;
-				}else { /* v>0 */
-					value.s.s="";
-					value.s.len=0;
-				}
+					break;
+				} /* v>0 */
 			}
-			flags=avp->type|AVP_VAL_STR;
 			ret=(value.s.len>0);
 			break;
 		case RV_AVP:
 			avp_mark=0;
 			if (unlikely((rv->v.avps.type & AVP_INDEX_ALL) == AVP_INDEX_ALL)){
+				/* special case: add the value to the avp */
 				r_avp = search_first_avp(rv->v.avps.type, rv->v.avps.name,
 											&value, &st);
 				while(r_avp){
@@ -136,6 +158,7 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
 				ret=1;
 				goto end;
 			}else{
+				/* normal case, value is replaced */
 				r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
 											&value, rv->v.avps.index);
 				if (likely(r_avp)){
@@ -146,8 +169,11 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
 									AVP_NAME_RE));
 					ret=1;
 				}else{
-					ret=-1;
-					goto error;
+					/* on error, keep the type of the assigned avp, but
+					   reset it to an empty value */
+					AVP_ASSIGN_NOVAL();
+					ret=0;
+					break;
 				}
 			}
 			break;
@@ -165,21 +191,22 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
 					flags=avp->type | AVP_VAL_STR;
 				}else if (pval.flags==PV_VAL_NONE ||
 							(pval.flags & (PV_VAL_NULL|PV_VAL_EMPTY))){
-					value.s.s="";
-					value.s.len=0;
+					AVP_ASSIGN_NOVAL();
 					ret=0;
-					flags=avp->type | AVP_VAL_STR;
 				}
 			}else{
 				/* non existing pvar */
-				value.s.s="";
-				value.s.len=0;
+				/* on error, keep the type of the assigned avp, but
+				   reset it to an empty value */
+				AVP_ASSIGN_NOVAL();
 				ret=0;
-				flags=avp->type | AVP_VAL_STR;
 			}
 			break;
 	}
-	if (add_avp(flags & ~AVP_INDEX_ALL, avp->name, value) < 0) {
+	/* If the left attr was specified without indexing brackets delete
+	 * existing AVPs before adding the new value */
+	delete_avp(avp->type, avp->name);
+	if (avp_add && (add_avp(flags & ~AVP_INDEX_ALL, avp->name, value) < 0)) {
 		ERR("failed to assign value to avp\n");
 		goto error;
 	}
@@ -218,6 +245,10 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
 	int v;
 	int destroy_pval;
 	
+	#define PVAR_ASSIGN_NOVAL() \
+		/* no value found => "undefine" */ \
+		pv_get_null(msg, 0, &pval)
+	
 	destroy_pval=0;
 	pvar=&lv->lv.pvs;
 	if (unlikely(!pv_is_w(pvar))){
@@ -229,7 +260,9 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
 	switch(rv->type){
 		case RV_NONE:
 			BUG("non-intialized rval / rval expr \n");
-			goto error;
+			PVAR_ASSIGN_NOVAL();
+			ret=-1;
+			break;
 		case RV_INT:
 			pval.flags=PV_TYPE_INT|PV_VAL_INT;
 			pval.ri=rv->v.l;
@@ -263,12 +296,12 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
 			pval.flags=PV_VAL_STR;
 			v=run_select(&pval.rs, &rv->v.sel, msg);
 			if (unlikely(v!=0)){
+				pval.flags|=PV_VAL_EMPTY;
+				pval.rs.s="";
+				pval.rs.len=0;
 				if (v<0){
 					ret=-1;
-					goto error;
-				}else { /* v>0 */
-					pval.rs.s="";
-					pval.rs.len=0;
+					break;
 				}
 			}
 			ret=(pval.rs.len)>0;
@@ -287,8 +320,9 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
 						ret=!(!pval.ri);
 					}
 				}else{
-					ret=-1;
-					goto error;
+					PVAR_ASSIGN_NOVAL();
+					ret=0; /* avp not defined (valid case) */
+					break;
 				}
 			break;
 		case RV_PVAR:
@@ -299,14 +333,13 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
 				}else if (pval.flags & PV_VAL_STR){
 					ret=(pval.rs.len>0);
 				}else{
-					ERR("no value in pvar assignment rval\n");
-					ret=-1;
-					goto error;
+					/* no value / not defined (e.g. avp) -> keep the flags */
+					ret=0;
 				}
 			}else{
 				ERR("non existing right pvar\n");
+				PVAR_ASSIGN_NOVAL();
 				ret=-1;
-				goto error;
 			}
 			break;
 	}




More information about the sr-dev mailing list