Browse code

rtpengine: add play_media() and stop_media()

Also includes addition of the media_duration pvar, as well as several
code cleanups and simplifications.

Richard Fuchs authored on 08/03/2019 21:05:44
Showing 2 changed files
... ...
@@ -135,6 +135,8 @@ static const char *command_strings[] = {
135 135
 	[OP_UNBLOCK_MEDIA]	= "unblock media",
136 136
 	[OP_START_FORWARDING]	= "start forwarding",
137 137
 	[OP_STOP_FORWARDING]	= "stop forwarding",
138
+	[OP_PLAY_MEDIA]		= "play media",
139
+	[OP_STOP_MEDIA]		= "stop media",
138 140
 };
139 141
 
140 142
 struct minmax_mos_stats {
... ...
@@ -192,6 +194,8 @@ static int block_media_f(struct sip_msg *, char *, char *);
192 194
 static int unblock_media_f(struct sip_msg *, char *, char *);
193 195
 static int start_forwarding_f(struct sip_msg *, char *, char *);
194 196
 static int stop_forwarding_f(struct sip_msg *, char *, char *);
197
+static int play_media_f(struct sip_msg *, char *, char *);
198
+static int stop_media_f(struct sip_msg *, char *, char *);
195 199
 static int rtpengine_answer1_f(struct sip_msg *, char *, char *);
196 200
 static int rtpengine_offer1_f(struct sip_msg *, char *, char *);
197 201
 static int rtpengine_delete1_f(struct sip_msg *, char *, char *);
... ...
@@ -276,6 +280,9 @@ static pv_spec_t *write_sdp_pvar = NULL;
276 280
 static str read_sdp_pvar_str = {NULL, 0};
277 281
 static pv_spec_t *read_sdp_pvar = NULL;
278 282
 
283
+static str media_duration_pvar_str = {NULL, 0};
284
+static pv_spec_t *media_duration_pvar = NULL;
285
+
279 286
 #define RTPENGINE_SESS_LIMIT_MSG "Parallel session limit reached"
280 287
 #define RTPENGINE_SESS_LIMIT_MSG_LEN (sizeof(RTPENGINE_SESS_LIMIT_MSG)-1)
281 288
 
... ...
@@ -354,6 +361,15 @@ static cmd_export_t cmds[] = {
354 361
 	{"stop_forwarding",	(cmd_function)stop_forwarding_f,	1,
355 362
 		fixup_spve_null, 0,
356 363
 		ANY_ROUTE},
364
+	{"play_media",		(cmd_function)play_media_f, 		1,
365
+		fixup_spve_null, 0,
366
+		ANY_ROUTE},
367
+	{"stop_media",		(cmd_function)stop_media_f, 		1,
368
+		fixup_spve_null, 0,
369
+		ANY_ROUTE},
370
+	{"stop_media",		(cmd_function)stop_media_f, 		0,
371
+		0, 0,
372
+		ANY_ROUTE},
357 373
 	{"rtpengine_offer",	(cmd_function)rtpengine_offer1_f,	0,
358 374
 		0, 0,
359 375
 		ANY_ROUTE},
... ...
@@ -424,6 +440,7 @@ static param_export_t params[] = {
424 440
 	{"hash_table_tout",       INT_PARAM, &hash_table_tout        },
425 441
 	{"hash_table_size",       INT_PARAM, &hash_table_size        },
426 442
 	{"setid_default",         INT_PARAM, &setid_default          },
443
+	{"media_duration",        PARAM_STR, &media_duration_pvar_str},
427 444
 
428 445
 	/* MOS stats output */
429 446
 	/* global averages */
... ...
@@ -1656,6 +1673,16 @@ mod_init(void)
1656 1673
 		}
1657 1674
 	}
1658 1675
 
1676
+	if (media_duration_pvar_str.len > 0) {
1677
+		media_duration_pvar = pv_cache_get(&media_duration_pvar_str);
1678
+		if (media_duration_pvar == NULL
1679
+			|| (media_duration_pvar->type != PVT_AVP && media_duration_pvar->type != PVT_SCRIPTVAR) ) {
1680
+			LM_ERR("media_duration_pv: not a valid AVP or VAR definition <%.*s>\n",
1681
+				media_duration_pvar_str.len, media_duration_pvar_str.s);
1682
+			return -1;
1683
+		}
1684
+	}
1685
+
1659 1686
 	if (rtpp_strings)
1660 1687
 		pkg_free(rtpp_strings);
1661 1688
 
... ...
@@ -2454,7 +2481,8 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_
2454 2481
 	}
2455 2482
 	else if ((msg->first_line.type == SIP_REQUEST && op != OP_ANSWER)
2456 2483
 		|| (msg->first_line.type == SIP_REPLY && op == OP_DELETE)
2457
-		|| (msg->first_line.type == SIP_REPLY && op == OP_ANSWER))
2484
+		|| (msg->first_line.type == SIP_REPLY && op == OP_ANSWER)
2485
+		|| ng_flags.directional) /* set if from-tag was set manually */
2458 2486
 	{
2459 2487
 		bencode_dictionary_add_str(ng_flags.dict, "from-tag", &ng_flags.from_tag);
2460 2488
 		if (ng_flags.to && ng_flags.to_tag.s && ng_flags.to_tag.len)
... ...
@@ -2622,14 +2650,27 @@ error:
2622 2650
 static int rtpp_function_call_simple(struct sip_msg *msg, enum rtpe_operation op, const char *flags_str)
2623 2651
 {
2624 2652
 	bencode_buffer_t bencbuf;
2653
+	bencode_item_t *ret;
2625 2654
 
2626
-	if (!rtpp_function_call(&bencbuf, msg, op, flags_str, NULL))
2655
+	ret = rtpp_function_call(&bencbuf, msg, op, flags_str, NULL);
2656
+	if (!ret)
2627 2657
 		return -1;
2628 2658
 
2659
+	if (bencode_dictionary_get_strcmp(ret, "result", "ok")) {
2660
+		LM_ERR("proxy didn't return \"ok\" result\n");
2661
+		bencode_buffer_free(&bencbuf);
2662
+		return -1;
2663
+	}
2664
+
2629 2665
 	bencode_buffer_free(&bencbuf);
2630 2666
 	return 1;
2631 2667
 }
2632 2668
 
2669
+static int rtpengine_simple_wrap(struct sip_msg *msg, void *d, int more, enum rtpe_operation op) {
2670
+	return rtpp_function_call_simple(msg, op, d);
2671
+}
2672
+
2673
+
2633 2674
 static bencode_item_t *rtpp_function_call_ok(bencode_buffer_t *bencbuf, struct sip_msg *msg,
2634 2675
 		enum rtpe_operation op, const char *flags_str, str *body)
2635 2676
 {
... ...
@@ -3334,8 +3375,9 @@ static int rtpengine_query(struct sip_msg *msg, const char *flags) {
3334 3375
 	return 1;
3335 3376
 }
3336 3377
 
3337
-static int rtpengine_rtpp_set_wrap(struct sip_msg *msg, int (*func)(struct sip_msg *msg, void *, int),
3338
-		void *data, int direction)
3378
+static int rtpengine_rtpp_set_wrap(struct sip_msg *msg, int (*func)(struct sip_msg *msg, void *, int,
3379
+			enum rtpe_operation),
3380
+		void *data, int direction, enum rtpe_operation op)
3339 3381
 {
3340 3382
 	int ret, more;
3341 3383
 
... ...
@@ -3348,7 +3390,7 @@ static int rtpengine_rtpp_set_wrap(struct sip_msg *msg, int (*func)(struct sip_m
3348 3390
 	if (!selected_rtpp_set_2 || selected_rtpp_set_2 == selected_rtpp_set_1)
3349 3391
 		more = 0;
3350 3392
 
3351
-	ret = func(msg, data, more);
3393
+	ret = func(msg, data, more, op);
3352 3394
 	if (ret < 0)
3353 3395
 		return ret;
3354 3396
 
... ...
@@ -3359,17 +3401,18 @@ static int rtpengine_rtpp_set_wrap(struct sip_msg *msg, int (*func)(struct sip_m
3359 3401
 	if (set_rtpengine_set_from_avp(msg, direction) == -1)
3360 3402
 		return -1;
3361 3403
 
3362
-	ret = func(msg, data, 0);
3404
+	ret = func(msg, data, 0, op);
3363 3405
 	body_intermediate.s = NULL;
3364 3406
 	return ret;
3365 3407
 }
3366 3408
 
3367
-static int rtpengine_delete_wrap(struct sip_msg *msg, void *d, int more) {
3409
+static int rtpengine_delete_wrap(struct sip_msg *msg, void *d, int more, enum rtpe_operation op) {
3368 3410
 	return rtpengine_delete(msg, d);
3369 3411
 }
3370 3412
 
3371
-static int
3372
-rtpengine_delete1_f(struct sip_msg* msg, char* str1, char* str2)
3413
+static int rtpengine_rtpp_set_wrap_fparam(struct sip_msg *msg, int (*func)(struct sip_msg *msg, void *, int,
3414
+			enum rtpe_operation),
3415
+		char *str1, int direction, enum rtpe_operation op)
3373 3416
 {
3374 3417
 	str flags;
3375 3418
 
... ...
@@ -3381,27 +3424,23 @@ rtpengine_delete1_f(struct sip_msg* msg, char* str1, char* str2)
3381 3424
 		}
3382 3425
 	}
3383 3426
 
3384
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_delete_wrap, flags.s, 1);
3427
+	return rtpengine_rtpp_set_wrap(msg, func, flags.s, direction, op);
3428
+}
3429
+
3430
+static int
3431
+rtpengine_delete1_f(struct sip_msg* msg, char* str1, char* str2)
3432
+{
3433
+	return rtpengine_rtpp_set_wrap_fparam(msg, rtpengine_delete_wrap, str1, 1, OP_DELETE);
3385 3434
 }
3386 3435
 
3387
-static int rtpengine_query_wrap(struct sip_msg *msg, void *d, int more) {
3436
+static int rtpengine_query_wrap(struct sip_msg *msg, void *d, int more, enum rtpe_operation op) {
3388 3437
 	return rtpengine_query(msg, d);
3389 3438
 }
3390 3439
 
3391 3440
 static int
3392 3441
 rtpengine_query1_f(struct sip_msg* msg, char* str1, char* str2)
3393 3442
 {
3394
-	str flags;
3395
-
3396
-	flags.s = NULL;
3397
-	if (str1) {
3398
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3399
-			LM_ERR("Error getting string parameter\n");
3400
-			return -1;
3401
-		}
3402
-	}
3403
-
3404
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_query_wrap, flags.s, 1);
3443
+	return rtpengine_rtpp_set_wrap_fparam(msg, rtpengine_query_wrap, str1, 1, OP_QUERY);
3405 3444
 }
3406 3445
 
3407 3446
 
... ...
@@ -3547,88 +3586,45 @@ rtpengine_manage(struct sip_msg *msg, const char *flags)
3547 3586
 	return -1;
3548 3587
 }
3549 3588
 
3550
-static int rtpengine_manage_wrap(struct sip_msg *msg, void *d, int more) {
3589
+static int rtpengine_manage_wrap(struct sip_msg *msg, void *d, int more, enum rtpe_operation op) {
3551 3590
 	return rtpengine_manage(msg, d);
3552 3591
 }
3553 3592
 
3554 3593
 static int
3555 3594
 rtpengine_manage1_f(struct sip_msg *msg, char *str1, char *str2)
3556 3595
 {
3557
-	str flags;
3558
-
3559
-	flags.s = NULL;
3560
-	if (str1) {
3561
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3562
-			LM_ERR("Error getting string parameter\n");
3563
-			return -1;
3564
-		}
3565
-	}
3566
-
3567
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_manage_wrap, flags.s, 1);
3568
-}
3569
-
3570
-static int rtpengine_info_wrap(struct sip_msg *msg, void *d, int more) {
3571
-	return rtpp_function_call_simple(msg, OP_OFFER, d);
3596
+	return rtpengine_rtpp_set_wrap_fparam(msg, rtpengine_manage_wrap, str1, 1, OP_ANY);
3572 3597
 }
3573 3598
 
3574 3599
 static int
3575 3600
 rtpengine_info1_f(struct sip_msg *msg, char *str1, char *str2)
3576 3601
 {
3577
-	str flags;
3578
-
3579
-	flags.s = NULL;
3580
-	if (str1) {
3581
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3582
-			LM_ERR("Error getting string parameter\n");
3583
-			return -1;
3584
-		}
3585
-	}
3586
-
3587
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_info_wrap, flags.s, 1);
3602
+	return rtpengine_rtpp_set_wrap_fparam(msg, rtpengine_simple_wrap, str1, 1, OP_OFFER);
3588 3603
 }
3589 3604
 
3590
-static int rtpengine_offer_wrap(struct sip_msg *msg, void *d, int more) {
3605
+static int rtpengine_offer_wrap(struct sip_msg *msg, void *d, int more, enum rtpe_operation op) {
3591 3606
 	return rtpengine_offer_answer(msg, d, OP_OFFER, more);
3592 3607
 }
3593 3608
 
3594 3609
 static int
3595 3610
 rtpengine_offer1_f(struct sip_msg *msg, char *str1, char *str2)
3596 3611
 {
3597
-	str flags;
3598
-
3599
-	flags.s = NULL;
3600
-	if (str1) {
3601
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3602
-			LM_ERR("Error getting string parameter\n");
3603
-			return -1;
3604
-		}
3605
-	}
3606
-
3607
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_offer_wrap, flags.s, 1);
3612
+	return rtpengine_rtpp_set_wrap_fparam(msg, rtpengine_offer_wrap, str1, 1, OP_OFFER);
3608 3613
 }
3609 3614
 
3610
-static int rtpengine_answer_wrap(struct sip_msg *msg, void *d, int more) {
3615
+static int rtpengine_answer_wrap(struct sip_msg *msg, void *d, int more, enum rtpe_operation op) {
3611 3616
 	return rtpengine_offer_answer(msg, d, OP_ANSWER, more);
3612 3617
 }
3613 3618
 
3614 3619
 static int
3615 3620
 rtpengine_answer1_f(struct sip_msg *msg, char *str1, char *str2)
3616 3621
 {
3617
-	str flags;
3618 3622
 
3619 3623
 	if (msg->first_line.type == SIP_REQUEST)
3620 3624
 		if (msg->first_line.u.request.method_value != METHOD_ACK)
3621 3625
 			return -1;
3622 3626
 
3623
-	flags.s = NULL;
3624
-	if (str1) {
3625
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3626
-			LM_ERR("Error getting string parameter\n");
3627
-			return -1;
3628
-		}
3629
-	}
3630
-
3631
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_answer_wrap, flags.s, 2);
3627
+	return rtpengine_rtpp_set_wrap_fparam(msg, rtpengine_answer_wrap, str1, 2, OP_ANSWER);
3632 3628
 }
3633 3629
 
3634 3630
 static int
... ...
@@ -3702,160 +3698,102 @@ error:
3702 3698
 }
3703 3699
 
3704 3700
 
3705
-static int rtpengine_start_recording_wrap(struct sip_msg *msg, void *d, int more) {
3706
-	return rtpp_function_call_simple(msg, OP_START_RECORDING, d);
3707
-}
3708
-
3709
-static int rtpengine_stop_recording_wrap(struct sip_msg *msg, void *d, int more) {
3710
-	return rtpp_function_call_simple(msg, OP_STOP_RECORDING, d);
3701
+static int
3702
+rtpengine_generic_f(struct sip_msg* msg, char *str1, enum rtpe_operation op)
3703
+{
3704
+	return rtpengine_rtpp_set_wrap_fparam(msg, rtpengine_simple_wrap, str1, 1, op);
3711 3705
 }
3712 3706
 
3713 3707
 static int
3714 3708
 start_recording_f(struct sip_msg* msg, char *str1, char *str2)
3715 3709
 {
3716
-	str flags;
3717
-	flags.s = NULL;
3718
-	if (str1) {
3719
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3720
-			LM_ERR("Error getting string parameter\n");
3721
-			return -1;
3722
-		}
3723
-	}
3724
-
3725
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_start_recording_wrap, flags.s, 1);
3710
+	return rtpengine_generic_f(msg, str1, OP_START_RECORDING);
3726 3711
 }
3727 3712
 
3728 3713
 static int
3729 3714
 stop_recording_f(struct sip_msg* msg, char *str1, char *str2)
3730 3715
 {
3731
-	str flags;
3732
-	flags.s = NULL;
3733
-	if (str1) {
3734
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3735
-			LM_ERR("Error getting string parameter\n");
3736
-			return -1;
3737
-		}
3738
-	}
3739
-
3740
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_stop_recording_wrap, flags.s, 1);
3741
-}
3742
-
3743
-
3744
-static int rtpengine_block_dtmf_wrap(struct sip_msg *msg, void *d, int more) {
3745
-	return rtpp_function_call_simple(msg, OP_BLOCK_DTMF, d);
3746
-}
3747
-
3748
-static int rtpengine_unblock_dtmf_wrap(struct sip_msg *msg, void *d, int more) {
3749
-	return rtpp_function_call_simple(msg, OP_UNBLOCK_DTMF, d);
3716
+	return rtpengine_generic_f(msg, str1, OP_STOP_RECORDING);
3750 3717
 }
3751 3718
 
3752 3719
 static int
3753 3720
 block_dtmf_f(struct sip_msg* msg, char *str1, char *str2)
3754 3721
 {
3755
-	str flags;
3756
-	flags.s = NULL;
3757
-	if (str1) {
3758
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3759
-			LM_ERR("Error getting string parameter\n");
3760
-			return -1;
3761
-		}
3762
-	}
3763
-
3764
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_block_dtmf_wrap, flags.s, 1);
3722
+	return rtpengine_generic_f(msg, str1, OP_BLOCK_DTMF);
3765 3723
 }
3766 3724
 
3767 3725
 static int
3768 3726
 unblock_dtmf_f(struct sip_msg* msg, char *str1, char *str2)
3769 3727
 {
3770
-	str flags;
3771
-	flags.s = NULL;
3772
-	if (str1) {
3773
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3774
-			LM_ERR("Error getting string parameter\n");
3775
-			return -1;
3776
-		}
3777
-	}
3778
-
3779
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_unblock_dtmf_wrap, flags.s, 1);
3780
-}
3781
-
3782
-static int rtpengine_block_media_wrap(struct sip_msg *msg, void *d, int more) {
3783
-	return rtpp_function_call_simple(msg, OP_BLOCK_MEDIA, d);
3784
-}
3785
-
3786
-static int rtpengine_unblock_media_wrap(struct sip_msg *msg, void *d, int more) {
3787
-	return rtpp_function_call_simple(msg, OP_UNBLOCK_MEDIA, d);
3728
+	return rtpengine_generic_f(msg, str1, OP_UNBLOCK_DTMF);
3788 3729
 }
3789 3730
 
3790 3731
 static int
3791 3732
 block_media_f(struct sip_msg* msg, char *str1, char *str2)
3792 3733
 {
3793
-	str flags;
3794
-	flags.s = NULL;
3795
-	if (str1) {
3796
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3797
-			LM_ERR("Error getting string parameter\n");
3798
-			return -1;
3799
-		}
3800
-	}
3801
-
3802
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_block_media_wrap, flags.s, 1);
3734
+	return rtpengine_generic_f(msg, str1, OP_BLOCK_MEDIA);
3803 3735
 }
3804 3736
 
3805 3737
 static int
3806 3738
 unblock_media_f(struct sip_msg* msg, char *str1, char *str2)
3807 3739
 {
3808
-	str flags;
3809
-	flags.s = NULL;
3810
-	if (str1) {
3811
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3812
-			LM_ERR("Error getting string parameter\n");
3813
-			return -1;
3740
+	return rtpengine_generic_f(msg, str1, OP_UNBLOCK_MEDIA);
3741
+}
3742
+
3743
+static int rtpengine_play_media(struct sip_msg *msg, void *d, int more, enum rtpe_operation op) {
3744
+	bencode_buffer_t bencbuf;
3745
+	long long duration;
3746
+	bencode_item_t *ret;
3747
+	char intbuf[32];
3748
+	pv_value_t val;
3749
+	int retval = 1;
3750
+
3751
+	ret = rtpp_function_call_ok(&bencbuf, msg, OP_PLAY_MEDIA, d, NULL);
3752
+	if (!ret)
3753
+		return -1;
3754
+	if (media_duration_pvar) {
3755
+		duration = bencode_dictionary_get_integer(ret, "duration", -1);
3756
+		snprintf(intbuf, sizeof(intbuf), "%lli", duration);
3757
+		memset(&val, 0, sizeof(val));
3758
+		val.flags = PV_VAL_STR;
3759
+		val.rs.s = intbuf;
3760
+		val.rs.len = strlen(intbuf);
3761
+		if (media_duration_pvar->setf(msg, &media_duration_pvar->pvp, (int)EQ_T, &val) < 0)
3762
+		{
3763
+			LM_ERR("error setting pvar <%.*s>\n", media_duration_pvar_str.len, media_duration_pvar_str.s);
3764
+			retval = -1;
3814 3765
 		}
3815 3766
 	}
3816 3767
 
3817
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_unblock_media_wrap, flags.s, 1);
3768
+	bencode_buffer_free(&bencbuf);
3769
+	return retval;
3818 3770
 }
3819 3771
 
3820
-static int rtpengine_start_forwarding_wrap(struct sip_msg *msg, void *d, int more) {
3821
-	return rtpp_function_call_simple(msg, OP_START_FORWARDING, d);
3772
+static int
3773
+play_media_f(struct sip_msg* msg, char *str1, char *str2)
3774
+{
3775
+	return rtpengine_rtpp_set_wrap_fparam(msg, rtpengine_play_media, str1, 1, OP_PLAY_MEDIA);
3822 3776
 }
3823 3777
 
3824
-static int rtpengine_stop_forwarding_wrap(struct sip_msg *msg, void *d, int more) {
3825
-	return rtpp_function_call_simple(msg, OP_STOP_FORWARDING, d);
3778
+static int
3779
+stop_media_f(struct sip_msg* msg, char *str1, char *str2)
3780
+{
3781
+	return rtpengine_generic_f(msg, str1, OP_STOP_MEDIA);
3826 3782
 }
3827 3783
 
3828 3784
 static int
3829 3785
 start_forwarding_f(struct sip_msg* msg, char *str1, char *str2)
3830 3786
 {
3831
-	str flags;
3832
-	flags.s = NULL;
3833
-	if (str1) {
3834
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3835
-			LM_ERR("Error getting string parameter\n");
3836
-			return -1;
3837
-		}
3838
-	}
3839
-
3840
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_start_forwarding_wrap, flags.s, 1);
3787
+	return rtpengine_generic_f(msg, str1, OP_START_FORWARDING);
3841 3788
 }
3842 3789
 
3843 3790
 static int
3844 3791
 stop_forwarding_f(struct sip_msg* msg, char *str1, char *str2)
3845 3792
 {
3846
-	str flags;
3847
-	flags.s = NULL;
3848
-	if (str1) {
3849
-		if (get_str_fparam(&flags, msg, (fparam_t *) str1)) {
3850
-			LM_ERR("Error getting string parameter\n");
3851
-			return -1;
3852
-		}
3853
-	}
3854
-
3855
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_stop_forwarding_wrap, flags.s, 1);
3793
+	return rtpengine_generic_f(msg, str1, OP_STOP_FORWARDING);
3856 3794
 }
3857 3795
 
3858
-static int rtpengine_rtpstat_wrap(struct sip_msg *msg, void *d, int more) {
3796
+static int rtpengine_rtpstat_wrap(struct sip_msg *msg, void *d, int more, enum rtpe_operation op) {
3859 3797
 	void **parms;
3860 3798
 	pv_param_t *param;
3861 3799
 	pv_value_t *res;
... ...
@@ -3909,7 +3847,7 @@ pv_get_rtpstat_f(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
3909 3847
 	parms[0] = param;
3910 3848
 	parms[1] = res;
3911 3849
 
3912
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_rtpstat_wrap, parms, 1);
3850
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_rtpstat_wrap, parms, 1, OP_ANY);
3913 3851
 }
3914 3852
 
3915 3853
 static int
... ...
@@ -3934,64 +3872,65 @@ set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri) {
3934 3872
  *
3935 3873
  */
3936 3874
 static int ki_rtpengine_manage0(sip_msg_t *msg) {
3937
-    return rtpengine_rtpp_set_wrap(msg, rtpengine_manage_wrap, NULL, 1);
3875
+    return rtpengine_rtpp_set_wrap(msg, rtpengine_manage_wrap, NULL, 1, OP_ANY);
3938 3876
 }
3939 3877
 
3940 3878
 /**
3941 3879
  *
3942 3880
  */
3943 3881
 static int ki_rtpengine_manage(sip_msg_t *msg, str *flags) {
3944
-    return rtpengine_rtpp_set_wrap(msg, rtpengine_manage_wrap, ((flags && flags->len > 0) ? flags->s : NULL), 1);
3882
+    return rtpengine_rtpp_set_wrap(msg, rtpengine_manage_wrap, ((flags && flags->len > 0) ? flags->s : NULL), 1,
3883
+		    OP_ANY);
3945 3884
 }
3946 3885
 
3947 3886
 static int ki_rtpengine_offer0(sip_msg_t *msg)
3948 3887
 {
3949
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_offer_wrap, 0, 1);
3888
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_offer_wrap, 0, 1, OP_ANY);
3950 3889
 }
3951 3890
 
3952 3891
 static int ki_rtpengine_offer(sip_msg_t *msg, str *flags)
3953 3892
 {
3954
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_offer_wrap, flags->s, 1);
3893
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_offer_wrap, flags->s, 1, OP_ANY);
3955 3894
 }
3956 3895
 
3957 3896
 static int ki_rtpengine_answer0(sip_msg_t *msg)
3958 3897
 {
3959
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_answer_wrap, NULL, 2);
3898
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_answer_wrap, NULL, 2, OP_ANY);
3960 3899
 }
3961 3900
 
3962 3901
 static int ki_rtpengine_answer(sip_msg_t *msg, str *flags)
3963 3902
 {
3964
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_answer_wrap, flags->s, 2);
3903
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_answer_wrap, flags->s, 2, OP_ANY);
3965 3904
 }
3966 3905
 
3967 3906
 static int ki_rtpengine_delete0(sip_msg_t *msg)
3968 3907
 {
3969
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_delete_wrap, NULL, 1);
3908
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_delete_wrap, NULL, 1, OP_ANY);
3970 3909
 }
3971 3910
 
3972 3911
 static int ki_rtpengine_delete(sip_msg_t *msg, str *flags)
3973 3912
 {
3974
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_delete_wrap, flags->s, 1);
3913
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_delete_wrap, flags->s, 1, OP_ANY);
3975 3914
 }
3976 3915
 
3977 3916
 static int ki_rtpengine_query0(sip_msg_t *msg)
3978 3917
 {       
3979
-        return rtpengine_rtpp_set_wrap(msg, rtpengine_query_wrap, NULL, 1);
3918
+        return rtpengine_rtpp_set_wrap(msg, rtpengine_query_wrap, NULL, 1, OP_ANY);
3980 3919
 }
3981 3920
 
3982 3921
 static int ki_rtpengine_query(sip_msg_t *msg, str *flags)
3983 3922
 {       
3984
-        return rtpengine_rtpp_set_wrap(msg, rtpengine_query_wrap, flags->s, 1);
3923
+        return rtpengine_rtpp_set_wrap(msg, rtpengine_query_wrap, flags->s, 1, OP_ANY);
3985 3924
 }
3986 3925
 
3987 3926
 static int ki_start_recording(sip_msg_t *msg)
3988 3927
 {
3989
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_start_recording_wrap, NULL, 1);
3928
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_simple_wrap, NULL, 1, OP_START_RECORDING);
3990 3929
 }
3991 3930
 
3992 3931
 static int ki_stop_recording(sip_msg_t *msg)
3993 3932
 {
3994
-	return rtpengine_rtpp_set_wrap(msg, rtpengine_stop_recording_wrap, NULL, 1);
3933
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_simple_wrap, NULL, 1, OP_STOP_RECORDING);
3995 3934
 }
3996 3935
 
3997 3936
 static int ki_set_rtpengine_set(sip_msg_t *msg, int r1)
... ...
@@ -44,6 +44,10 @@ enum rtpe_operation {
44 44
         OP_UNBLOCK_MEDIA,
45 45
         OP_START_FORWARDING,
46 46
         OP_STOP_FORWARDING,
47
+        OP_PLAY_MEDIA,
48
+        OP_STOP_MEDIA,
49
+
50
+        OP_ANY,
47 51
 };
48 52
 
49 53
 struct rtpp_node {