TT#47971 pv_headers: add isolation for branches

* branches now have isolated modified headers
    * headers stored in branches use headers#uid=>.. as
      as the xavp name left part where the transaction
      as headers=>...

Change-Id: I12e35b1be349281c3ff14548755a91e26ad5c740
changes/96/28596/8
Kirill Solomko 7 years ago
parent 152f660f9b
commit c105266be2

@ -28,7 +28,7 @@
+include ../../Makefile.modules
--- /dev/null
+++ b/src/modules/pv_headers/README
@@ -0,0 +1,454 @@
@@ -0,0 +1,450 @@
+The pv_headers Module
+
+Kirill Solomko
@ -398,11 +398,7 @@
+
+ $var(test) = $x_hdr(X-Header);
+
+ * retrieve a value of header "X-Header" with index 0 otherwise $null
+
+ $var(test) = $x_hdr(X-Header)[*]);
+
+ * retrieve a value of header "X-Header" with index 2 otherwise $null
+ * retrieve a value of header "X-Header" with index 2, otherwise $null
+
+ $var(test) = $(x_hdr(X-Header)[2]);
+
@ -485,7 +481,7 @@
+
--- /dev/null
+++ b/src/modules/pv_headers/pv_headers.c
@@ -0,0 +1,1646 @@
@@ -0,0 +1,1806 @@
+/*
+ * pv_headers
+ *
@ -579,7 +575,7 @@
+static int pv_remove_header(struct sip_msg *_m, char *hname, char *_s2);
+static int pv_remove_header_idx(struct sip_msg *_m, char *hname, char *hidx);
+
+static int pv_set_xavp(str *xname, str *name, void *data, sr_xtype_t type, int idx, int append);
+static int pv_set_xavp(struct sip_msg *msg, str *xname, str *name, void *data, sr_xtype_t type, int idx, int append);
+static int pv_free_xavp(str *xname);
+
+static int pv_fixup_svalue(struct sip_msg *msg, char *src, str *dst);
@ -597,7 +593,8 @@
+static sr_xavp_t * pv_xavp_new_value(str *name, sr_xval_t *val);
+static int pv_xavp_append_value(str *name, sr_xval_t *val, sr_xavp_t **start);
+static int pv_xavp_set_value(str *name, sr_xval_t *val, int idx, sr_xavp_t **start);
+static sr_xval_t * pv_xavp_get_value(str *xname, str *name, int idx);
+static sr_xval_t * pv_xavp_get_value(struct sip_msg *msg, str *xname, str *name, int idx);
+static sr_xavp_t * pv_xavp_get_child(struct sip_msg *msg, str *xname, str *name);
+static int pv_xavp_is_null(sr_xavp_t * xavp);
+static void pv_xavp_free_data(void *p, sr_xavp_sfree_f sfree);
+static void pv_free_to_params(struct to_param *param, sr_xavp_sfree_f sfree);
@ -618,6 +615,9 @@
+static int pv_set_uri(struct sip_msg *msg, pv_param_t *param, int op, pv_value_t *val);
+static int pv_merge_uri(struct sip_msg *msg, enum action_type type, str *cur, str *new, xavp_c_data_t *c_data);
+
+static int pv_get_branch_index(struct sip_msg *msg, int *br_idx);
+static int pv_get_branch_xname(struct sip_msg *msg, str *xname, str *dst);
+static int pv_clone_branch_xavp(struct sip_msg *msg, str *br_xname);
+
+/*
+ * Exported functions
@ -710,15 +710,14 @@
+ struct hdr_field *hf = NULL;
+ str name = STR_NULL;
+ str val = STR_NULL;
+
+ char hvals[header_name_size][header_value_size];
+ int idx = 0, d_size = 0;
+ str val_part = STR_NULL;
+
+ if ((isbflagset(0, FL_PV_HDRS_COLLECTED) == 1) &&
+ (isflagset(msg, FL_PV_HDRS_COLLECTED) == 1)) {
+ LM_ERR("headers are already collected\n");
+ return -1;
+ if (isbflagset(0, FL_PV_HDRS_COLLECTED) == 1 &&
+ isflagset(msg, FL_PV_HDRS_COLLECTED) == 1) {
+ LM_ERR("headers are already collected\n");
+ return -1;
+ }
+
+ if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
@ -749,17 +748,17 @@
+ for (idx=0;idx<d_size;idx++) {
+ val_part.s = hvals[idx];
+ val_part.len = strlen(hvals[idx]);
+ if (pv_set_xavp(&xavp_name, &name, &val_part, SR_XTYPE_STR, 0, 1) < 0)
+ if (pv_set_xavp(msg, &xavp_name, &name, &val_part, SR_XTYPE_STR, 0, 1) < 0)
+ goto err;
+ }
+ continue;
+ }
+
+ if (pv_set_xavp(&xavp_name, &name, &val, SR_XTYPE_STR, 0, 1) < 0)
+ if (pv_set_xavp(msg, &xavp_name, &name, &val, SR_XTYPE_STR, 0, 1) < 0)
+ goto err;
+ }
+
+ if (pv_set_xavp(&xavp_helper_xname, &xavp_helper_name, &xavp_name, SR_XTYPE_STR, 0, 0) < 0)
+ if (pv_set_xavp(msg, &xavp_helper_xname, &xavp_helper_name, &xavp_name, SR_XTYPE_STR, 0, 0) < 0)
+ goto err;
+
+ pv_str_free(&name);
@ -784,11 +783,13 @@
+ str uri = STR_NULL;
+ struct str_hash_table rm_hdrs;
+ int from_cnt = 0, to_cnt = 0;
+ str br_xname = STR_NULL;
+ int br_idx;
+
+ if ((isbflagset(0, FL_PV_HDRS_APPLIED) == 1) &&
+ (isflagset(msg, FL_PV_HDRS_APPLIED) == 1)) {
+ LM_ERR("headers are already applied\n");
+ return -1;
+ if (isbflagset(0, FL_PV_HDRS_APPLIED) == 1 &&
+ isflagset(msg, FL_PV_HDRS_APPLIED) == 1) {
+ LM_ERR("headers are already applied\n");
+ return -1;
+ }
+
+ if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
@ -796,23 +797,27 @@
+ return -1;
+ }
+
+ xavp = xavp_get(&xavp_name, NULL);
+ if (xavp == NULL) {
+ if (pv_str_new(&display, header_value_size) < 0) goto err;
+ if (pv_str_new(&uri, header_value_size) < 0) goto err;
+ if (pv_str_new(&br_xname, header_value_size) < 0) goto err;
+
+ pv_get_branch_index(msg, &br_idx);
+ pv_get_branch_xname(msg, &xavp_name, &br_xname);
+
+ if ((xavp = xavp_get(&br_xname, NULL)) == NULL &&
+ (xavp = xavp_get(&xavp_name, NULL)) == NULL) {
+ LM_ERR("missing xavp %s, run pv_collect_headers() first\n", xavp_name.s);
+ return -1;
+ goto err;
+ }
+
+ if (xavp->val.type != SR_XTYPE_XAVP) {
+ LM_ERR("not xavp child type %s\n" , xavp_name.s);
+ return -1;
+ goto err;
+ }
+
+ if (xavp && xavp->val.type == SR_XTYPE_XAVP)
+ sub = xavp->val.v.xavp;
+
+ if (sub == NULL) {
+ if ((sub = xavp->val.v.xavp) == NULL) {
+ LM_ERR("invalid xavp structure: %s\n", xavp_name.s);
+ return -1;
+ goto err;
+ }
+
+ if (str_hash_alloc(&rm_hdrs, pv_xavp_keys_count(&sub)) < 0) {
@ -821,9 +826,6 @@
+ }
+ str_hash_init(&rm_hdrs);
+
+ if (pv_str_new(&display, header_value_size) < 0) goto err;
+ if (pv_str_new(&uri, header_value_size) < 0) goto err;
+
+ do {
+ if (pv_skip_header(&sub->name) == 1)
+ continue;
@ -893,22 +895,25 @@
+ if (!str_hash_get(&rm_hdrs, sub->name.s, sub->name.len)) {
+ if (!pv_xavp_is_null(sub) &&
+ (pv_single_header(&sub->name) || xavp_count(&sub->name, &sub) == 1)) {
+ LM_DBG("replace header[%s]: %s\n", sub->name.s, sub->val.v.s.s);
+ pv_real_hdr_replace(msg, &sub->name, &sub->val.v.s);
+ pv_str_hash_add_key(&rm_hdrs, &sub->name);
+ continue;
+ }
+ LM_DBG("remove header[%s]: %s\n", sub->name.s, sub->val.v.s.s);
+ pv_real_hdr_del_by_name(msg, &sub->name);
+ pv_str_hash_add_key(&rm_hdrs, &sub->name);
+ }
+
+ if (!pv_xavp_is_null(sub)) {
+ pv_real_hdr_append(msg, &sub->name, &sub->val.v.s);
+ LM_DBG("apply header[%s]: %s\n", sub->name.s, sub->val.v.s.s);
+ LM_DBG("append header[%s]: %s\n", sub->name.s, sub->val.v.s.s);
+ }
+ } while ((sub = sub->next) != NULL);
+
+ pv_str_free(&display);
+ pv_str_free(&uri);
+ pv_str_free(&br_xname);
+ pv_str_hash_free(&rm_hdrs);
+
+ setbflag(0, FL_PV_HDRS_APPLIED);
@ -919,17 +924,31 @@
+err:
+ pv_str_free(&display);
+ pv_str_free(&uri);
+ pv_str_free(&br_xname);
+ pv_str_hash_free(&rm_hdrs);
+ return -1;
+}
+
+int pv_reset_headers(struct sip_msg *msg, char *_s1, char *_s2)
+{
+ pv_free_xavp(&xavp_name);
+ pv_free_xavp(&xavp_parsed_xname);
+ str br_xname = STR_NULL;
+
+ if (pv_str_new(&br_xname, header_name_size) < 0)
+ return -1;
+
+ pv_get_branch_xname(msg, &xavp_name, &br_xname);
+
+ pv_free_xavp(&br_xname);
+ pv_get_branch_xname(msg, &xavp_parsed_xname, &br_xname);
+ pv_free_xavp(&br_xname);
+
+ resetbflag(0, FL_PV_HDRS_COLLECTED);
+ resetflag(msg, FL_PV_HDRS_COLLECTED);
+ resetbflag(0, FL_PV_HDRS_APPLIED);
+ resetflag(msg, FL_PV_HDRS_APPLIED);
+
+ pv_str_free(&br_xname);
+
+ return 1;
+}
+
@ -940,7 +959,7 @@
+ if (hname == NULL || pv_fixup_svalue(msg, hname, &hname_s) < 0)
+ return -1;
+
+ if (xavp_get_child(&xavp_name, &hname_s) == NULL)
+ if (pv_xavp_get_child(msg, &xavp_name, &hname_s) == NULL)
+ return -1;
+
+ return 1;
@ -957,7 +976,7 @@
+ if (pv_fixup_svalue(msg, hvalue, &hvalue_s) < 0)
+ return -1;
+
+ return pv_set_xavp(&xavp_name, &hname_s, &hvalue_s, SR_XTYPE_STR, 0, 1);
+ return pv_set_xavp(msg, &xavp_name, &hname_s, &hvalue_s, SR_XTYPE_STR, 0, 1);
+}
+
+int pv_modify_header(struct sip_msg *msg, char *hname, char *hvalue)
@ -971,7 +990,7 @@
+ if (pv_fixup_svalue(msg, hvalue, &hvalue_s) < 0)
+ return -1;
+
+ return pv_set_xavp(&xavp_name, &hname_s, &hvalue_s, SR_XTYPE_STR, 0, 0);
+ return pv_set_xavp(msg, &xavp_name, &hname_s, &hvalue_s, SR_XTYPE_STR, 0, 0);
+}
+
+int pv_modify_header_idx(struct sip_msg *msg, char *hname, char *hidx, char *hvalue)
@ -990,7 +1009,7 @@
+ if (pv_fixup_svalue(msg, hvalue, &hvalue_s) < 0)
+ return -1;
+
+ return pv_set_xavp(&xavp_name, &hname_s, &hvalue_s, SR_XTYPE_STR, idx, 0);
+ return pv_set_xavp(msg, &xavp_name, &hname_s, &hvalue_s, SR_XTYPE_STR, idx, 0);
+}
+
+int pv_remove_header(struct sip_msg *msg, char *hname, char *_s2)
@ -1003,13 +1022,13 @@
+ if (hname == NULL || pv_fixup_svalue(msg, hname, &hname_s) < 0)
+ return -1;
+
+ if ((avp = xavp_get_child(&xavp_name, &hname_s)) == NULL)
+ if ((avp = pv_xavp_get_child(msg, &xavp_name, &hname_s)) == NULL)
+ return 1;
+
+ count = xavp_count(&hname_s, &avp);
+
+ while (idx < count) {
+ if (pv_set_xavp(&xavp_name, &hname_s, NULL, SR_XTYPE_STR, idx++, 0) < 1)
+ if (pv_set_xavp(msg, &xavp_name, &hname_s, NULL, SR_XTYPE_STR, idx++, 0) < 1)
+ return -1;
+ }
+
@ -1029,21 +1048,28 @@
+ return -1;
+ idx = atoi(hidx_s.s);
+
+ return pv_set_xavp(&xavp_name, &hname_s, NULL, SR_XTYPE_STR, idx, 0);
+ return pv_set_xavp(msg, &xavp_name, &hname_s, NULL, SR_XTYPE_STR, idx, 0);
+}
+
+int pv_set_xavp(str *xname, str *name, void *data, sr_xtype_t type, int idx, int append)
+int pv_set_xavp(struct sip_msg *msg, str *xname, str *name, void *data, sr_xtype_t type, int idx, int append)
+{
+ sr_xavp_t **xavp = NULL;
+ sr_xavp_t *root = NULL;
+ sr_xval_t root_xval;
+ sr_xval_t xval;
+ str br_xname = STR_NULL;
+ int br_idx;
+
+ if (xname == NULL || name == NULL) {
+ LM_ERR("missing xavp/pv name\n");
+ return -1;
+ }
+
+ pv_get_branch_index(msg, &br_idx);
+ if (pv_str_new(&br_xname, header_name_size) < 0)
+ return -1;
+ pv_get_branch_xname(msg, xname, &br_xname);
+
+ memset(&xval, 0, sizeof(sr_xval_t));
+ if (data == NULL || SR_XTYPE_NULL) {
+ xval.type = SR_XTYPE_NULL;
@ -1055,14 +1081,20 @@
+ xval.v.data = (sr_data_t*)shm_malloc(sizeof(sr_data_t));
+ if (xval.v.data == NULL) {
+ LM_ERR("out of shared memory\n");
+ return -1;
+ goto err;
+ }
+ memset(xval.v.data, 0, sizeof(sr_data_t));
+ xval.v.data->p = data;
+ xval.v.data->pfree = pv_xavp_free_data;
+ }
+
+ root = xavp_get(xname, NULL);
+ root = xavp_get(&br_xname, NULL);
+
+ if (root == NULL && br_idx > 0) {
+ pv_clone_branch_xavp(msg, &br_xname);
+ root = xavp_get(&br_xname, NULL);
+ }
+
+ xavp = root ? &root->val.v.xavp : &root;
+
+ if (root == NULL) {
@ -1071,36 +1103,41 @@
+ root_xval.type = SR_XTYPE_XAVP;
+ root_xval.v.xavp = NULL;
+
+ if ((*xavp = xavp_add_value(xname, &root_xval, NULL)) == NULL) {
+ LM_ERR("error create xavp %s\n", xname->s);
+ if ((*xavp = xavp_add_value(&br_xname, &root_xval, NULL)) == NULL) {
+ LM_ERR("error create xavp %s\n", br_xname.s);
+ goto err;
+ }
+ xavp = &(*xavp)->val.v.xavp;
+ } else if (xavp_get_child(xname, name) == NULL) {
+ } else if (xavp_get_child(&br_xname, name) == NULL) {
+ append = 1;
+ }
+
+ if (append) {
+ if (pv_xavp_append_value(name, &xval, xavp) < 0) {
+ LM_ERR("error append xavp=>name %s=>%.*s\n", xname->s, name->len, name->s);
+ return -1;
+ LM_ERR("error append xavp=>name %s=>%.*s\n", br_xname.s, name->len, name->s);
+ goto err;
+ }
+ } else {
+ if (pv_xavp_set_value(name, &xval, idx, xavp) < 0) {
+ LM_ERR("error modify xavp=>name %s=>%.*s idx=%d\n", xname->s, name->len, name->s, idx);
+ return -1;
+ LM_ERR("error modify xavp=>name %s=>%.*s idx=%d\n", br_xname.s, name->len, name->s, idx);
+ goto err;
+ }
+ }
+
+ pv_str_free(&br_xname);
+ return 1;
+
+err:
+ pv_str_free(&br_xname);
+ return -1;
+}
+
+int pv_free_xavp(str *xname)
+{
+ sr_xavp_t *xavp = NULL;
+ xavp_rm_by_name(xname, 1, NULL);
+ if ((xavp = xavp_get(xname, NULL)) != NULL)
+ xavp_rm(xavp, NULL);
+ return 1;
+}
+
@ -1480,23 +1517,61 @@
+ return 1;
+}
+
+sr_xval_t * pv_xavp_get_value(str *xname, str *name, int idx)
+sr_xval_t * pv_xavp_get_value(struct sip_msg *msg, str *xname, str *name, int idx)
+{
+ sr_xavp_t *xavp = NULL;
+ sr_xavp_t *sub = NULL;
+ str br_xname = STR_NULL;
+
+ if ((xavp = xavp_get(xname, NULL)) == NULL)
+ if (pv_str_new(&br_xname, header_name_size) < 0)
+ return NULL;
+
+ pv_get_branch_xname(msg, xname, &br_xname);
+ if ((xavp = xavp_get(&br_xname, NULL)) == NULL &&
+ (xavp = xavp_get(xname, NULL)) == NULL) {
+ goto err;
+ }
+
+ if (xavp->val.type != SR_XTYPE_XAVP) {
+ LM_ERR("not xavp child type %s\n" , xname->s);
+ return NULL;
+ LM_ERR("not xavp child type %s\n" , br_xname.s);
+ goto err;
+ }
+
+ if ((sub = xavp_get_by_index(name, idx, &xavp->val.v.xavp)) == NULL)
+ sub = xavp_get_by_index(name, idx, &xavp->val.v.xavp);
+
+ pv_str_free(&br_xname);
+ return sub ? &sub->val : NULL;
+
+err:
+ pv_str_free(&br_xname);
+ return NULL;
+}
+
+sr_xavp_t * pv_xavp_get_child(struct sip_msg *msg, str *xname, str *name)
+{
+ sr_xavp_t *xavp = NULL;
+ str br_xname = STR_NULL;
+ int is_branch = 0;
+
+ if (pv_str_new(&br_xname, header_name_size) < 0)
+ return NULL;
+
+ return &sub->val;
+ pv_get_branch_xname(msg, xname, &br_xname);
+ if ((xavp = xavp_get(&br_xname, NULL)) == NULL)
+ is_branch = 1;
+
+ if (is_branch == 0 && (xavp = xavp_get(xname, NULL)) == NULL)
+ goto err;
+
+ xavp = is_branch ? xavp_get_child(&br_xname, name)
+ : xavp_get_child(xname, name);
+ pv_str_free(&br_xname);
+
+ return xavp;
+
+err:
+ pv_str_free(&br_xname);
+ return NULL;
+}
+
+int pv_xavp_is_null(sr_xavp_t * avp)
@ -1724,7 +1799,7 @@
+ }
+
+ if (idx < 0) {
+ if ((xavp = xavp_get_child(&xavp_name, &hname)) == NULL)
+ if ((xavp = pv_xavp_get_child(msg, &xavp_name, &hname)) == NULL)
+ cnt = 0;
+ else
+ cnt = xavp_count(&hname, &xavp);
@ -1733,7 +1808,7 @@
+ pv_get_null(msg, param, res);
+ }
+
+ xval = pv_xavp_get_value(&xavp_name, &hname, idx);
+ xval = pv_xavp_get_value(msg, &xavp_name, &hname, idx);
+
+ if (xval == NULL || !xval->v.s.s)
+ return pv_get_null(msg, param, res);
@ -1777,7 +1852,7 @@
+ return -1;
+ }
+
+ if ((xavp = xavp_get_child(&xavp_name, &hname)) == NULL)
+ if ((xavp = pv_xavp_get_child(msg, &xavp_name, &hname)) == NULL)
+ idx = 0;
+ else if (idx < 0)
+ idx = idx + xavp_count(&hname, &xavp);
@ -1785,11 +1860,11 @@
+ if (val->flags & PV_VAL_NULL) {
+ if (itype == PV_IDX_ALL) {
+ for (idx=xavp_count(&hname, &xavp)-1;idx>=0;idx--) {
+ if (pv_set_xavp(&xavp_name, &hname, NULL, SR_XTYPE_STR, idx, 0) < 0)
+ if (pv_set_xavp(msg, &xavp_name, &hname, NULL, SR_XTYPE_STR, idx, 0) < 0)
+ goto err;
+ }
+ } else {
+ if (pv_set_xavp(&xavp_name, &hname, NULL, SR_XTYPE_STR, idx, 0) < 0)
+ if (pv_set_xavp(msg, &xavp_name, &hname, NULL, SR_XTYPE_STR, idx, 0) < 0)
+ goto err;
+ }
+ } else if (val->flags & PV_VAL_STR) {
@ -1804,19 +1879,19 @@
+ }
+ if (strlen(orig_hname.s) > 1 &&
+ strcmp(orig_hname.s+strlen(orig_hname.s)-2, "])") != 0) {
+ if (pv_set_xavp(&xavp_name, &hname, &fval, SR_XTYPE_STR, 0, 1) < 0)
+ if (pv_set_xavp(msg, &xavp_name, &hname, &fval, SR_XTYPE_STR, 0, 1) < 0)
+ goto err;
+ } else if (itype == PV_IDX_ALL) {
+ idx = 0;
+ cnt = xavp_count(&hname, &xavp);
+ while (idx < cnt) {
+ if (pv_set_xavp(&xavp_name, &hname, NULL, SR_XTYPE_STR, idx++, 0) < 1)
+ if (pv_set_xavp(msg, &xavp_name, &hname, NULL, SR_XTYPE_STR, idx++, 0) < 1)
+ goto err;
+ }
+ if (pv_set_xavp(&xavp_name, &hname, &fval, SR_XTYPE_STR, 0, cnt ? 0 : 1) < 0)
+ if (pv_set_xavp(msg, &xavp_name, &hname, &fval, SR_XTYPE_STR, 0, cnt ? 0 : 1) < 0)
+ goto err;
+ } else {
+ if (pv_set_xavp(&xavp_name, &hname, &fval, SR_XTYPE_STR, idx, 0) < 0)
+ if (pv_set_xavp(msg, &xavp_name, &hname, &fval, SR_XTYPE_STR, idx, 0) < 0)
+ goto err;
+ }
+ if (pv_format)
@ -1852,11 +1927,11 @@
+ else if (p_no >= 6 && p_no <= 10)
+ pv_str_copy(&hname, &(str){"To",2}, header_name_size);
+
+ xval = pv_xavp_get_value(&xavp_name, &hname, 0);
+ xval = pv_xavp_get_value(msg, &xavp_name, &hname, 0);
+ if (xval == NULL || !xval->v.s.s)
+ goto err;
+
+ xval_pd = pv_xavp_get_value(&xavp_parsed_xname, &hname, 0);
+ xval_pd = pv_xavp_get_value(msg, &xavp_parsed_xname, &hname, 0);
+
+ if (xval_pd &&
+ (c_data = (xavp_c_data_t*)xval_pd->v.data->p) != NULL &&
@ -1873,7 +1948,7 @@
+ memset(c_data, 0, sizeof(xavp_c_data_t));
+ if (pv_merge_uri(msg, SET_URI_T, &xval->v.s, &xval->v.s, c_data) < 0)
+ goto err;
+ if (pv_set_xavp(&xavp_parsed_xname, &hname, c_data, SR_XTYPE_DATA, 0, 0) < 0)
+ if (pv_set_xavp(msg, &xavp_parsed_xname, &hname, c_data, SR_XTYPE_DATA, 0, 0) < 0)
+ goto err;
+ }
+
@ -1961,7 +2036,7 @@
+ goto err;
+ }
+
+ xval = pv_xavp_get_value(&xavp_name, &hname, 0);
+ xval = pv_xavp_get_value(msg, &xavp_name, &hname, 0);
+ if (xval == NULL || !xval->v.s.s)
+ goto err;
+
@ -1974,10 +2049,10 @@
+ if (pv_merge_uri(msg, a_type, &xval->v.s, &fval, c_data) < 0)
+ goto err;
+
+ if (pv_set_xavp(&xavp_name, &hname, &c_data->value, SR_XTYPE_STR, 0, 0) < 0)
+ if (pv_set_xavp(msg, &xavp_name, &hname, &c_data->value, SR_XTYPE_STR, 0, 0) < 0)
+ goto err;
+
+ if (pv_set_xavp(&xavp_parsed_xname, &hname, c_data, SR_XTYPE_DATA, 0, 0) < 0)
+ if (pv_set_xavp(msg, &xavp_parsed_xname, &hname, c_data, SR_XTYPE_DATA, 0, 0) < 0)
+ goto err;
+
+ pv_str_free(&hname);
@ -2132,6 +2207,87 @@
+ free_to_params(&c_data->to_b);
+ return -1;
+}
+
+int pv_get_branch_index(struct sip_msg *msg, int *br_idx)
+{
+ qvalue_t q;
+ int br_len;
+ str ruid;
+
+ *br_idx = 0;
+ while ((get_branch(*br_idx,&br_len,&q,0,0,0,0,&ruid,0,0))) {
+ if (strcmp(msg->ruid.s, ruid.s) == 0)
+ break;
+ (*br_idx)++;
+ }
+
+ return 1;
+}
+
+int pv_get_branch_xname(struct sip_msg *msg, str *xname, str *dst)
+{
+ int br_idx;
+ int os = 0;
+
+ if (dst == NULL)
+ return -1;
+
+ memset(dst->s, 0, dst->len);
+ memcpy(dst->s, xname->s, xname->len); os+=xname->len;
+
+ pv_get_branch_index(msg, &br_idx);
+ if (br_idx > 0) {
+ memcpy(dst->s+os, "#", 1); os+=1;
+ memcpy(dst->s+os, msg->ruid.s, msg->ruid.len); os+=msg->ruid.len;
+ }
+ dst->len = os;
+ dst->s[dst->len] = '\0';
+
+ return 1;
+}
+
+static int pv_clone_branch_xavp(struct sip_msg *msg, str *br_xname)
+{
+ sr_xavp_t *xavp = NULL;
+ sr_xavp_t *br_xavp = NULL;
+ sr_xavp_t *sub = NULL;
+ sr_xval_t root_xval;
+
+ if ((xavp = xavp_get(&xavp_name, NULL)) == NULL) {
+ LM_ERR("cannot clone xavp from non existing %s\n" , xavp_name.s);
+ return -1;
+ }
+
+ if (xavp->val.type != SR_XTYPE_XAVP) {
+ LM_ERR("not xavp child type %s\n" , xavp_name.s);
+ return -1;
+ }
+
+ if ((sub = xavp->val.v.xavp) == NULL) {
+ LM_ERR("invalid xavp structure: %s\n", xavp_name.s);
+ return -1;
+ }
+
+ memset(&root_xval, 0, sizeof(sr_xval_t));
+ root_xval.type = SR_XTYPE_XAVP;
+ root_xval.v.xavp = NULL;
+
+ if ((br_xavp = xavp_add_value(br_xname, &root_xval, NULL)) == NULL) {
+ LM_ERR("error create xavp %s\n", br_xname->s);
+ return -1;
+ }
+
+ do {
+ if (pv_skip_header(&sub->name) == 1)
+ continue;
+ if (pv_xavp_append_value(&sub->name, &sub->val, &br_xavp->val.v.xavp) < 0) {
+ LM_ERR("cannot clone xavp xavp %s\n", sub->name.s);
+ return -1;
+ }
+ } while ((sub = sub->next) != NULL);
+
+ return 1;
+}
--- /dev/null
+++ b/src/modules/pv_headers/pv_headers.h
@@ -0,0 +1,30 @@

Loading…
Cancel
Save