Browse code

pv: added $rpl(key) variable

- return attributes of the sip reply that is processed at that moment
- the key can be:
- duri - SIP URI corresponding to the destination address where the
reply is going to be sent based on 2nd via
- dhost - host part of duri
- dport - port part of duri
- dproto - proto of duri
- dprotoid - proto id of duri
- cntvia - number of via header bodies

Daniel-Constantin Mierla authored on 12/05/2021 11:11:26
Showing 3 changed files
... ...
@@ -538,6 +538,8 @@ static pv_export_t mod_pvs[] = {
538 538
 		pv_parse_msg_attrs_name, 0, 0, 0 },
539 539
 	{ {"ksr", (sizeof("ksr")-1)}, PVT_OTHER, pv_get_ksr_attrs, 0,
540 540
 		pv_parse_ksr_attrs_name, 0, 0, 0 },
541
+	{{"rpl", (sizeof("rpl")-1)}, PVT_OTHER, pv_get_rpl_attrs, 0,
542
+		pv_parse_rpl_attrs_name, 0, 0, 0},
541 543
 
542 544
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
543 545
 };
... ...
@@ -3751,3 +3751,146 @@ int pv_get_ksr_attrs(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
3751 3751
 			return pv_get_null(msg, param, res);
3752 3752
 	}
3753 3753
 }
3754
+
3755
+
3756
+/**
3757
+ *
3758
+ */
3759
+int pv_parse_rpl_attrs_name(pv_spec_p sp, str *in)
3760
+{
3761
+	if(sp==NULL || in==NULL || in->len<=0)
3762
+		return -1;
3763
+
3764
+	/* attributes not related to dst of reply get an id starting with 20 */
3765
+	switch(in->len) {
3766
+		case 4:
3767
+			if(strncmp(in->s, "duri", 4)==0)
3768
+				sp->pvp.pvn.u.isname.name.n = 0;
3769
+			else goto error;
3770
+		break;
3771
+		case 5:
3772
+			if(strncmp(in->s, "dhost", 5)==0)
3773
+				sp->pvp.pvn.u.isname.name.n = 1;
3774
+			else if(strncmp(in->s, "dport", 5)==0)
3775
+				sp->pvp.pvn.u.isname.name.n = 2;
3776
+			else goto error;
3777
+		break;
3778
+		case 6:
3779
+			if(strncmp(in->s, "dproto", 6)==0)
3780
+				sp->pvp.pvn.u.isname.name.n = 3;
3781
+			else if(strncmp(in->s, "cntvia", 6)==0)
3782
+				sp->pvp.pvn.u.isname.name.n = 20;
3783
+			else goto error;
3784
+		break;
3785
+		case 8:
3786
+			if(strncmp(in->s, "dprotoid", 8)==0)
3787
+				sp->pvp.pvn.u.isname.name.n = 4;
3788
+			else goto error;
3789
+		break;
3790
+
3791
+		default:
3792
+			goto error;
3793
+	}
3794
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
3795
+	sp->pvp.pvn.u.isname.type = 0;
3796
+
3797
+	return 0;
3798
+
3799
+error:
3800
+	LM_ERR("unknown PV rpl key: %.*s\n", in->len, in->s);
3801
+	return -1;
3802
+}
3803
+
3804
+
3805
+/**
3806
+ *
3807
+ */
3808
+int pv_get_rpl_attrs(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
3809
+{
3810
+	static char rpluribuf[MAX_URI_SIZE];
3811
+	str suri = STR_NULL;
3812
+	str host = STR_NULL;
3813
+	str sproto = STR_NULL;
3814
+	unsigned int port = 0;
3815
+	hdr_field_t *hf = NULL;
3816
+
3817
+	if(param==NULL) {
3818
+		return pv_get_null(msg, param, res);
3819
+	}
3820
+
3821
+	if(!IS_SIP_REPLY(msg)) {
3822
+		return pv_get_null(msg, param, res);
3823
+	}
3824
+	if(param->pvn.u.isname.name.n<20) {
3825
+		if(parse_headers( msg, HDR_VIA2_F, 0)==-1) {
3826
+			LM_DBG("no 2nd via parsed\n");
3827
+			return pv_get_null(msg, param, res);
3828
+		}
3829
+		if((msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
3830
+			return pv_get_null(msg, param, res);
3831
+		}
3832
+		if(msg->via2->rport && msg->via2->rport->value.s) {
3833
+			LM_DBG("using 'rport'\n");
3834
+			if(str2int(&msg->via2->rport->value, &port)<0) {
3835
+				LM_ERR("invalid rport value\n");
3836
+				return pv_get_null(msg, param, res);
3837
+			}
3838
+		}
3839
+		if(msg->via2->received) {
3840
+			LM_DBG("using 'received'\n");
3841
+			host = msg->via2->received->value;
3842
+		} else {
3843
+			LM_DBG("using via host\n");
3844
+			host = msg->via2->host;
3845
+		}
3846
+		if(port==0) {
3847
+			port = (msg->via2->port)?msg->via2->port:SIP_PORT;
3848
+		}
3849
+	}
3850
+	switch(param->pvn.u.isname.name.n) {
3851
+		case 0: /* dst uri */
3852
+			if(get_valid_proto_string(msg->via2->proto, 1, 0, &sproto)<0) {
3853
+				sproto.s = "udp";
3854
+				sproto.len = 3;
3855
+			}
3856
+			suri.len = snprintf(rpluribuf, MAX_URI_SIZE, "sip:%.*s:%u;transport=%.*s",
3857
+					host.len, host.s, port, sproto.len, sproto.s);
3858
+			if(suri.len<=0 || suri.len>=MAX_URI_SIZE) {
3859
+				LM_DBG("building the dst uri failed (%d)\n", suri.len);
3860
+				return pv_get_null(msg, param, res);
3861
+			}
3862
+			suri.s = rpluribuf;
3863
+			return pv_get_strval(msg, param, res, &suri);
3864
+		case 1: /* dst host */
3865
+			return pv_get_strval(msg, param, res, &host);
3866
+		case 2: /* dst port */
3867
+			return pv_get_uintval(msg, param, res, port);
3868
+		case 3: /* dst proto */
3869
+			if(get_valid_proto_string(msg->via2->proto, 0, 0, &sproto)<0) {
3870
+				sproto.s = "udp";
3871
+				sproto.len = 3;
3872
+			}
3873
+			return pv_get_strintval(msg, param, res, &sproto,
3874
+					(int)msg->via2->proto);
3875
+		case 4: /* dst protoid */
3876
+			return pv_get_uintval(msg, param, res, msg->via2->proto);
3877
+		case 20: /* count of via */
3878
+			if (parse_headers(msg, HDR_EOH_F, 0)<0) {
3879
+				LM_DBG("failed to parse sip headers\n");
3880
+				return pv_get_uintval(msg, param, res, 0);
3881
+			}
3882
+			port = 0;
3883
+			for(hf=msg->h_via1; hf!=NULL; hf=hf->next) {
3884
+				if(hf->type==HDR_VIA_T) {
3885
+					via_body_t *vb;
3886
+					for(vb=(via_body_t*)hf->parsed; vb!=NULL; vb=vb->next) {
3887
+						port++;
3888
+					}
3889
+				}
3890
+			}
3891
+			return pv_get_uintval(msg, param, res, port);
3892
+
3893
+		default:
3894
+			return pv_get_null(msg, param, res);
3895
+	}
3896
+}
... ...
@@ -393,5 +393,10 @@ int pv_parse_ksr_attrs_name(pv_spec_p sp, str *in);
393 393
 int pv_get_ksr_attrs(sip_msg_t *msg, pv_param_t *param,
394 394
 		pv_value_t *res);
395 395
 
396
+int pv_parse_rpl_attrs_name(pv_spec_p sp, str *in);
397
+
398
+int pv_get_rpl_attrs(sip_msg_t *msg, pv_param_t *param,
399
+		pv_value_t *res);
400
+
396 401
 #endif
397 402