Browse code

pv: new variables $hfl(name)

- similar to $hdr(name), but for some of the standard headers that can
have many bodies serialized in the same header field is able to return the
individual body values
- so far implemented for Via
- for the rest of the headers works like $hdr(name)

Daniel-Constantin Mierla authored on 27/05/2021 13:18:46
Showing 3 changed files
... ...
@@ -108,6 +108,8 @@ static pv_export_t mod_pvs[] = {
108 108
 		pv_parse_index, 0, 0},
109 109
 	{{"hdrc", (sizeof("hdrc")-1)}, PVT_HDRC, pv_get_hdrc, 0, pv_parse_hdr_name,
110 110
 		0, 0, 0},
111
+	{{"hfl", (sizeof("hfl")-1)}, PVT_HDR, pv_get_hfl, 0, pv_parse_hfl_name,
112
+		pv_parse_index, 0, 0},
111 113
 	{{"var", (sizeof("var")-1)}, PVT_SCRIPTVAR, pv_get_scriptvar,
112 114
 		pv_set_scriptvar, pv_parse_scriptvar_name, 0, 0, 0},
113 115
 	{{"vz", (sizeof("vz")-1)}, PVT_SCRIPTVAR, pv_get_scriptvar,
... ...
@@ -1959,91 +1959,55 @@ int pv_get_avp(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
1959 1959
 	return pv_get_null(msg, param, res);
1960 1960
 }
1961 1961
 
1962
-int pv_get_hdr(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
1962
+int pv_get_hdr_helper(sip_msg_t *msg, pv_param_t *param, pv_value_t *res,
1963
+		pv_value_t *tv, int idx, int idxf)
1963 1964
 {
1964
-	int idx;
1965
-	int idxf;
1966
-	pv_value_t tv;
1967 1965
 	struct hdr_field *hf;
1968 1966
 	struct hdr_field *hf0;
1969 1967
 	char *p, *p_ini;
1970 1968
 	int n, p_size;
1971 1969
 
1972
-	if(msg==NULL || res==NULL || param==NULL)
1973
-		return -1;
1974
-
1975
-	/* get the name */
1976
-	if(param->pvn.type == PV_NAME_PVAR)
1977
-	{
1978
-		if(pv_get_spec_name(msg, param, &tv)!=0 || (!(tv.flags&PV_VAL_STR)))
1979
-		{
1980
-			LM_ERR("invalid name\n");
1981
-			return -1;
1982
-		}
1983
-	} else {
1984
-		if(param->pvn.u.isname.type == AVP_NAME_STR)
1985
-		{
1986
-			tv.flags = PV_VAL_STR;
1987
-			tv.rs = param->pvn.u.isname.name.s;
1988
-		} else {
1989
-			tv.flags = 0;
1990
-			tv.ri = param->pvn.u.isname.name.n;
1991
-		}
1992
-	}
1993 1970
 	/* we need to be sure we have parsed all headers */
1994
-	if(parse_headers(msg, HDR_EOH_F, 0)<0)
1995
-	{
1971
+	if(parse_headers(msg, HDR_EOH_F, 0)<0) {
1996 1972
 		LM_ERR("error parsing headers\n");
1997 1973
 		return pv_get_null(msg, param, res);
1998 1974
 	}
1999 1975
 
2000
-	for (hf=msg->headers; hf; hf=hf->next)
2001
-	{
2002
-		if(tv.flags == 0)
2003
-		{
2004
-			if (tv.ri==hf->type)
1976
+	for (hf=msg->headers; hf; hf=hf->next) {
1977
+		if(tv->flags == 0) {
1978
+			if (tv->ri==hf->type)
2005 1979
 				break;
2006 1980
 		} else {
2007
-			if(tv.rs.len==1 && tv.rs.s[0]=='*')
1981
+			if(tv->rs.len==1 && tv->rs.s[0]=='*')
2008 1982
 				break;
2009
-			if (cmp_hdrname_str(&hf->name, &tv.rs)==0)
1983
+			if (cmp_hdrname_str(&hf->name, &tv->rs)==0)
2010 1984
 				break;
2011 1985
 		}
2012 1986
 	}
2013
-	if(hf==NULL)
1987
+	if(hf==NULL) {
2014 1988
 		return pv_get_null(msg, param, res);
2015
-	/* get the index */
2016
-	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
2017
-	{
2018
-		LM_ERR("invalid index\n");
2019
-		return -1;
2020 1989
 	}
2021 1990
 
2022 1991
 	/* get the value */
2023 1992
 	res->flags = PV_VAL_STR;
2024
-	if(idx==0 && (idxf==PV_IDX_INT || idxf==PV_IDX_NONE))
2025
-	{
1993
+	if(idx==0 && (idxf==PV_IDX_INT || idxf==PV_IDX_NONE)) {
2026 1994
 		res->rs  = hf->body;
2027 1995
 		return 0;
2028 1996
 	}
2029
-	if(idxf==PV_IDX_ALL)
2030
-	{
1997
+	if(idxf==PV_IDX_ALL) {
2031 1998
 		p_ini = pv_get_buffer();
2032 1999
 		p = p_ini;
2033 2000
 		p_size = pv_get_buffer_size();
2034 2001
 		do {
2035
-			if(p!=p_ini)
2036
-			{
2037
-				if(p-p_ini+PV_FIELD_DELIM_LEN+1>p_size)
2038
-				{
2002
+			if(p!=p_ini) {
2003
+				if(p-p_ini+PV_FIELD_DELIM_LEN+1>p_size) {
2039 2004
 					LM_ERR("local buffer length exceeded\n");
2040 2005
 					return pv_get_null(msg, param, res);
2041 2006
 				}
2042 2007
 				memcpy(p, PV_HDR_DELIM, PV_HDR_DELIM_LEN);
2043 2008
 				p += PV_HDR_DELIM_LEN;
2044 2009
 			}
2045
-			if(p-p_ini+hf->body.len+1>p_size)
2046
-			{
2010
+			if(p-p_ini+hf->body.len+1>p_size) {
2047 2011
 				LM_ERR("local buffer length exceeded [%d/%d]!\n",
2048 2012
 						(int)(p-p_ini+hf->body.len+1),
2049 2013
 						hf->body.len);
... ...
@@ -2052,16 +2016,14 @@ int pv_get_hdr(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2052 2016
 			memcpy(p, hf->body.s, hf->body.len);
2053 2017
 			p += hf->body.len;
2054 2018
 			/* next hf */
2055
-			for (hf=hf->next; hf; hf=hf->next)
2056
-			{
2057
-				if(tv.flags == 0)
2058
-				{
2059
-					if (tv.ri==hf->type)
2019
+			for (hf=hf->next; hf; hf=hf->next) {
2020
+				if(tv->flags == 0) {
2021
+					if (tv->ri==hf->type)
2060 2022
 						break;
2061 2023
 				} else {
2062
-					if(tv.rs.len==1 && tv.rs.s[0]=='*')
2024
+					if(tv->rs.len==1 && tv->rs.s[0]=='*')
2063 2025
 						break;
2064
-					if (cmp_hdrname_str(&hf->name, &tv.rs)==0)
2026
+					if (cmp_hdrname_str(&hf->name, &tv->rs)==0)
2065 2027
 						break;
2066 2028
 				}
2067 2029
 			}
... ...
@@ -2073,50 +2035,42 @@ int pv_get_hdr(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2073 2035
 
2074 2036
 	/* we have a numeric index */
2075 2037
 	hf0 = 0;
2076
-	if(idx<0)
2077
-	{
2038
+	if(idx<0) {
2078 2039
 		n = 1;
2079 2040
 		/* count headers */
2080
-		for (hf0=hf->next; hf0; hf0=hf0->next)
2081
-		{
2082
-			if(tv.flags == 0)
2083
-			{
2084
-				if (tv.ri==hf0->type)
2041
+		for (hf0=hf->next; hf0; hf0=hf0->next) {
2042
+			if(tv->flags == 0) {
2043
+				if (tv->ri==hf0->type)
2085 2044
 					n++;
2086 2045
 			} else {
2087
-				if(tv.rs.len==1 && tv.rs.s[0]=='*') {
2046
+				if(tv->rs.len==1 && tv->rs.s[0]=='*') {
2088 2047
 					n++;
2089
-				} else if (cmp_hdrname_str(&hf0->name, &tv.rs)==0) {
2048
+				} else if (cmp_hdrname_str(&hf0->name, &tv->rs)==0) {
2090 2049
 					n++;
2091 2050
 				}
2092 2051
 			}
2093 2052
 		}
2094 2053
 		idx = -idx;
2095
-		if(idx>n)
2096
-		{
2054
+		if(idx>n) {
2097 2055
 			LM_DBG("index out of range\n");
2098 2056
 			return pv_get_null(msg, param, res);
2099 2057
 		}
2100 2058
 		idx = n - idx;
2101
-		if(idx==0)
2102
-		{
2059
+		if(idx==0) {
2103 2060
 			res->rs  = hf->body;
2104 2061
 			return 0;
2105 2062
 		}
2106 2063
 	}
2107 2064
 	n=0;
2108
-	while(n<idx)
2109
-	{
2110
-		for (hf0=hf->next; hf0; hf0=hf0->next)
2111
-		{
2112
-			if(tv.flags == 0)
2113
-			{
2114
-				if (tv.ri==hf0->type)
2065
+	while(n<idx) {
2066
+		for (hf0=hf->next; hf0; hf0=hf0->next) {
2067
+			if(tv->flags == 0) {
2068
+				if (tv->ri==hf0->type)
2115 2069
 					n++;
2116 2070
 			} else {
2117
-				if(tv.rs.len==1 && tv.rs.s[0]=='*') {
2071
+				if(tv->rs.len==1 && tv->rs.s[0]=='*') {
2118 2072
 					n++;
2119
-				} else if (cmp_hdrname_str(&hf0->name, &tv.rs)==0) {
2073
+				} else if (cmp_hdrname_str(&hf0->name, &tv->rs)==0) {
2120 2074
 					n++;
2121 2075
 				}
2122 2076
 			}
... ...
@@ -2127,15 +2081,48 @@ int pv_get_hdr(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2127 2081
 			break;
2128 2082
 	}
2129 2083
 
2130
-	if(hf0!=0)
2131
-	{
2084
+	if(hf0!=0) {
2132 2085
 		res->rs  = hf0->body;
2133 2086
 		return 0;
2134 2087
 	}
2135 2088
 
2136 2089
 	LM_DBG("index out of range\n");
2137 2090
 	return pv_get_null(msg, param, res);
2091
+}
2092
+
2093
+/**
2094
+ *
2095
+ */
2096
+int pv_get_hdr(sip_msg_t *msg,  pv_param_t *param, pv_value_t *res)
2097
+{
2098
+	int idx;
2099
+	int idxf;
2100
+	pv_value_t tv = {0};
2101
+
2102
+	if(msg==NULL || res==NULL || param==NULL)
2103
+		return -1;
2138 2104
 
2105
+	/* get the name */
2106
+	if(param->pvn.type == PV_NAME_PVAR) {
2107
+		if(pv_get_spec_name(msg, param, &tv)!=0 || (!(tv.flags&PV_VAL_STR))) {
2108
+			LM_ERR("invalid name\n");
2109
+			return -1;
2110
+		}
2111
+	} else {
2112
+		if(param->pvn.u.isname.type == AVP_NAME_STR) {
2113
+			tv.flags = PV_VAL_STR;
2114
+			tv.rs = param->pvn.u.isname.name.s;
2115
+		} else {
2116
+			tv.flags = 0;
2117
+			tv.ri = param->pvn.u.isname.name.n;
2118
+		}
2119
+	}
2120
+	/* get the index */
2121
+	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
2122
+		LM_ERR("invalid index\n");
2123
+		return -1;
2124
+	}
2125
+	return pv_get_hdr_helper(msg, param, res, &tv, idx, idxf);
2139 2126
 }
2140 2127
 
2141 2128
 /**
... ...
@@ -2194,6 +2181,98 @@ int pv_get_hdrc(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2194 2181
 	return pv_get_sintval(msg, param, res, hcount);
2195 2182
 }
2196 2183
 
2184
+/**
2185
+ *
2186
+ */
2187
+int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2188
+{
2189
+	int idx = 0;
2190
+	int idxf = 0;
2191
+	pv_value_t tv = {0};
2192
+	via_body_t *vb = NULL;
2193
+	hdr_field_t *hf = NULL;
2194
+	int n = 0;
2195
+	str sval = STR_NULL;
2196
+
2197
+	if(msg==NULL || res==NULL || param==NULL)
2198
+		return -1;
2199
+
2200
+	/* get the name */
2201
+	if(param->pvn.type == PV_NAME_PVAR) {
2202
+		if(pv_get_spec_name(msg, param, &tv)!=0 || (!(tv.flags&PV_VAL_STR))) {
2203
+			LM_ERR("invalid name\n");
2204
+			return -1;
2205
+		}
2206
+	} else {
2207
+		if(param->pvn.u.isname.type == AVP_NAME_STR) {
2208
+			tv.flags = PV_VAL_STR;
2209
+			tv.rs = param->pvn.u.isname.name.s;
2210
+		} else {
2211
+			tv.flags = 0;
2212
+			tv.ri = param->pvn.u.isname.name.n;
2213
+		}
2214
+	}
2215
+	/* get the index */
2216
+	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
2217
+		LM_ERR("invalid index\n");
2218
+		return -1;
2219
+	}
2220
+	if((tv.flags != 0) || (idxf==PV_IDX_ALL)) {
2221
+		return pv_get_hdr_helper(msg, param, res, &tv, idx, idxf);
2222
+	}
2223
+	if (parse_headers(msg, HDR_EOH_F, 0)<0) {
2224
+		LM_DBG("failed to parse sip headers\n");
2225
+		return pv_get_null(msg, param, res);
2226
+	}
2227
+
2228
+	if((tv.flags == 0) && (tv.ri==HDR_VIA_T)) {
2229
+		if(idx<0) {
2230
+			n = 1;
2231
+			/* count Vua header bodies */
2232
+			for(hf=msg->h_via1; hf!=NULL; hf=hf->next) {
2233
+				if(hf->type==HDR_VIA_T) {
2234
+					for(vb=(via_body_t*)hf->parsed; vb!=NULL; vb=vb->next) {
2235
+						n++;
2236
+					}
2237
+				}
2238
+			}
2239
+
2240
+			idx = -idx;
2241
+			if(idx>n) {
2242
+				LM_DBG("index out of range\n");
2243
+				return pv_get_null(msg, param, res);
2244
+			}
2245
+			idx = n - idx;
2246
+		}
2247
+		if(idx==0) {
2248
+			vb = (via_body_t*)(msg->h_via1->parsed);
2249
+			sval.s = vb->name.s;
2250
+			sval.len = vb->bsize;
2251
+			trim(&sval);
2252
+			res->rs = sval;
2253
+			return 0;
2254
+		}
2255
+		n=0;
2256
+		for(hf=msg->h_via1; hf!=NULL; hf=hf->next) {
2257
+			if(hf->type==HDR_VIA_T) {
2258
+				for(vb=(via_body_t*)hf->parsed; vb!=NULL; vb=vb->next) {
2259
+					if(n==idx) {
2260
+						sval.s = vb->name.s;
2261
+						sval.len = vb->bsize;
2262
+						trim(&sval);
2263
+						res->rs = sval;
2264
+						return 0;
2265
+					}
2266
+					n++;
2267
+				}
2268
+			}
2269
+		}
2270
+		LM_DBG("unexpected via index out of range\n");
2271
+		return pv_get_null(msg, param, res);
2272
+	}
2273
+	return pv_get_hdr_helper(msg, param, res, &tv, idx, idxf);
2274
+}
2275
+
2197 2276
 /**
2198 2277
  *
2199 2278
  */
... ...
@@ -3298,6 +3377,11 @@ error:
3298 3377
 	return -1;
3299 3378
 }
3300 3379
 
3380
+int pv_parse_hfl_name(pv_spec_t *sp, str *in)
3381
+{
3382
+	return pv_parse_hdr_name(sp, in);
3383
+}
3384
+
3301 3385
 int pv_parse_cnt_name(pv_spec_p sp, str *in)
3302 3386
 {
3303 3387
 	pv_spec_t *pv=NULL;
... ...
@@ -249,10 +249,12 @@ int pv_get_branches(struct sip_msg *msg, pv_param_t *param,
249 249
 
250 250
 int pv_get_avp(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res);
251 251
 
252
-int pv_get_hdr(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res);
252
+int pv_get_hdr(sip_msg_t *msg,  pv_param_t *param, pv_value_t *res);
253 253
 
254 254
 int pv_get_hdrc(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res);
255 255
 
256
+int pv_get_hfl(sip_msg_t *msg,  pv_param_t *param, pv_value_t *res);
257
+
256 258
 int pv_get_scriptvar(struct sip_msg *msg,  pv_param_t *param,
257 259
 		pv_value_t *res);
258 260
 
... ...
@@ -359,6 +361,8 @@ int pv_parse_scriptvarnull_name(pv_spec_p sp, str *in);
359 361
 
360 362
 int pv_parse_hdr_name(pv_spec_p sp, str *in);
361 363
 
364
+int pv_parse_hfl_name(pv_spec_p sp, str *in);
365
+
362 366
 int pv_parse_cnt_name(pv_spec_p sp, str *in);
363 367
 
364 368
 int pv_parse_af_name(pv_spec_p sp, str *in);