Browse code

Merge b948fb3669b361d1dde51889bd1a5ec097a1e634 into 1ba6f2fa77459ed1fcec04f446fe9e8c210b94d6

Nicolas C authored on 28/11/2021 15:49:26 • GitHub committed on 28/11/2021 15:49:26
Showing 1 changed files
... ...
@@ -32,6 +32,7 @@
32 32
 #include "../../core/strutils.h"
33 33
 #include "../../core/tcp_conn.h"
34 34
 #include "../../core/pvapi.h"
35
+#include "../../core/xavp.h"
35 36
 #include "../../core/ppcfg.h"
36 37
 #include "../../core/trim.h"
37 38
 #include "../../core/msg_translator.h"
... ...
@@ -2607,15 +2608,148 @@ int pv_get_cnt(struct sip_msg *msg, pv_param_t *param,
2607 2608
 	if(pv==NULL)
2608 2609
 		return pv_get_null(msg, param, res);
2609 2610
 
2610
-	if(pv_get_avp_name(0, &pv->pvp, &avp_name, &avp_type)!=0)
2611
-	{
2612
-		LM_ERR("invalid AVP definition\n");
2613
-		return pv_get_null(msg, param, res);
2614
-	}
2615
-	avp=search_first_avp(avp_type, avp_name, NULL, &state);
2616
-	while(avp) {
2617
-		n++;
2618
-		avp=search_next_avp(&state, NULL);
2611
+	switch(pv->type) {
2612
+		case PVT_AVP:
2613
+			if(pv_get_avp_name(0, &pv->pvp, &avp_name, &avp_type)!=0)
2614
+			{
2615
+				LM_ERR("invalid AVP definition\n");
2616
+				return pv_get_null(msg, param, res);
2617
+			}
2618
+			avp=search_first_avp(avp_type, avp_name, NULL, &state);
2619
+			while(avp) {
2620
+				n++;
2621
+				avp=search_next_avp(&state, NULL);
2622
+			}
2623
+		break;
2624
+
2625
+		case PVT_XAVP:
2626
+		{
2627
+			/* Usage:
2628
+			 *
2629
+			 * $cnt($xavp(key[*])) : number of XAVPs "key".
2630
+			 * $cnt($xavp(key[n]=>sub[*])) : number of children "sub" in XAVP "key[n]".
2631
+			 * $cnt($xavp(key[*]=>sub[*])) : total number of children "sub" in all XAVPs "key".
2632
+			 *
2633
+			 * $cnt($xavp(key[n])) : 1 or 0 (if this index exists or not).
2634
+			 * $cnt($xavp(key[-n])) : same but with reverse indexing (-1 is the last index).
2635
+			 *
2636
+			 * $cnt($xavp(key[*]=>sub[n] : number of children "sub[n]" that exist in all XAPVs "key".
2637
+			 *
2638
+			 * $cnt($xavp(key)) is the same as $cnt($xavp(key[*])).
2639
+			 * $cnt($xavp(key=>sub)) is the same as $cnt($xavp(key[*]=>sub[*])).
2640
+			 *
2641
+			 * Note: Usually for a XAVP no index means "index 0", not all.
2642
+			 * But this would be less intuitive in our case for counting.
2643
+			 */
2644
+			pv_xavp_name_t *xname, *xname_sub;
2645
+			sr_xavp_t *ravp, *sub_avp;
2646
+			int root_idxf, root_idx_spec, root_idx;
2647
+			int sub_idxf, sub_idx_spec, sub_idx;
2648
+			int count;
2649
+
2650
+			xname = pv->pvp.pvn.u.dname;
2651
+			if (xname == NULL) {
2652
+				LM_ERR("invalid XAVP definition\n");
2653
+				return pv_get_null(msg, param, res);
2654
+			}
2655
+			xname_sub = xname->next; /* NULL if no sub-key is provided */
2656
+
2657
+			/* No index or index * means: count all entries */
2658
+			int root_all = 1;
2659
+			if (xname->index.type == PVT_EXTRA) {
2660
+				/* Get root index */
2661
+				if (pv_get_spec_index(msg, &xname->index.pvp, &root_idx_spec, &root_idxf) != 0) {
2662
+					LM_ERR("invalid XAVP root index\n");
2663
+					return pv_get_null(msg, param, res);
2664
+				}
2665
+				if (!(root_idxf == PV_IDX_ALL)) root_all = 0;
2666
+			}
2667
+			if (!root_all) {
2668
+				/* Fix root index (if negative) */
2669
+				if (root_idx_spec >= 0) {
2670
+					root_idx = root_idx_spec;
2671
+				} else {
2672
+					count = xavp_count(&xname->name, NULL);
2673
+					root_idx = count + root_idx_spec;
2674
+				}
2675
+				ravp = xavp_get_by_index(&xname->name, root_idx, NULL);
2676
+			}
2677
+
2678
+			if (xname_sub == NULL) {
2679
+				/* No XAVP sub-key */
2680
+				if (root_all) {
2681
+					/* Count all root XAVP */
2682
+					n = xavp_count(&xname->name, NULL);
2683
+				} else {
2684
+					/* Check if specific root XAVP index exists */
2685
+					if (ravp) n = 1;
2686
+				}
2687
+
2688
+			} else {
2689
+				/* Having a XAVP sub-key */
2690
+				/* No index or index * means: count all entries */
2691
+				int sub_all = 1;
2692
+				if (xname_sub->index.type == PVT_EXTRA) {
2693
+					/* Get sub index */
2694
+					if (pv_get_spec_index(msg, &xname_sub->index.pvp, &sub_idx_spec, &sub_idxf) != 0) {
2695
+						LM_ERR("invalid XAVP sub index\n");
2696
+						return pv_get_null(msg, param, res);
2697
+					}
2698
+					if (!(sub_idxf == PV_IDX_ALL)) sub_all = 0;
2699
+				}
2700
+
2701
+				if (!root_all) {
2702
+					/* If the root XAVP value is not of type XAVP then nothing to count */
2703
+					if (ravp && ravp->val.type == SR_XTYPE_XAVP) {
2704
+						if (sub_all) {
2705
+							/* Count all sub XAVP within root XAVP */
2706
+							n = xavp_count(&xname_sub->name, &ravp->val.v.xavp);
2707
+						} else {
2708
+							/* Check if specific sub XAVP index exists within root XAVP */
2709
+							/* Fix sub index (if negative) */
2710
+							if (sub_idx_spec >= 0) {
2711
+								sub_idx = sub_idx_spec;
2712
+							} else {
2713
+								count = xavp_count(&xname_sub->name, &ravp->val.v.xavp);
2714
+								sub_idx = count + sub_idx_spec;
2715
+							}
2716
+							sub_avp = xavp_get_by_index(&xname_sub->name, sub_idx, &ravp->val.v.xavp);
2717
+							if (sub_avp) n = 1;
2718
+						}
2719
+					}
2720
+
2721
+				} else {
2722
+					/* Iterate on root XAVP. For each, count the sub XAVP. */
2723
+					ravp = xavp_get(&xname->name, NULL);
2724
+					while (ravp) {
2725
+						/* If the root XAVP value is not of type XAVP then nothing to count */
2726
+						if (ravp->val.type == SR_XTYPE_XAVP) {
2727
+							if (sub_all) {
2728
+								/* Count all sub XAVP within root XAVP */
2729
+								n += xavp_count(&xname_sub->name, &ravp->val.v.xavp);
2730
+							} else {
2731
+								/* Check if specific sub XAVP index exists within root XAVP */
2732
+								/* Fix sub index (if negative) */
2733
+								if (sub_idx_spec >= 0) {
2734
+									sub_idx = sub_idx_spec;
2735
+								} else {
2736
+									count = xavp_count(&xname_sub->name, &ravp->val.v.xavp);
2737
+									sub_idx = count + sub_idx_spec;
2738
+								}
2739
+								sub_avp = xavp_get_by_index(&xname_sub->name, sub_idx, &ravp->val.v.xavp);
2740
+								if (sub_avp) n += 1;
2741
+							}
2742
+						}
2743
+						ravp = xavp_get_next(ravp);
2744
+					}
2745
+				}
2746
+			}
2747
+		}
2748
+		break;
2749
+
2750
+		default:
2751
+			LM_ERR("invalid type: neither AVP nor XAVP\n");
2752
+			return pv_get_null(msg, param, res);
2619 2753
 	}
2620 2754
 
2621 2755
 	return pv_get_uintval(msg, param, res, n);
... ...
@@ -3672,8 +3806,8 @@ int pv_parse_cnt_name(pv_spec_p sp, str *in)
3672 3806
 		return -1;
3673 3807
 	}
3674 3808
 
3675
-	if(pv->type!=PVT_AVP) {
3676
-		LM_ERR("expected avp name instead of [%.*s]\n", in->len, in->s);
3809
+	if(pv->type!=PVT_AVP && pv->type!=PVT_XAVP) {
3810
+		LM_ERR("expected avp or xavp name instead of [%.*s]\n", in->len, in->s);
3677 3811
 		return -1;
3678 3812
 	}
3679 3813