Browse code

rtp_media_server: support for multiple actions

Julien Chavanton authored on 11/11/2018 20:46:10
Showing 8 changed files
... ...
@@ -24,7 +24,7 @@ listen=udp:147.75.39.121:5090
24 24
 
25 25
 event_route[rms:start] {
26 26
 	xnotice("[rms:start] play ...\n");
27
-	rms_play("./voice_file/Bach_10s_8000.wav", "rms:after_play");
27
+	rms_play("./voice_files/OSR_us_000_0010_8k.wav", "rms:after_play");
28 28
 };
29 29
 
30 30
 event_route[rms:after_play] {
... ...
@@ -103,6 +103,9 @@ modparam("rtp_media_server", "log_file_name", "/var/log/rms/rms_ortp.log")
103 103
 		Create a session and a call leg and call the event_route[rms:start]
104 104
 		config example
105 105
 		</para>
106
+		<para>
107
+		This function can be used from REQUEST_ROUTE, REPLY_ROUTE and FAILURE_ROUTE.
108
+		</para>
106 109
 		<example>
107 110
 		<title>usage example</title>
108 111
 		<programlisting format="linespecific">
... ...
@@ -142,6 +145,9 @@ route {
142 145
 		<para>
143 146
 		Send a BYE, delete the RTP session and the media ressources.
144 147
 		</para>
148
+		<para>
149
+		This function can be used from EVENT_ROUTE.
150
+		</para>
145 151
 		<example>
146 152
 		<title>usage example</title>
147 153
 		<programlisting format="linespecific">
... ...
@@ -162,6 +168,9 @@ route {
162 168
 		If the SIP session is not found "481 Call/Transaction Does Not Exist"
163 169
 		is returned.
164 170
 		</para>
171
+		<para>
172
+		This function can be used from REQUEST_ROUTE, REPLY_ROUTE and FAILURE_ROUTE.
173
+		</para>
165 174
 		<example>
166 175
 		<title>usage example</title>
167 176
 		<programlisting format="linespecific">
... ...
@@ -181,6 +190,9 @@ route {
181 190
 		</para><para>
182 191
 		The second parameter is the event route that will be called when the file was played.
183 192
 		</para>
193
+		<para>
194
+		This function can be used from EVENT_ROUTE.
195
+		</para>
184 196
 		<example>
185 197
 		<title>usage example</title>
186 198
 		<programlisting format="linespecific">
... ...
@@ -43,3 +43,10 @@ make install
43 43
 cd ..
44 44
 
45 45
 ldconfig
46
+
47
+# download sample voice file
48
+mkdir -p voice_files
49
+cd voice_files
50
+wget http://www.voiptroubleshooter.com/open_speech/american/OSR_us_000_0010_8k.wav
51
+cd ..
52
+
... ...
@@ -41,7 +41,6 @@ typedef struct shared_global_vars
41 41
 	gen_lock_t lock;
42 42
 } shared_global_vars_t;
43 43
 
44
-static shared_global_vars_t *vars;
45 44
 
46 45
 MSFilterDesc *rms_ms_filter_descs[] = {&ms_alaw_dec_desc, &ms_alaw_enc_desc,
47 46
 		&ms_ulaw_dec_desc, &ms_ulaw_enc_desc, &ms_rtp_send_desc,
... ...
@@ -75,7 +74,6 @@ int rms_media_init()
75 74
 	ortp_memory_functions.free_fun = ptr_shm_free;
76 75
 	ortp_set_memory_functions(&ortp_memory_functions);
77 76
 	ortp_init();
78
-	vars = shm_malloc(sizeof(shared_global_vars_t));
79 77
 	return 1;
80 78
 }
81 79
 
... ...
@@ -155,8 +153,8 @@ static void rms_player_eof(
155 153
 		void *user_data, MSFilter *f, unsigned int event, void *event_data)
156 154
 {
157 155
 	if(event == MS_FILE_PLAYER_EOF) {
158
-		rms_session_info_t *si = (rms_session_info_t *)user_data;
159
-		si->action = RMS_DONE;
156
+		rms_action_t *a = (rms_action_t *)user_data;
157
+		a->type = RMS_DONE;
160 158
 	}
161 159
 	MS_UNUSED(f), MS_UNUSED(event_data);
162 160
 }
... ...
@@ -203,13 +201,22 @@ int rms_stop_bridge(call_leg_media_t *m1, call_leg_media_t *m2)
203 201
 	return 1;
204 202
 }
205 203
 
206
-int rms_playfile(call_leg_media_t *m, char *file_name)
204
+
205
+int rms_get_dtmf(call_leg_media_t *m, char dtmf) {
206
+//	static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id, MSToneDetectorEvent *ev) {
207
+//			MS_UNUSED(data), MS_UNUSED(f), MS_UNUSED(event_id), MS_UNUSED(ev);
208
+//				ms_tester_tone_detected = TRUE;
209
+//	}
210
+	return 1;
211
+}
212
+
213
+int rms_playfile(call_leg_media_t *m, rms_action_t *a)
207 214
 {
208 215
 	int file_sample_rate = 8000;
209 216
 	if(!m->ms_player)
210 217
 		return 0;
211
-	ms_filter_add_notify_callback(m->ms_player, rms_player_eof, m->si, TRUE);
212
-	ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_OPEN, (void *)file_name);
218
+	ms_filter_add_notify_callback(m->ms_player, rms_player_eof, a, TRUE);
219
+	ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_OPEN, (void *)a->param.s);
213 220
 	ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_START, NULL);
214 221
 	ms_filter_call_method(m->ms_player, MS_FILTER_GET_SAMPLE_RATE, &file_sample_rate);
215 222
 	ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate);
... ...
@@ -35,6 +35,7 @@
35 35
 #include <ortp/port.h>
36 36
 
37 37
 struct rms_session_info;
38
+typedef struct rms_action rms_action_t;
38 39
 
39 40
 typedef struct call_leg_media
40 41
 {
... ...
@@ -68,7 +69,7 @@ void rms_media_destroy();
68 69
 MSFactory *rms_get_factory();
69 70
 
70 71
 int rms_stop_media(call_leg_media_t *m);
71
-int rms_playfile(call_leg_media_t *m, char *file_name);
72
+int rms_playfile(call_leg_media_t *m, rms_action_t *a);
72 73
 int rms_start_media(call_leg_media_t *m, char *file_name);
73 74
 int rms_bridge(call_leg_media_t *m1, call_leg_media_t *m2);
74 75
 int rms_stop_bridge(call_leg_media_t *m1, call_leg_media_t *m2);
... ...
@@ -47,13 +47,15 @@ static int rms_hangup_f(struct sip_msg *);
47 47
 static int rms_sessions_dump_f(struct sip_msg *, char *, char *);
48 48
 
49 49
 static cmd_export_t cmds[] = {
50
-		{"rms_answer", (cmd_function)rms_answer_f, 0, 0, 0, ANY_ROUTE},
50
+		{"rms_answer", (cmd_function)rms_answer_f, 0, 0, 0, EVENT_ROUTE},
51 51
 		{"rms_play", (cmd_function)rms_action_play_f, 2, fixup_rms_action_play, 0,
52 52
 				ANY_ROUTE},
53 53
 		{"rms_sdp_offer", (cmd_function)rms_sdp_offer_f, 0, 0, 0, ANY_ROUTE},
54
-		{"rms_sdp_answer", (cmd_function)rms_sdp_answer_f, 0, 0, 0, ANY_ROUTE},
55
-		{"rms_media_stop", (cmd_function)rms_media_stop_f, 0, 0, 0, ANY_ROUTE},
56
-		{"rms_hangup", (cmd_function)rms_hangup_f, 0, 0, 0, ANY_ROUTE},
54
+		{"rms_sdp_answer", (cmd_function)rms_sdp_answer_f, 0, 0, 0, REQUEST_ROUTE
55
+				| FAILURE_ROUTE | ONREPLY_ROUTE},
56
+		{"rms_media_stop", (cmd_function)rms_media_stop_f, 0, 0, 0, REQUEST_ROUTE
57
+				| FAILURE_ROUTE | ONREPLY_ROUTE},
58
+		{"rms_hangup", (cmd_function)rms_hangup_f, 0, 0, 0, EVENT_ROUTE},
57 59
 		{"rms_sessions_dump", (cmd_function)rms_sessions_dump_f, 0, 0, 0,
58 60
 				ANY_ROUTE},
59 61
 		{0, 0, 0, 0, 0, 0}};
... ...
@@ -161,6 +163,53 @@ void rms_signal_handler(int signum)
161 163
 	LM_INFO("signal received [%d]\n", signum);
162 164
 }
163 165
 
166
+static rms_session_info_t* rms_session_action_check(rms_session_info_t *si)
167
+{
168
+	rms_action_t *a;
169
+	clist_foreach(&si->action, a, next)
170
+	{
171
+		if(a->type == RMS_HANGUP) {
172
+			LM_INFO("session action RMS_HANGUP [%s]\n", si->callid.s);
173
+			rms_hangup_call(si);
174
+			a->type = RMS_STOP;
175
+			return si;
176
+		} else if(a->type == RMS_STOP) {
177
+			LM_INFO("session action RMS_STOP [%s][%p|%p]\n", si->callid.s, si, si->prev);
178
+			rms_stop_media(&si->caller_media);
179
+			rms_session_info_t *tmp = si->prev;
180
+			clist_rm(si, next, prev);
181
+			rms_session_free(si);
182
+			si = tmp;
183
+			return si;
184
+		} else if(a->type == RMS_PLAY) {
185
+			LM_INFO("session action RMS_PLAY [%s]\n", si->callid.s);
186
+			rms_playfile(&si->caller_media, a);
187
+			a->type = RMS_NONE;
188
+		} else if(a->type == RMS_DONE) {
189
+			LM_INFO("session action RMS_DONE [%s][%s]\n", si->callid.s,
190
+					a->route.s);
191
+			if(a->route.s) {
192
+				run_action_route(si, a->route.s);
193
+				rms_action_t *tmp = a->prev;
194
+				clist_rm(a, next, prev);
195
+				shm_free(a);
196
+				a = tmp;
197
+			} else {
198
+				a->type = RMS_HANGUP;
199
+			}
200
+			return si;
201
+		} else if(a->type == RMS_START) {
202
+			create_call_leg_media(&si->caller_media);
203
+			LM_INFO("session action RMS_START [%s]\n", si->callid.s);
204
+			rms_start_media(&si->caller_media, a->param.s);
205
+			run_action_route(si, "rms:start");
206
+			a->type = RMS_NONE;
207
+			return si;
208
+		}
209
+	}
210
+	return si;
211
+}
212
+
164 213
 /**
165 214
  * Most interaction with the session and media streams that are controlled 
166 215
  * in this function this is safer in the event where a library is using non shared memory
... ...
@@ -173,36 +222,7 @@ static void rms_session_manage_loop()
173 222
 		rms_session_info_t *si;
174 223
 		clist_foreach(rms_session_list, si, next)
175 224
 		{
176
-			if(si->action == RMS_HANGUP) {
177
-				LM_INFO("session action RMS_HANGUP [%s]\n", si->callid.s);
178
-				rms_hangup_call(si);
179
-				si->action = RMS_STOP;
180
-			} else if(si->action == RMS_STOP) {
181
-				LM_INFO("session action RMS_STOP [%s]\n", si->callid.s);
182
-				rms_stop_media(&si->caller_media);
183
-				rms_session_info_t *tmp = si->prev;
184
-				clist_rm(si, next, prev);
185
-				rms_session_free(si);
186
-				si = tmp;
187
-			} else if(si->action == RMS_PLAY) {
188
-				LM_INFO("session action RMS_PLAY [%s]\n", si->callid.s);
189
-				rms_playfile(&si->caller_media, si->action_param.s);
190
-				si->action = RMS_NONE;
191
-			} else if(si->action == RMS_DONE) {
192
-				LM_INFO("session action RMS_DONE [%s][%s]\n", si->callid.s,
193
-						si->action_route.s);
194
-				if(si->action_route.s) {
195
-					run_action_route(si, si->action_route.s);
196
-				} else {
197
-					si->action = RMS_HANGUP;
198
-				}
199
-			} else if(si->action == RMS_START) {
200
-				create_call_leg_media(&si->caller_media);
201
-				LM_INFO("session action RMS_START [%s]\n", si->callid.s);
202
-				rms_start_media(&si->caller_media, si->action_param.s);
203
-				si->action = RMS_NONE;
204
-				run_action_route(si, "rms:start");
205
-			}
225
+			si = rms_session_action_check(si);
206 226
 		}
207 227
 		unlock(&session_list_mutex);
208 228
 		usleep(2000);
... ...
@@ -362,20 +382,6 @@ static int rms_answer_call(struct sip_msg *msg, rms_session_info_t *si)
362 382
 	return 1;
363 383
 }
364 384
 
365
-static rms_session_info_t *rms_session_search(char *callid, int len)
366
-{
367
-	// lock(&session_list_mutex);
368
-	rms_session_info_t *si;
369
-	clist_foreach(rms_session_list, si, next)
370
-	{
371
-		if(strncmp(callid, si->callid.s, len) == 0) {
372
-			unlock(&session_list_mutex);
373
-			return si;
374
-		}
375
-	}
376
-	// unlock(&session_list_mutex);
377
-	return NULL;
378
-}
379 385
 
380 386
 static int rms_hangup_call(rms_session_info_t *si)
381 387
 {
... ...
@@ -421,8 +427,20 @@ static int rms_check_msg(struct sip_msg *msg)
421 427
 	return 1;
422 428
 }
423 429
 
430
+static void rms_action_free(rms_session_info_t *si)
431
+{
432
+	rms_action_t *a, *tmp;
433
+	clist_foreach(&si->action, a, next) {
434
+		tmp = a;
435
+		a = a->prev;
436
+		clist_rm(tmp, next, prev);
437
+		shm_free(tmp);
438
+	}
439
+}
440
+
424 441
 static int rms_session_free(rms_session_info_t *si)
425 442
 {
443
+	rms_action_free(si);
426 444
 	rms_sdp_info_free(&si->sdp_info_offer);
427 445
 	rms_sdp_info_free(&si->sdp_info_answer);
428 446
 	if(si->caller_media.pt) {
... ...
@@ -458,6 +476,14 @@ static int rms_session_free(rms_session_info_t *si)
458 476
 	return 1;
459 477
 }
460 478
 
479
+rms_action_t *rms_action_new(rms_action_type_t t) {
480
+	rms_action_t *a = shm_malloc(sizeof(rms_action_t));
481
+	if (!a) return NULL;
482
+	memset(a, 0, sizeof(rms_action_t));
483
+	a->type = t;
484
+	return a;
485
+}
486
+
461 487
 rms_session_info_t *rms_session_new(struct sip_msg *msg)
462 488
 {
463 489
 	struct hdr_field *hdr = NULL;
... ...
@@ -502,7 +528,7 @@ rms_session_info_t *rms_session_new(struct sip_msg *msg)
502 528
 		tmb.t_reply(msg, 488, "incompatible media format");
503 529
 		goto error;
504 530
 	}
505
-
531
+	clist_init(&si->action, next, prev);
506 532
 	return si;
507 533
 error:
508 534
 	rms_session_free(si);
... ...
@@ -552,6 +578,16 @@ static int rms_create_trans(struct sip_msg *msg) {
552 578
 	return 1;
553 579
 }
554 580
 
581
+static void rms_action_add(rms_session_info_t *si, rms_action_t *a) {
582
+	clist_append(&si->action, a, next, prev);
583
+}
584
+
585
+static void rms_action_add_sync(rms_session_info_t *si, rms_action_t *a) {
586
+	lock(&session_list_mutex);
587
+	rms_action_add(si, a);
588
+	unlock(&session_list_mutex);
589
+}
590
+
555 591
 static void rms_session_add(rms_session_info_t *si) {
556 592
 	lock(&session_list_mutex);
557 593
 	clist_append(rms_session_list, si, next, prev);
... ...
@@ -564,6 +600,26 @@ static void rms_session_rm(rms_session_info_t *si) {
564 600
 	unlock(&session_list_mutex);
565 601
 }
566 602
 
603
+static rms_session_info_t *rms_session_search(char *callid, int len)
604
+{
605
+	rms_session_info_t *si;
606
+	clist_foreach(rms_session_list, si, next)
607
+	{
608
+		if(strncmp(callid, si->callid.s, len) == 0) {
609
+			return si;
610
+		}
611
+	}
612
+	return NULL;
613
+}
614
+
615
+static rms_session_info_t *rms_session_search_sync(char *callid, int len)
616
+{
617
+	lock(&session_list_mutex);
618
+	rms_session_info_t *si = rms_session_search(callid, len);
619
+	unlock(&session_list_mutex);
620
+	return si;
621
+}
622
+
567 623
 static int rms_sdp_offer_f(struct sip_msg *msg, char *param1, char *param2)
568 624
 {
569 625
 	int status = rms_create_trans(msg);
... ...
@@ -595,7 +651,7 @@ static int rms_sdp_answer_f(struct sip_msg *msg, char *param1, char *param2)
595 651
 		LM_INFO("no callid ?\n");
596 652
 		return -1;
597 653
 	}
598
-	si = rms_session_search(msg->callid->body.s, msg->callid->body.len);
654
+	si = rms_session_search_sync(msg->callid->body.s, msg->callid->body.len);
599 655
 	if(!si) {
600 656
 		LM_INFO("session not found ci[%.*s]\n", msg->callid->body.len,
601 657
 				msg->callid->body.s);
... ...
@@ -642,7 +698,7 @@ static int rms_media_stop_f(struct sip_msg *msg, char *param1, char *param2)
642 698
 		LM_ERR("no callid\n");
643 699
 		return -1;
644 700
 	}
645
-	si = rms_session_search(msg->callid->body.s, msg->callid->body.len);
701
+	si = rms_session_search_sync(msg->callid->body.s, msg->callid->body.len);
646 702
 	if(!si) {
647 703
 		LM_INFO("session not found ci[%.*s]\n", msg->callid->body.len,
648 704
 				msg->callid->body.s);
... ...
@@ -651,13 +707,24 @@ static int rms_media_stop_f(struct sip_msg *msg, char *param1, char *param2)
651 707
 		}
652 708
 		return 0;
653 709
 	}
654
-	si->action = RMS_STOP;
710
+	rms_action_t *a = rms_action_new(RMS_STOP);
711
+	if(!a) return -1;
712
+	rms_action_add_sync(si, a);
655 713
 	if(!tmb.t_reply(msg, 200, "OK")) {
656 714
 		return -1;
657 715
 	}
658 716
 	return 0;
659 717
 }
660 718
 
719
+//static int rms_action_dtmf_f(struct sip_msg *msg, char dtmf, str *route)
720
+//	rms_session_info_t *si =
721
+//			rms_session_search(msg->callid->body.s, msg->callid->body.len);
722
+//	if(!si)
723
+//		return -1;
724
+//	rms_playfile();
725
+//	return 0;
726
+//}
727
+
661 728
 static int rms_action_play_f(struct sip_msg *msg, str *playback_fn, str *route)
662 729
 {
663 730
 	rms_session_info_t *si =
... ...
@@ -667,11 +734,14 @@ static int rms_action_play_f(struct sip_msg *msg, str *playback_fn, str *route)
667 734
 	LM_INFO("RTP session [%s:%d]<>[%s:%d]\n", si->caller_media.local_ip.s,
668 735
 			si->caller_media.local_port, si->caller_media.remote_ip.s,
669 736
 			si->caller_media.remote_port);
670
-	si->action = RMS_PLAY;
671
-	si->action_param.len = playback_fn->len;
672
-	si->action_param.s = playback_fn->s;
673
-	si->action_route.len = route->len;
674
-	si->action_route.s = route->s;
737
+
738
+	rms_action_t *a = rms_action_new(RMS_PLAY);
739
+	if(!a) return -1;
740
+	a->param.len = playback_fn->len;
741
+	a->param.s = playback_fn->s;
742
+	a->route.len = route->len;
743
+	a->route.s = route->s;
744
+	rms_action_add(si, a);
675 745
 	return 0;
676 746
 }
677 747
 
... ...
@@ -681,12 +751,12 @@ static int rms_hangup_f(struct sip_msg *msg)
681 751
 			rms_session_search(msg->callid->body.s, msg->callid->body.len);
682 752
 	if(!si)
683 753
 		return -1;
684
-	si->action = RMS_HANGUP;
754
+	rms_action_t *a = rms_action_new(RMS_HANGUP);
755
+	if(!a) return -1;
756
+	rms_action_add(si, a);
685 757
 	return 0;
686 758
 }
687 759
 
688
-
689
-
690 760
 static int rms_answer_f(struct sip_msg *msg)
691 761
 {
692 762
 	int status = rms_create_trans(msg);
... ...
@@ -707,7 +777,9 @@ static int rms_answer_f(struct sip_msg *msg)
707 777
 	LM_INFO("RTP session [%s:%d]<>[%s:%d]\n", si->caller_media.local_ip.s,
708 778
 			si->caller_media.local_port, si->caller_media.remote_ip.s,
709 779
 			si->caller_media.remote_port);
710
-	si->action = RMS_START;
780
+	rms_action_t *a = rms_action_new(RMS_START);
781
+	if(!a) return -1;
782
+	rms_action_add(si, a);
711 783
 	return 1;
712 784
 error:
713 785
 	rms_session_rm(si);
... ...
@@ -58,13 +58,23 @@ typedef struct ms_res
58 58
 	RtpProfile *rtp_profile;
59 59
 } ms_res_t;
60 60
 
61
-typedef enum rms_action {
61
+typedef enum rms_action_type
62
+{
62 63
 	RMS_NONE,
63 64
 	RMS_START,
64 65
 	RMS_STOP,
65 66
 	RMS_HANGUP,
66 67
 	RMS_PLAY,
67 68
 	RMS_DONE,
69
+} rms_action_type_t;
70
+
71
+typedef struct rms_action
72
+{
73
+	struct rms_action *next;
74
+	struct rms_action *prev;
75
+	str param;
76
+	str route;
77
+	rms_action_type_t type;
68 78
 } rms_action_t;
69 79
 
70 80
 typedef struct rms_session_info
... ...
@@ -85,8 +95,6 @@ typedef struct rms_session_info
85 95
 	call_leg_media_t caller_media;
86 96
 	call_leg_media_t callee_media;
87 97
 	rms_action_t action;
88
-	str action_param;
89
-	str action_route;
90 98
 } rms_session_info_t;
91 99
 
92 100
 #endif
93 101
deleted file mode 100644
94 102
Binary files a/src/modules/rtp_media_server/voice_file/Bach_10s_8000.wav and /dev/null differ