Browse code

pv: added breaks in case of mismatching via var name

Daniel-Constantin Mierla authored on 10/08/2021 08:10:44
Showing 1 changed files
... ...
@@ -4488,6 +4488,7 @@ int pv_parse_via_name(pv_spec_p sp, str *in)
4488 4488
 			if(in->s[0]=='i')
4489 4489
 				sp->pvp.pvn.u.isname.name.n = 7;
4490 4490
 			else goto error;
4491
+		break;
4491 4492
 		case 4:
4492 4493
 			if(strncmp(in->s, "host", 4)==0)
4493 4494
 				sp->pvp.pvn.u.isname.name.n = 0;
... ...
@@ -4511,6 +4512,7 @@ int pv_parse_via_name(pv_spec_p sp, str *in)
4511 4512
 			if(strncmp(in->s, "protoid", 7)==0)
4512 4513
 				sp->pvp.pvn.u.isname.name.n = 3;
4513 4514
 			else goto error;
4515
+		break;
4514 4516
 		case 8:
4515 4517
 			if(strncmp(in->s, "received", 8)==0)
4516 4518
 				sp->pvp.pvn.u.isname.name.n = 6;
Browse code

pv: added variable $msgbuf(index)

- get/set the character at the position index in the message buffer

Daniel-Constantin Mierla authored on 27/07/2021 13:44:38
Showing 1 changed files
... ...
@@ -4633,3 +4633,115 @@ int pv_get_viaZ(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
4633 4633
 
4634 4634
 	return pv_get_via_attr(msg, vbZ, param, res);
4635 4635
 }
4636
+
4637
+/**
4638
+ *
4639
+ */
4640
+int pv_parse_msgbuf_name(pv_spec_t *sp, str *in)
4641
+{
4642
+	int n;
4643
+	char *p;
4644
+	pv_spec_t *nsp = 0;
4645
+
4646
+	if(in==NULL || in->s==NULL || in->len<=0 || sp==NULL) {
4647
+		return -1;
4648
+	}
4649
+
4650
+	p = in->s;
4651
+	if(*p==PV_MARKER) {
4652
+		nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
4653
+		if(nsp==NULL) {
4654
+			LM_ERR("no more memory\n");
4655
+			return -1;
4656
+		}
4657
+		p = pv_parse_spec(in, nsp);
4658
+		if(p==NULL) {
4659
+			LM_ERR("invalid variable [%.*s]\n", in->len, in->s);
4660
+			pv_spec_free(nsp);
4661
+			return -1;
4662
+		}
4663
+		//LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
4664
+		//pv_print_spec(nsp);
4665
+		sp->pvp.pvn.type = PV_NAME_PVAR;
4666
+		sp->pvp.pvn.u.dname = (void*)nsp;
4667
+		return 0;
4668
+	}
4669
+
4670
+	if (str2sint(in, &n) != 0) {
4671
+		LM_ERR("bad index value: [%.*s]\n", in->len, in->s);
4672
+		return -1;
4673
+	}
4674
+
4675
+	sp->pvp.pvn.u.isname.name.n = n;
4676
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
4677
+	sp->pvp.pvn.u.isname.type = 0;
4678
+
4679
+	return 0;
4680
+}
4681
+
4682
+/**
4683
+ *
4684
+ */
4685
+int pv_get_vparam_ival(sip_msg_t *msg, pv_param_t *param)
4686
+{
4687
+	pv_value_t vval;
4688
+
4689
+	if(param->pvn.type==PV_NAME_PVAR) {
4690
+		/* pvar */
4691
+		if(pv_get_spec_value(msg, (pv_spec_t*)(param->pvn.u.dname), &vval)!=0) {
4692
+			LM_ERR("cannot get name value\n");
4693
+			return -1;
4694
+		}
4695
+		return vval.ri;
4696
+	} else {
4697
+		return param->pvn.u.isname.name.n;
4698
+	}
4699
+}
4700
+
4701
+/**
4702
+ *
4703
+ */
4704
+int pv_get_msgbuf(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
4705
+{
4706
+	int n;
4707
+	static char outmsgbuf[4];
4708
+
4709
+	n = pv_get_vparam_ival(msg, param);
4710
+
4711
+	if(n<0 || n>=msg->len) {
4712
+		LM_ERR("index out of range\n");
4713
+		return pv_get_null(msg, param, res);
4714
+	}
4715
+	outmsgbuf[0] = msg->buf[n];
4716
+	outmsgbuf[1] = '\0';
4717
+	return pv_get_strlval(msg, param, res, outmsgbuf, 2);
4718
+}
4719
+
4720
+/**
4721
+ *
4722
+ */
4723
+int pv_set_msgbuf(sip_msg_t *msg, pv_param_t *param,
4724
+		int op, pv_value_t *val)
4725
+{
4726
+	int n;
4727
+
4728
+	n = pv_get_vparam_ival(msg, param);
4729
+
4730
+	if(n<0 || n>=msg->len) {
4731
+		LM_ERR("index out of range\n");
4732
+		return -1;
4733
+	}
4734
+
4735
+	if((val==NULL) || (val->flags&PV_VAL_NULL)) {
4736
+		LM_ERR("null value - skipping\n");
4737
+		return 1;
4738
+	}
4739
+	if(!(val->flags&PV_VAL_STR) || val->rs.len<=0) {
4740
+		LM_ERR("error - str value required\n");
4741
+		return -1;
4742
+	}
4743
+
4744
+	msg->buf[n] = val->rs.s[0];
4745
+
4746
+	return 0;
4747
+}
Browse code

pv: added $via1(...) - return attributes of 2nd via

Daniel-Constantin Mierla authored on 13/07/2021 07:12:17
Showing 1 changed files
... ...
@@ -4595,6 +4595,19 @@ int pv_get_via0(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
4595 4595
 	return pv_get_via_attr(msg, msg->via1, param, res);
4596 4596
 }
4597 4597
 
4598
+/**
4599
+ *
4600
+ */
4601
+int pv_get_via1(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
4602
+{
4603
+	if (parse_headers(msg, HDR_EOH_F, 0)<0) {
4604
+		LM_DBG("failed to parse sip headers\n");
4605
+		return pv_get_null(msg, param, res);
4606
+	}
4607
+
4608
+	return pv_get_via_attr(msg, msg->via2, param, res);
4609
+}
4610
+
4598 4611
 /**
4599 4612
  *
4600 4613
  */
Browse code

pv: added $viaZ(attr) - get the attributes of last via header

Daniel-Constantin Mierla authored on 03/07/2021 08:54:10
Showing 1 changed files
... ...
@@ -4537,7 +4537,7 @@ int pv_get_via_attr(sip_msg_t *msg, via_body_t *vb, pv_param_t *param,
4537 4537
 		pv_value_t *res)
4538 4538
 {
4539 4539
 	if(vb==NULL) {
4540
-		LM_DBG("invalid via header\n");
4540
+		LM_DBG("null via header\n");
4541 4541
 		return pv_get_null(msg, param, res);
4542 4542
 	}
4543 4543
 
... ...
@@ -4594,3 +4594,29 @@ int pv_get_via0(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
4594 4594
 
4595 4595
 	return pv_get_via_attr(msg, msg->via1, param, res);
4596 4596
 }
4597
+
4598
+/**
4599
+ *
4600
+ */
4601
+int pv_get_viaZ(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
4602
+{
4603
+	hdr_field_t *hf = NULL;
4604
+	via_body_t *vb = NULL;
4605
+	via_body_t *vbZ = NULL;
4606
+
4607
+	if (parse_headers(msg, HDR_EOH_F, 0)<0) {
4608
+		LM_DBG("failed to parse sip headers\n");
4609
+		return pv_get_null(msg, param, res);
4610
+	}
4611
+
4612
+	vbZ = msg->via1;
4613
+	for(hf=msg->h_via1; hf!=NULL; hf=hf->next) {
4614
+		if(hf->type==HDR_VIA_T) {
4615
+			for(vb=(via_body_t*)hf->parsed; vb!=NULL; vb=vb->next) {
4616
+				vbZ = vb;
4617
+			}
4618
+		}
4619
+	}
4620
+
4621
+	return pv_get_via_attr(msg, vbZ, param, res);
4622
+}
Browse code

vp: new variable $via0(attr)

- get the attributes of first Via

Daniel-Constantin Mierla authored on 02/07/2021 14:18:55
Showing 1 changed files
... ...
@@ -4473,3 +4473,124 @@ int pv_set_ccp_attrs(struct sip_msg* msg, pv_param_t *param,
4473 4473
 	}
4474 4474
 	return 0;
4475 4475
 }
4476
+
4477
+/**
4478
+ *
4479
+ */
4480
+int pv_parse_via_name(pv_spec_p sp, str *in)
4481
+{
4482
+	if(sp==NULL || in==NULL || in->len<=0)
4483
+		return -1;
4484
+
4485
+	/* attributes not related to dst of reply get an id starting with 20 */
4486
+	switch(in->len) {
4487
+		case 1:
4488
+			if(in->s[0]=='i')
4489
+				sp->pvp.pvn.u.isname.name.n = 7;
4490
+			else goto error;
4491
+		case 4:
4492
+			if(strncmp(in->s, "host", 4)==0)
4493
+				sp->pvp.pvn.u.isname.name.n = 0;
4494
+			else if(strncmp(in->s, "port", 4)==0)
4495
+				sp->pvp.pvn.u.isname.name.n = 1;
4496
+			else goto error;
4497
+		break;
4498
+		case 5:
4499
+			if(strncmp(in->s, "proto", 5)==0)
4500
+				sp->pvp.pvn.u.isname.name.n = 2;
4501
+			else if(strncmp(in->s, "rport", 5)==0)
4502
+				sp->pvp.pvn.u.isname.name.n = 5;
4503
+			else goto error;
4504
+		break;
4505
+		case 6:
4506
+			if(strncmp(in->s, "branch", 6)==0)
4507
+				sp->pvp.pvn.u.isname.name.n = 4;
4508
+			else goto error;
4509
+		break;
4510
+		case 7:
4511
+			if(strncmp(in->s, "protoid", 7)==0)
4512
+				sp->pvp.pvn.u.isname.name.n = 3;
4513
+			else goto error;
4514
+		case 8:
4515
+			if(strncmp(in->s, "received", 8)==0)
4516
+				sp->pvp.pvn.u.isname.name.n = 6;
4517
+			else goto error;
4518
+		break;
4519
+
4520
+		default:
4521
+			goto error;
4522
+	}
4523
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
4524
+	sp->pvp.pvn.u.isname.type = 0;
4525
+
4526
+	return 0;
4527
+
4528
+error:
4529
+	LM_ERR("unknown PV rpl key: %.*s\n", in->len, in->s);
4530
+	return -1;
4531
+}
4532
+
4533
+/**
4534
+ *
4535
+ */
4536
+int pv_get_via_attr(sip_msg_t *msg, via_body_t *vb, pv_param_t *param,
4537
+		pv_value_t *res)
4538
+{
4539
+	if(vb==NULL) {
4540
+		LM_DBG("invalid via header\n");
4541
+		return pv_get_null(msg, param, res);
4542
+	}
4543
+
4544
+	switch(param->pvn.u.isname.name.n) {
4545
+		case 0: /* host */
4546
+			if(vb->host.s!=NULL && vb->host.len>0) {
4547
+				return pv_get_strval(msg, param, res, &vb->host);
4548
+			}
4549
+			break;
4550
+		case 1: /* port */
4551
+			return pv_get_uintval(msg, param, res, (vb->port)?vb->port:SIP_PORT);
4552
+		case 2: /* proto */
4553
+			return pv_get_strval(msg, param, res, &vb->transport);
4554
+		case 3: /* protoid */
4555
+			return pv_get_sintval(msg, param, res, (int)vb->proto);
4556
+		case 4: /* branch */
4557
+			if(vb->branch!=NULL && vb->branch->value.len>0) {
4558
+				return pv_get_strval(msg, param, res, &vb->branch->value);
4559
+			}
4560
+			break;
4561
+		case 5: /* rport */
4562
+			if(vb->rport!=NULL && vb->rport->value.len>0) {
4563
+				return pv_get_strval(msg, param, res, &vb->rport->value);
4564
+			}
4565
+			break;
4566
+		case 6: /* received */
4567
+			if(vb->received!=NULL && vb->received->value.len>0) {
4568
+				return pv_get_strval(msg, param, res, &vb->received->value);
4569
+			}
4570
+			break;
4571
+		case 7: /* i */
4572
+			if(vb->i!=NULL && vb->i->value.len>0) {
4573
+				return pv_get_strval(msg, param, res, &vb->i->value);
4574
+			}
4575
+			break;
4576
+
4577
+		default:
4578
+			return pv_get_null(msg, param, res);
4579
+	}
4580
+
4581
+	return pv_get_null(msg, param, res);
4582
+}
4583
+
4584
+
4585
+/**
4586
+ *
4587
+ */
4588
+int pv_get_via0(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
4589
+{
4590
+	if (parse_headers(msg, HDR_EOH_F, 0)<0) {
4591
+		LM_DBG("failed to parse sip headers\n");
4592
+		return pv_get_null(msg, param, res);
4593
+	}
4594
+
4595
+	return pv_get_via_attr(msg, msg->via1, param, res);
4596
+}
Browse code

pv: support for Contact header in $hflc()

Daniel-Constantin Mierla authored on 11/06/2021 07:17:36
Showing 1 changed files
... ...
@@ -2429,6 +2429,7 @@ int pv_get_hflc(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2429 2429
 	pv_value_t tv = {0};
2430 2430
 	via_body_t *vb = NULL;
2431 2431
 	rr_t *rrb = NULL;
2432
+	contact_t *cb = NULL;
2432 2433
 	hdr_field_t *hf = NULL;
2433 2434
 	int n = 0;
2434 2435
 
... ...
@@ -2499,6 +2500,28 @@ int pv_get_hflc(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2499 2500
 		return pv_get_sintval(msg, param, res, n);
2500 2501
 	}
2501 2502
 
2503
+	if((tv.flags == 0) && (tv.ri==HDR_CONTACT_T)) {
2504
+		if(msg->contact==NULL) {
2505
+			LM_DBG("no Contact header\n");
2506
+			return pv_get_sintval(msg, param, res, 0);
2507
+		}
2508
+		if(parse_contact_headers(msg) < 0) {
2509
+			LM_DBG("failed to parse Contact headers\n");
2510
+			return pv_get_sintval(msg, param, res, 0);
2511
+		}
2512
+
2513
+		/* count Contact header bodies */
2514
+		for(hf=msg->contact; hf!=NULL; hf=hf->next) {
2515
+			if(hf->type==HDR_CONTACT_T) {
2516
+				for(cb=(((contact_body_t*)hf->parsed)->contacts);
2517
+						cb!=NULL; cb=cb->next) {
2518
+					n++;
2519
+				}
2520
+			}
2521
+		}
2522
+		return pv_get_sintval(msg, param, res, n);
2523
+	}
2524
+
2502 2525
 	for (hf=msg->headers; hf; hf=hf->next) {
2503 2526
 		if(tv.flags == 0) {
2504 2527
 			if (tv.ri==hf->type) {
Browse code

pv: support Record/-Route headers for $hflc(...)

Daniel-Constantin Mierla authored on 09/06/2021 11:33:06
Showing 1 changed files
... ...
@@ -2428,6 +2428,7 @@ int pv_get_hflc(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2428 2428
 {
2429 2429
 	pv_value_t tv = {0};
2430 2430
 	via_body_t *vb = NULL;
2431
+	rr_t *rrb = NULL;
2431 2432
 	hdr_field_t *hf = NULL;
2432 2433
 	int n = 0;
2433 2434
 
... ...
@@ -2471,6 +2472,33 @@ int pv_get_hflc(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2471 2472
 		return pv_get_sintval(msg, param, res, n);
2472 2473
 	}
2473 2474
 
2475
+	if((tv.flags == 0) && (tv.ri==HDR_RECORDROUTE_T || tv.ri==HDR_ROUTE_T)) {
2476
+		if(tv.ri==HDR_RECORDROUTE_T) {
2477
+			hf=msg->record_route;
2478
+		} else {
2479
+			hf=msg->route;
2480
+		}
2481
+		if(hf==NULL) {
2482
+			LM_DBG("no %s header\n", (tv.ri==HDR_ROUTE_T)?"route":"record-route");
2483
+			return pv_get_sintval(msg, param, res, 0);
2484
+		}
2485
+
2486
+		/* count Record-Route/Route header bodies */
2487
+		for(; hf!=NULL; hf=hf->next) {
2488
+			if(hf->type==tv.ri) {
2489
+				if(parse_rr(hf) == -1) {
2490
+					LM_ERR("failed parsing %s header\n",
2491
+							(tv.ri==HDR_ROUTE_T)?"route":"record-route");
2492
+					return pv_get_sintval(msg, param, res, 0);
2493
+				}
2494
+				for(rrb=(rr_t*)hf->parsed; rrb!=NULL; rrb=rrb->next) {
2495
+					n++;
2496
+				}
2497
+			}
2498
+		}
2499
+		return pv_get_sintval(msg, param, res, n);
2500
+	}
2501
+
2474 2502
 	for (hf=msg->headers; hf; hf=hf->next) {
2475 2503
 		if(tv.flags == 0) {
2476 2504
 			if (tv.ri==hf->type) {
Browse code

pv: support INET/6 as alternative IPv4/6 for $K(key)

- these are the keywords in the config

Daniel-Constantin Mierla authored on 09/06/2021 10:27:57
Showing 1 changed files
... ...
@@ -3632,6 +3632,7 @@ int pv_parse_K_name(pv_spec_p sp, str *in)
3632 3632
 			if(strncmp(in->s, "WS", 2)==0)
3633 3633
 				sp->pvp.pvn.u.isname.name.n = 6;
3634 3634
 			else goto error;
3635
+		break;
3635 3636
 		case 3:
3636 3637
 			if(strncmp(in->s, "UDP", 3)==0)
3637 3638
 				sp->pvp.pvn.u.isname.name.n = 2;
... ...
@@ -3646,12 +3647,19 @@ int pv_parse_K_name(pv_spec_p sp, str *in)
3646 3647
 		case 4:
3647 3648
 			if(strncmp(in->s, "IPv4", 4)==0)
3648 3649
 				sp->pvp.pvn.u.isname.name.n = 0;
3650
+			else if(strncmp(in->s, "INET", 4)==0)
3651
+				sp->pvp.pvn.u.isname.name.n = 0;
3649 3652
 			else if(strncmp(in->s, "IPv6", 4)==0)
3650 3653
 				sp->pvp.pvn.u.isname.name.n = 1;
3651 3654
 			else if(strncmp(in->s, "SCTP", 4)==0)
3652 3655
 				sp->pvp.pvn.u.isname.name.n = 5;
3653 3656
 			else goto error;
3654 3657
 		break;
3658
+		case 5:
3659
+			if(strncmp(in->s, "INET6", 5)==0)
3660
+				sp->pvp.pvn.u.isname.name.n = 1;
3661
+			else goto error;
3662
+		break;
3655 3663
 		default:
3656 3664
 			goto error;
3657 3665
 	}
Browse code

pv: added missing WS and WSS to $K(key) variable

Daniel-Constantin Mierla authored on 09/06/2021 10:15:38
Showing 1 changed files
... ...
@@ -3628,6 +3628,10 @@ int pv_parse_K_name(pv_spec_p sp, str *in)
3628 3628
 
3629 3629
 	switch(in->len)
3630 3630
 	{
3631
+		case 2:
3632
+			if(strncmp(in->s, "WS", 2)==0)
3633
+				sp->pvp.pvn.u.isname.name.n = 6;
3634
+			else goto error;
3631 3635
 		case 3:
3632 3636
 			if(strncmp(in->s, "UDP", 3)==0)
3633 3637
 				sp->pvp.pvn.u.isname.name.n = 2;
... ...
@@ -3635,6 +3639,8 @@ int pv_parse_K_name(pv_spec_p sp, str *in)
3635 3639
 				sp->pvp.pvn.u.isname.name.n = 3;
3636 3640
 			else if(strncmp(in->s, "TLS", 3)==0)
3637 3641
 				sp->pvp.pvn.u.isname.name.n = 4;
3642
+			else if(strncmp(in->s, "WSS", 3)==0)
3643
+				sp->pvp.pvn.u.isname.name.n = 7;
3638 3644
 			else goto error;
3639 3645
 		break;
3640 3646
 		case 4:
... ...
@@ -3706,6 +3712,10 @@ int pv_get_K(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
3706 3712
 			return pv_get_uintval(msg, param, res, PROTO_TLS);
3707 3713
 		case 5:
3708 3714
 			return pv_get_uintval(msg, param, res, PROTO_SCTP);
3715
+		case 6:
3716
+			return pv_get_uintval(msg, param, res, PROTO_WS);
3717
+		case 7:
3718
+			return pv_get_uintval(msg, param, res, PROTO_WSS);
3709 3719
 		default:
3710 3720
 			return pv_get_uintval(msg, param, res, AF_INET);
3711 3721
 	}
Browse code

pv: new variable $hflc(hname)

- return the number of bodies for known headers that can also be as a comma
separated list
- supported now is Via header

Daniel-Constantin Mierla authored on 08/06/2021 11:25:54
Showing 1 changed files
... ...
@@ -2421,6 +2421,70 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2421 2421
 	return pv_get_hdr_helper(msg, param, res, &tv, idx, idxf);
2422 2422
 }
2423 2423
 
2424
+/**
2425
+ *
2426
+ */
2427
+int pv_get_hflc(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2428
+{
2429
+	pv_value_t tv = {0};
2430
+	via_body_t *vb = NULL;
2431
+	hdr_field_t *hf = NULL;
2432
+	int n = 0;
2433
+
2434
+	if(msg==NULL || res==NULL || param==NULL)
2435
+		return -1;
2436
+
2437
+	/* get the name */
2438
+	if(param->pvn.type == PV_NAME_PVAR) {
2439
+		if(pv_get_spec_name(msg, param, &tv)!=0 || (!(tv.flags&PV_VAL_STR))) {
2440
+			LM_ERR("invalid name\n");
2441
+			return pv_get_sintval(msg, param, res, 0);
2442
+		}
2443
+	} else {
2444
+		if(param->pvn.u.isname.type == AVP_NAME_STR) {
2445
+			tv.flags = PV_VAL_STR;
2446
+			tv.rs = param->pvn.u.isname.name.s;
2447
+		} else {
2448
+			tv.flags = 0;
2449
+			tv.ri = param->pvn.u.isname.name.n;
2450
+		}
2451
+	}
2452
+
2453
+	if (parse_headers(msg, HDR_EOH_F, 0)<0) {
2454
+		LM_DBG("failed to parse sip headers\n");
2455
+		return pv_get_sintval(msg, param, res, 0);
2456
+	}
2457
+
2458
+	if((tv.flags == 0) && (tv.ri==HDR_VIA_T)) {
2459
+		if(msg->h_via1==NULL) {
2460
+			LM_WARN("no Via header\n");
2461
+			return pv_get_sintval(msg, param, res, 0);
2462
+		}
2463
+		/* count Via header bodies */
2464
+		for(hf=msg->h_via1; hf!=NULL; hf=hf->next) {
2465
+			if(hf->type==HDR_VIA_T) {
2466
+				for(vb=(via_body_t*)hf->parsed; vb!=NULL; vb=vb->next) {
2467
+					n++;
2468
+				}
2469
+			}
2470
+		}
2471
+		return pv_get_sintval(msg, param, res, n);
2472
+	}
2473
+
2474
+	for (hf=msg->headers; hf; hf=hf->next) {
2475
+		if(tv.flags == 0) {
2476
+			if (tv.ri==hf->type) {
2477
+				n++;
2478
+			}
2479
+		} else {
2480
+			if (cmp_hdrname_str(&hf->name, &tv.rs)==0) {
2481
+				n++;
2482
+			}
2483
+		}
2484
+	}
2485
+	return pv_get_sintval(msg, param, res, n);
2486
+}
2487
+
2424 2488
 /**
2425 2489
  *
2426 2490
  */
Browse code

pv: pv_get_method fixed error "pv_get_method(): no CSEQ header"

GH #2761: Error obeserver when sent HTTP reply like

HTTP/1.1 200 OK
Sia: SIP/2.0/TCP 8.8.8.8:39813
Content-Type: application/json
Server: kamailio
Content-Length: 49

{"data":{"status-code":200,"reason-phrase":"OK"}}

Sergey Safarov authored on 03/06/2021 18:03:32 • Daniel-Constantin Mierla committed on 04/06/2021 14:22:49
Showing 1 changed files
... ...
@@ -147,6 +147,9 @@ int pv_get_method(struct sip_msg *msg, pv_param_t *param,
147 147
 				(int)msg->first_line.u.request.method_value);
148 148
 	}
149 149
 
150
+	if (IS_HTTP_REPLY(msg))
151
+		return pv_get_null(msg, param, res);
152
+
150 153
 	if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1) ||
151 154
 				(msg->cseq==NULL)))
152 155
 	{
Browse code

pv: test for HDR_ERROR_T after header name parsing

Daniel-Constantin Mierla authored on 03/06/2021 13:29:50
Showing 1 changed files
... ...
@@ -3501,8 +3501,8 @@ int pv_parse_hdr_name(pv_spec_p sp, str *in)
3501 3501
 	s.s = p;
3502 3502
 	s.len = in->len+1;
3503 3503
 
3504
-	if (parse_hname2_short(s.s, s.s + s.len, &hdr)==0)
3505
-	{
3504
+	parse_hname2_short(s.s, s.s + s.len, &hdr);
3505
+	if(hdr.type==HDR_ERROR_T) {
3506 3506
 		LM_ERR("error parsing header name [%.*s]\n", s.len, s.s);
3507 3507
 		goto error;
3508 3508
 	}
Browse code

pv: support Contact header in $hfl(...)

Daniel-Constantin Mierla authored on 03/06/2021 09:11:50
Showing 1 changed files
... ...
@@ -2191,6 +2191,7 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2191 2191
 	pv_value_t tv = {0};
2192 2192
 	via_body_t *vb = NULL;
2193 2193
 	rr_t *rrb = NULL;
2194
+	contact_t *cb = NULL;
2194 2195
 	hdr_field_t *hf = NULL;
2195 2196
 	int n = 0;
2196 2197
 	str sval = STR_NULL;
... ...
@@ -2358,6 +2359,62 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2358 2359
 		return pv_get_null(msg, param, res);
2359 2360
 	}
2360 2361
 
2362
+	if((tv.flags == 0) && (tv.ri==HDR_CONTACT_T)) {
2363
+		if(msg->contact==NULL) {
2364
+			LM_DBG("no Contact header\n");
2365
+			return pv_get_null(msg, param, res);
2366
+		}
2367
+		if(parse_contact_headers(msg) < 0) {
2368
+			LM_DBG("failed to parse Contact headers\n");
2369
+			return pv_get_null(msg, param, res);
2370
+		}
2371
+		if(idx<0) {
2372
+			n = 1;
2373
+			/* count Contact header bodies */
2374
+			for(hf=msg->contact; hf!=NULL; hf=hf->next) {
2375
+				if(hf->type==HDR_CONTACT_T) {
2376
+					for(cb=(((contact_body_t*)hf->parsed)->contacts);
2377
+							cb!=NULL; cb=cb->next) {
2378
+						n++;
2379
+					}
2380
+				}
2381
+			}
2382
+
2383
+			idx = -idx;
2384
+			if(idx>n) {
2385
+				LM_DBG("index out of range\n");
2386
+				return pv_get_null(msg, param, res);
2387
+			}
2388
+			idx = n - idx;
2389
+		}
2390
+		if(idx==0) {
2391
+			cb = ((contact_body_t*)msg->contact->parsed)->contacts;
2392
+			sval.s = cb->name.s;
2393
+			sval.len = cb->len;
2394
+			trim(&sval);
2395
+			res->rs = sval;
2396
+			return 0;
2397
+		}
2398
+		n=0;
2399
+		for(hf=msg->contact; hf!=NULL; hf=hf->next) {
2400
+			if(hf->type==HDR_CONTACT_T) {
2401
+				for(cb=(((contact_body_t*)hf->parsed)->contacts);
2402
+						cb!=NULL; cb=cb->next) {
2403
+					if(n==idx) {
2404
+						sval.s = cb->name.s;
2405
+						sval.len = cb->len;
2406
+						trim(&sval);
2407
+						res->rs = sval;
2408
+						return 0;
2409
+					}
2410
+					n++;
2411
+				}
2412
+			}
2413
+		}
2414
+		LM_DBG("unexpected contact index out of range\n");
2415
+		return pv_get_null(msg, param, res);
2416
+	}
2417
+
2361 2418
 	return pv_get_hdr_helper(msg, param, res, &tv, idx, idxf);
2362 2419
 }
2363 2420
 
Browse code

pv: suport also Route headers in $hfl(...)

Daniel-Constantin Mierla authored on 02/06/2021 14:57:05
Showing 1 changed files
... ...
@@ -2227,6 +2227,10 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2227 2227
 	}
2228 2228
 
2229 2229
 	if((tv.flags == 0) && (tv.ri==HDR_VIA_T)) {
2230
+		if(msg->h_via1==NULL) {
2231
+			LM_WARN("no Via header\n");
2232
+			return pv_get_null(msg, param, res);
2233
+		}
2230 2234
 		if(idx<0) {
2231 2235
 			n = 1;
2232 2236
 			/* count Via header bodies */
... ...
@@ -2271,17 +2275,28 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2271 2275
 		LM_DBG("unexpected via index out of range\n");
2272 2276
 		return pv_get_null(msg, param, res);
2273 2277
 	}
2274
-	if((tv.flags == 0) && (tv.ri==HDR_RECORDROUTE_T)) {
2278
+	if((tv.flags == 0) && (tv.ri==HDR_RECORDROUTE_T || tv.ri==HDR_ROUTE_T)) {
2279
+		if(tv.ri==HDR_RECORDROUTE_T) {
2280
+			hf=msg->record_route;
2281
+		} else {
2282
+			hf=msg->route;
2283
+		}
2284
+		if(hf==NULL) {
2285
+			LM_DBG("no %s header\n", (tv.ri==HDR_ROUTE_T)?"route":"record-route");
2286
+			return pv_get_null(msg, param, res);
2287
+		}
2288
+
2275 2289
 		if(idx<0) {
2276 2290
 			n = 1;
2277
-			/* count Record-Route header bodies */
2278
-			for(hf=msg->record_route; hf!=NULL; hf=hf->next) {
2279
-				if(hf->type==HDR_RECORDROUTE_T) {
2291
+			/* count Record-Route/Route header bodies */
2292
+			for(; hf!=NULL; hf=hf->next) {
2293
+				if(hf->type==tv.ri) {
2280 2294
 					if(parse_rr(hf) == -1) {
2281
-						LM_ERR("failed parsing rr header\n");
2295
+						LM_ERR("failed parsing %s header\n",
2296
+								(tv.ri==HDR_ROUTE_T)?"route":"record-route");
2282 2297
 						return pv_get_null(msg, param, res);
2283 2298
 					}
2284
-					for(rrb=(rr_t*)hf->parsed; vb!=NULL; rrb=rrb->next) {
2299
+					for(rrb=(rr_t*)hf->parsed; rrb!=NULL; rrb=rrb->next) {
2285 2300
 						n++;
2286 2301
 					}
2287 2302
 				}
... ...
@@ -2289,17 +2304,24 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2289 2304
 
2290 2305
 			idx = -idx;
2291 2306
 			if(idx>n) {
2292
-				LM_DBG("index out of rr headers range\n");
2307
+				LM_DBG("index out of %s headers range\n",
2308
+						(tv.ri==HDR_ROUTE_T)?"route":"record-route");
2293 2309
 				return pv_get_null(msg, param, res);
2294 2310
 			}
2295 2311
 			idx = n - idx;
2296 2312
 		}
2297 2313
 		if(idx==0) {
2298
-			if(parse_rr(msg->record_route) == -1) {
2299
-				LM_ERR("failed parsing rr header\n");
2314
+			if(tv.ri==HDR_RECORDROUTE_T) {
2315
+				hf=msg->record_route;
2316
+			} else {
2317
+				hf=msg->route;
2318
+			}
2319
+			if(parse_rr(hf) == -1) {
2320
+				LM_ERR("failed parsing %s header\n",
2321
+						(tv.ri==HDR_ROUTE_T)?"route":"record-route");
2300 2322
 				return pv_get_null(msg, param, res);
2301 2323
 			}
2302
-			rrb = (rr_t*)(msg->record_route->parsed);
2324
+			rrb = (rr_t*)(hf->parsed);
2303 2325
 			sval.s = rrb->nameaddr.name.s;
2304 2326
 			sval.len = rrb->len;
2305 2327
 			trim(&sval);
... ...
@@ -2307,13 +2329,19 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2307 2329
 			return 0;
2308 2330
 		}
2309 2331
 		n=0;
2310
-		for(hf=msg->record_route; hf!=NULL; hf=hf->next) {
2311
-			if(hf->type==HDR_RECORDROUTE_T) {
2332
+		if(tv.ri==HDR_RECORDROUTE_T) {
2333
+			hf=msg->record_route;
2334
+		} else {
2335
+			hf=msg->route;
2336
+		}
2337
+		for(; hf!=NULL; hf=hf->next) {
2338
+			if(hf->type==tv.ri) {
2312 2339
 				if(parse_rr(hf) == -1) {
2313
-					LM_ERR("failed parsing rr header\n");
2340
+					LM_ERR("failed parsing %s header\n",
2341
+							(tv.ri==HDR_ROUTE_T)?"route":"record-route");
2314 2342
 					return pv_get_null(msg, param, res);
2315 2343
 				}
2316
-				for(rrb=(rr_t*)hf->parsed; vb!=NULL; rrb=rrb->next) {
2344
+				for(rrb=(rr_t*)hf->parsed; rrb!=NULL; rrb=rrb->next) {
2317 2345
 					if(n==idx) {
2318 2346
 						sval.s = rrb->nameaddr.name.s;
2319 2347
 						sval.len = rrb->len;
... ...
@@ -2325,7 +2353,8 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2325 2353
 				}
2326 2354
 			}
2327 2355
 		}
2328
-		LM_DBG("unexpected record-route index out of range\n");
2356
+		LM_DBG("unexpected %s index out of range\n",
2357
+				(tv.ri==HDR_ROUTE_T)?"route":"record-route");
2329 2358
 		return pv_get_null(msg, param, res);
2330 2359
 	}
2331 2360
 
Browse code

pv: support for Record-Route in $hfl(...)

Daniel-Constantin Mierla authored on 02/06/2021 10:23:40
Showing 1 changed files
... ...
@@ -2190,6 +2190,7 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2190 2190
 	int idxf = 0;
2191 2191
 	pv_value_t tv = {0};
2192 2192
 	via_body_t *vb = NULL;
2193
+	rr_t *rrb = NULL;
2193 2194
 	hdr_field_t *hf = NULL;
2194 2195
 	int n = 0;
2195 2196
 	str sval = STR_NULL;
... ...
@@ -2228,7 +2229,7 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2228 2229
 	if((tv.flags == 0) && (tv.ri==HDR_VIA_T)) {
2229 2230
 		if(idx<0) {
2230 2231
 			n = 1;
2231
-			/* count Vua header bodies */
2232
+			/* count Via header bodies */
2232 2233
 			for(hf=msg->h_via1; hf!=NULL; hf=hf->next) {
2233 2234
 				if(hf->type==HDR_VIA_T) {
2234 2235
 					for(vb=(via_body_t*)hf->parsed; vb!=NULL; vb=vb->next) {
... ...
@@ -2270,6 +2271,64 @@ int pv_get_hfl(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2270 2271
 		LM_DBG("unexpected via index out of range\n");
2271 2272
 		return pv_get_null(msg, param, res);
2272 2273
 	}
2274
+	if((tv.flags == 0) && (tv.ri==HDR_RECORDROUTE_T)) {
2275
+		if(idx<0) {
2276
+			n = 1;
2277
+			/* count Record-Route header bodies */
2278
+			for(hf=msg->record_route; hf!=NULL; hf=hf->next) {
2279
+				if(hf->type==HDR_RECORDROUTE_T) {
2280
+					if(parse_rr(hf) == -1) {
2281
+						LM_ERR("failed parsing rr header\n");
2282
+						return pv_get_null(msg, param, res);
2283
+					}
2284
+					for(rrb=(rr_t*)hf->parsed; vb!=NULL; rrb=rrb->next) {
2285
+						n++;
2286
+					}
2287
+				}
2288
+			}
2289
+
2290
+			idx = -idx;
2291
+			if(idx>n) {
2292
+				LM_DBG("index out of rr headers range\n");
2293
+				return pv_get_null(msg, param, res);
2294
+			}
2295
+			idx = n - idx;
2296
+		}
2297
+		if(idx==0) {
2298
+			if(parse_rr(msg->record_route) == -1) {
2299
+				LM_ERR("failed parsing rr header\n");
2300
+				return pv_get_null(msg, param, res);
2301
+			}
2302
+			rrb = (rr_t*)(msg->record_route->parsed);
2303
+			sval.s = rrb->nameaddr.name.s;
2304
+			sval.len = rrb->len;
2305
+			trim(&sval);
2306
+			res->rs = sval;
2307
+			return 0;
2308
+		}
2309
+		n=0;
2310
+		for(hf=msg->record_route; hf!=NULL; hf=hf->next) {
2311
+			if(hf->type==HDR_RECORDROUTE_T) {
2312
+				if(parse_rr(hf) == -1) {
2313
+					LM_ERR("failed parsing rr header\n");
2314
+					return pv_get_null(msg, param, res);
2315
+				}
2316
+				for(rrb=(rr_t*)hf->parsed; vb!=NULL; rrb=rrb->next) {
2317
+					if(n==idx) {
2318
+						sval.s = rrb->nameaddr.name.s;
2319
+						sval.len = rrb->len;
2320
+						trim(&sval);
2321
+						res->rs = sval;
2322
+						return 0;
2323
+					}
2324
+					n++;
2325
+				}
2326
+			}
2327
+		}
2328
+		LM_DBG("unexpected record-route index out of range\n");
2329
+		return pv_get_null(msg, param, res);
2330
+	}
2331
+
2273 2332
 	return pv_get_hdr_helper(msg, param, res, &tv, idx, idxf);
2274 2333
 }
2275 2334
 
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 1 changed files
... ...
@@ -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();