Browse code

pv: extended $nh(k) to work for replies using 2nd via

Daniel-Constantin Mierla authored on 09/06/2021 10:02:08
Showing 1 changed files
... ...
@@ -669,6 +669,81 @@ error:
669 669
 	return -1;
670 670
 }
671 671
 
672
+/**
673
+ *
674
+ */
675
+int pv_get_nh_reply(struct sip_msg *msg, pv_param_t *param,
676
+		pv_value_t *res)
677
+{
678
+	static char rpluribuf[MAX_URI_SIZE];
679
+	str suri = STR_NULL;
680
+	str host = STR_NULL;
681
+	str sproto = STR_NULL;
682
+	unsigned int port = 0;
683
+
684
+	if(parse_headers( msg, HDR_VIA2_F, 0)==-1) {
685
+		LM_DBG("no 2nd via parsed\n");
686
+		return pv_get_null(msg, param, res);
687
+	}
688
+	if((msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
689
+		return pv_get_null(msg, param, res);
690
+	}
691
+	if(msg->via2->rport && msg->via2->rport->value.s) {
692
+		LM_DBG("using 'rport'\n");
693
+		if(str2int(&msg->via2->rport->value, &port)<0) {
694
+			LM_ERR("invalid rport value\n");
695
+			return pv_get_null(msg, param, res);
696
+		}
697
+	}
698
+	if(msg->via2->received) {
699
+		LM_DBG("using 'received'\n");
700
+		host = msg->via2->received->value;
701
+	} else {
702
+		LM_DBG("using via host\n");
703
+		host = msg->via2->host;
704
+	}
705
+	if(port==0) {
706
+		port = (msg->via2->port)?msg->via2->port:SIP_PORT;
707
+	}
708
+
709
+	switch(param->pvn.u.isname.name.n) {
710
+		case 0: /* uri */
711
+			if(get_valid_proto_string(msg->via2->proto, 1, 0, &sproto)<0) {
712
+				sproto.s = "udp";
713
+				sproto.len = 3;
714
+			}
715
+			suri.len = snprintf(rpluribuf, MAX_URI_SIZE, "sip:%.*s:%u;transport=%.*s",
716
+					host.len, host.s, port, sproto.len, sproto.s);
717
+			if(suri.len<=0 || suri.len>=MAX_URI_SIZE) {
718
+				LM_DBG("building the dst uri failed (%d)\n", suri.len);
719
+				return pv_get_null(msg, param, res);
720
+			}
721
+			suri.s = rpluribuf;
722
+			return pv_get_strval(msg, param, res, &suri);
723
+		case 1: /* user - not in Via */
724
+			return pv_get_null(msg, param, res);
725
+		case 2: /* domain/host */
726
+			return pv_get_strval(msg, param, res, &host);
727
+		case 3: /* port */
728
+			return pv_get_uintval(msg, param, res, port);
729
+		case 4: /* proto */
730
+			if(get_valid_proto_string(msg->via2->proto, 0, 0, &sproto)<0) {
731
+				/* default to udp */
732
+				sproto.s = "udp";
733
+				sproto.len = 3;
734
+				return pv_get_strintval(msg, param, res, &sproto, PROTO_UDP);
735
+			}
736
+			return pv_get_strintval(msg, param, res, &sproto,
737
+					(int)msg->via2->proto);
738
+	}
739
+
740
+	LM_ERR("unknown specifier\n");
741
+	return pv_get_null(msg, param, res);
742
+}
743
+
744
+/**
745
+ *
746
+ */
672 747
 int pv_get_nh(struct sip_msg *msg, pv_param_t *param,
673 748
 		pv_value_t *res)
674 749
 {
... ...
@@ -678,8 +753,10 @@ int pv_get_nh(struct sip_msg *msg, pv_param_t *param,
678 753
 	if(msg==NULL || res==NULL)
679 754
 		return -1;
680 755
 
681
-	if(msg->first_line.type == SIP_REPLY)	/* REPLY doesnt have r/d-uri */
682
-		return pv_get_null(msg, param, res);
756
+	if(msg->first_line.type == SIP_REPLY) {
757
+		/* REPLY doesnt have r/d-uri - use second Via */
758
+		return pv_get_nh_reply(msg, param, res);
759
+	}
683 760
 
684 761
     if (msg->dst_uri.s != NULL && msg->dst_uri.len>0)
685 762
 	{