From: Victor Seva <vseva@sipwise.com>
Date: Mon, 29 Aug 2022 13:59:38 +0200
Subject: pv_headers: rework pvh_remove_header_param, take two

* pvh_set_xavi changes/removes xavi, so we need the new value
* after pvh_remove_header, search for the header again
---
 src/modules/pv_headers/pv_headers.c | 18 ++++++++++++++----
 src/modules/pv_headers/pvh_func.c   | 12 ++++++++----
 src/modules/pv_headers/pvh_xavp.c   | 34 +++++++++++++++-------------------
 src/modules/pv_headers/pvh_xavp.h   |  2 +-
 4 files changed, 38 insertions(+), 28 deletions(-)

diff --git a/src/modules/pv_headers/pv_headers.c b/src/modules/pv_headers/pv_headers.c
index 246339f..5afe2dc 100644
--- a/src/modules/pv_headers/pv_headers.c
+++ b/src/modules/pv_headers/pv_headers.c
@@ -223,12 +223,15 @@ static int w_pvh_header_param_exists(
 
 static int ki_pvh_remove_header_param(struct sip_msg *msg, str *hname, str *toRemove)
 {
-	int idx;
+	int next;
+	int idx = 0;
 	int new_size;
 	str dst = STR_NULL;
 	sr_xavp_t *avi = pvh_xavi_get_child(msg, &xavi_name, hname);
 
-	for(idx=0; avi != NULL; avi = xavi_get_next(avi)) {
+	while(avi) {
+		next = 1;
+		LM_DBG("hname:%.*s[%d]\n", STR_FMT(hname), idx);
 		if (avi->val.type == SR_XTYPE_STR && avi->val.v.s.s != NULL) {
 			if(str_casesearch(&avi->val.v.s, toRemove) != NULL) {
 				new_size = pvh_remove_header_param_helper(&avi->val.v.s, toRemove, &dst);
@@ -237,13 +240,17 @@ static int ki_pvh_remove_header_param(struct sip_msg *msg, str *hname, str *toRe
 							STR_FMT(hname), idx);
 					if(pvh_remove_header(msg, hname, idx) < 0)
 						return -1;
+					avi = pvh_xavi_get_child(msg, &xavi_name, hname);
+					if(idx > 0) idx = 0;
+					next = 0;
 				} else if(dst.len < 0 || new_size == avi->val.v.s.len) {
 					LM_DBG("'%.*s' not found at '%.*s'\n", STR_FMT(toRemove),
 						STR_FMT(&avi->val.v.s));
 				} else {
 					LM_DBG("old_value:'%.*s' new_value:'%.*s'\n",
 						STR_FMT(&avi->val.v.s), STR_FMT(&dst));
-					if(pvh_set_xavi(msg, &xavi_name, hname, &dst, SR_XTYPE_STR, idx, 0) < 0) {
+					avi = pvh_set_xavi(msg, &xavi_name, hname, &dst, SR_XTYPE_STR, idx, 0);
+					if(avi == NULL) {
 						LM_ERR("can't set new value\n");
 						return -1;
 					}
@@ -253,7 +260,10 @@ static int ki_pvh_remove_header_param(struct sip_msg *msg, str *hname, str *toRe
 						STR_FMT(&avi->val.v.s));
 			}
 		}
-		idx++;
+		if(next) {
+			avi = xavi_get_next(avi);
+			idx++;
+		}
 	}
 	return 1;
 }
diff --git a/src/modules/pv_headers/pvh_func.c b/src/modules/pv_headers/pvh_func.c
index 918733c..09f70ba 100644
--- a/src/modules/pv_headers/pvh_func.c
+++ b/src/modules/pv_headers/pvh_func.c
@@ -325,12 +325,16 @@ int pvh_check_header(struct sip_msg *msg, str *hname)
 
 int pvh_append_header(struct sip_msg *msg, str *hname, str *hvalue)
 {
-	return pvh_set_xavi(msg, &xavi_name, hname, hvalue, SR_XTYPE_STR, 0, 1);
+	if(pvh_set_xavi(msg, &xavi_name, hname, hvalue, SR_XTYPE_STR, 0, 1) == NULL)
+		return -1;
+	return 1;
 }
 
 int pvh_modify_header(struct sip_msg *msg, str *hname, str *hvalue, int indx)
 {
-	return pvh_set_xavi(msg, &xavi_name, hname, hvalue, SR_XTYPE_STR, indx, 0);
+	if(pvh_set_xavi(msg, &xavi_name, hname, hvalue, SR_XTYPE_STR, indx, 0) == NULL)
+		return -1;
+	return 1;
 }
 
 int pvh_remove_header(struct sip_msg *msg, str *hname, int indx)
@@ -346,12 +350,12 @@ int pvh_remove_header(struct sip_msg *msg, str *hname, int indx)
 		do {
 			if(pvh_set_xavi(
 					   msg, &xavi_name, hname, NULL, SR_XTYPE_STR, indx++, 0)
-					< 1)
+					== NULL)
 				return -1;
 		} while(indx < count);
 	} else {
 		if(pvh_set_xavi(msg, &xavi_name, hname, NULL, SR_XTYPE_STR, indx, 0)
-				< 1)
+				== NULL)
 			return -1;
 	}
 
diff --git a/src/modules/pv_headers/pvh_xavp.c b/src/modules/pv_headers/pvh_xavp.c
index 8b2acbf..50cac4f 100644
--- a/src/modules/pv_headers/pvh_xavp.c
+++ b/src/modules/pv_headers/pvh_xavp.c
@@ -131,18 +131,18 @@ static sr_xavp_t *pvh_xavi_new_value(str *name, sr_xval_t *val)
 	return avp;
 }
 
-int pvh_xavi_append_value(str *name, sr_xval_t *val, sr_xavp_t **start)
+static sr_xavp_t * pvh_xavi_append_value(str *name, sr_xval_t *val, sr_xavp_t **start)
 {
 	sr_xavp_t *last = NULL;
 	sr_xavp_t *xavi = NULL;
 
 	if((xavi = pvh_xavi_new_value(name, val)) == NULL)
-		return -1;
+		return xavi;
 
 	if(*start == NULL) {
 		xavi->next = *start;
 		*start = xavi;
-		return 1;
+		return xavi;
 	}
 
 	last = *start;
@@ -150,13 +150,13 @@ int pvh_xavi_append_value(str *name, sr_xval_t *val, sr_xavp_t **start)
 		last = last->next;
 	last->next = xavi;
 
-	return 1;
+	return xavi;
 }
 
 /**
  *
  */
-static int pvh_xavi_set_value(
+static sr_xavp_t * pvh_xavi_set_value(
 		str *name, sr_xval_t *val, int idx, sr_xavp_t **start)
 {
 	int cnt = 0;
@@ -166,14 +166,11 @@ static int pvh_xavi_set_value(
 		idx = idx + cnt;
 		if(idx < 0) {
 			LM_ERR("wrong calculated idx:%d\n", idx);
-			return -1;
+			return NULL;
 		}
 	}
 	LM_DBG("xavi name: %.*s\n", name->len, name->s);
-	if(xavi_set_value(name, idx, val, start) == NULL)
-		return -1;
-
-	return 1;
+	return xavi_set_value(name, idx, val, start);
 }
 
 /**
@@ -356,11 +353,12 @@ int pvh_xavi_keys_count(sr_xavp_t **start)
 /**
  *
  */
-int pvh_set_xavi(struct sip_msg *msg, str *xname, str *name, void *data,
+sr_xavp_t * pvh_set_xavi(struct sip_msg *msg, str *xname, str *name, void *data,
 		sr_xtype_t type, int idx, int append)
 {
 	sr_xavp_t **xavi = NULL;
 	sr_xavp_t *root = NULL;
+	sr_xavp_t *result = NULL;
 	sr_xval_t root_xval;
 	sr_xval_t xval;
 	char t[header_name_size];
@@ -368,7 +366,7 @@ int pvh_set_xavi(struct sip_msg *msg, str *xname, str *name, void *data,
 
 	if(xname == NULL || name == NULL) {
 		LM_ERR("missing xavi/pv name\n");
-		return -1;
+		return result;
 	}
 
 	pvh_get_branch_xname(msg, xname, &br_xname);
@@ -385,7 +383,7 @@ int pvh_set_xavi(struct sip_msg *msg, str *xname, str *name, void *data,
 		xval.v.data = (sr_data_t *)shm_malloc(sizeof(sr_data_t));
 		if(xval.v.data == NULL) {
 			SHM_MEM_ERROR;
-			return -1;
+			return result;
 		}
 		memset(xval.v.data, 0, sizeof(sr_data_t));
 		xval.v.data->p = data;
@@ -409,7 +407,7 @@ int pvh_set_xavi(struct sip_msg *msg, str *xname, str *name, void *data,
 
 		if((root = xavi_add_value(&br_xname, &root_xval, NULL)) == NULL) {
 			LM_ERR("error create xavi %.*s\n", br_xname.len, br_xname.s);
-			return -1;
+			return NULL;
 		}
 		xavi = &root->val.v.xavp;
 	} else if(xavi_get_child(&br_xname, name) == NULL) {
@@ -417,20 +415,18 @@ int pvh_set_xavi(struct sip_msg *msg, str *xname, str *name, void *data,
 	}
 
 	if(append) {
-		if(pvh_xavi_append_value(name, &xval, xavi) < 0) {
+		if((result = pvh_xavi_append_value(name, &xval, xavi)) == NULL) {
 			LM_ERR("error append xavi=>name %.*s=>%.*s\n", br_xname.len,
 					br_xname.s, name->len, name->s);
-			return -1;
 		}
 	} else {
-		if(pvh_xavi_set_value(name, &xval, idx, xavi) < 0) {
+		if((result = pvh_xavi_set_value(name, &xval, idx, xavi)) == NULL) {
 			LM_ERR("error modify xavi=>name %.*s=>%.*s idx=%d\n", br_xname.len,
 					br_xname.s, name->len, name->s, idx);
-			return -1;
 		}
 	}
 
-	return 1;
+	return result;
 }
 
 
diff --git a/src/modules/pv_headers/pvh_xavp.h b/src/modules/pv_headers/pvh_xavp.h
index 646ebd7..2ced2eb 100644
--- a/src/modules/pv_headers/pvh_xavp.h
+++ b/src/modules/pv_headers/pvh_xavp.h
@@ -33,7 +33,7 @@
 
 int pvh_reply_append(sr_xavp_t **start);
 
-int pvh_set_xavi(struct sip_msg *msg, str *xname, str *name, void *data,
+sr_xavp_t * pvh_set_xavi(struct sip_msg *msg, str *xname, str *name, void *data,
 		sr_xtype_t type, int idx, int append);
 int pvh_xavi_keys_count(sr_xavp_t **start);
 sr_xavp_t *pvh_xavi_get_child(struct sip_msg *msg, str *xname, str *name);
