diff --git a/debian/patches/sipwise/add_pv_headers_module.patch b/debian/patches/sipwise/add_pv_headers_module.patch index 3f60f98ab..8ca15d2cd 100644 --- a/debian/patches/sipwise/add_pv_headers_module.patch +++ b/debian/patches/sipwise/add_pv_headers_module.patch @@ -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;idxval.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 @@