Browse Source

rtp_media_server: support for multiple actions

Julien Chavanton 6 năm trước cách đây
mục cha
commit
2a76fdd433

+ 1 - 1
src/modules/rtp_media_server/config_example/kamailio.cfg

@@ -24,7 +24,7 @@ listen=udp:147.75.39.121:5090
 
 event_route[rms:start] {
 	xnotice("[rms:start] play ...\n");
-	rms_play("./voice_file/Bach_10s_8000.wav", "rms:after_play");
+	rms_play("./voice_files/OSR_us_000_0010_8k.wav", "rms:after_play");
 };
 
 event_route[rms:after_play] {

+ 12 - 0
src/modules/rtp_media_server/doc/rtp_media_server_admin.xml

@@ -103,6 +103,9 @@ modparam("rtp_media_server", "log_file_name", "/var/log/rms/rms_ortp.log")
 		Create a session and a call leg and call the event_route[rms:start]
 		config example
 		</para>
+		<para>
+		This function can be used from REQUEST_ROUTE, REPLY_ROUTE and FAILURE_ROUTE.
+		</para>
 		<example>
 		<title>usage example</title>
 		<programlisting format="linespecific">
@@ -142,6 +145,9 @@ route {
 		<para>
 		Send a BYE, delete the RTP session and the media ressources.
 		</para>
+		<para>
+		This function can be used from EVENT_ROUTE.
+		</para>
 		<example>
 		<title>usage example</title>
 		<programlisting format="linespecific">
@@ -162,6 +168,9 @@ route {
 		If the SIP session is not found "481 Call/Transaction Does Not Exist"
 		is returned.
 		</para>
+		<para>
+		This function can be used from REQUEST_ROUTE, REPLY_ROUTE and FAILURE_ROUTE.
+		</para>
 		<example>
 		<title>usage example</title>
 		<programlisting format="linespecific">
@@ -181,6 +190,9 @@ route {
 		</para><para>
 		The second parameter is the event route that will be called when the file was played.
 		</para>
+		<para>
+		This function can be used from EVENT_ROUTE.
+		</para>
 		<example>
 		<title>usage example</title>
 		<programlisting format="linespecific">

+ 7 - 0
src/modules/rtp_media_server/install_bc.sh

@@ -43,3 +43,10 @@ make install
 cd ..
 
 ldconfig
+
+# download sample voice file
+mkdir -p voice_files
+cd voice_files
+wget http://www.voiptroubleshooter.com/open_speech/american/OSR_us_000_0010_8k.wav
+cd ..
+

+ 14 - 7
src/modules/rtp_media_server/rms_media.c

@@ -41,7 +41,6 @@ typedef struct shared_global_vars
 	gen_lock_t lock;
 } shared_global_vars_t;
 
-static shared_global_vars_t *vars;
 
 MSFilterDesc *rms_ms_filter_descs[] = {&ms_alaw_dec_desc, &ms_alaw_enc_desc,
 		&ms_ulaw_dec_desc, &ms_ulaw_enc_desc, &ms_rtp_send_desc,
@@ -75,7 +74,6 @@ int rms_media_init()
 	ortp_memory_functions.free_fun = ptr_shm_free;
 	ortp_set_memory_functions(&ortp_memory_functions);
 	ortp_init();
-	vars = shm_malloc(sizeof(shared_global_vars_t));
 	return 1;
 }
 
@@ -155,8 +153,8 @@ static void rms_player_eof(
 		void *user_data, MSFilter *f, unsigned int event, void *event_data)
 {
 	if(event == MS_FILE_PLAYER_EOF) {
-		rms_session_info_t *si = (rms_session_info_t *)user_data;
-		si->action = RMS_DONE;
+		rms_action_t *a = (rms_action_t *)user_data;
+		a->type = RMS_DONE;
 	}
 	MS_UNUSED(f), MS_UNUSED(event_data);
 }
@@ -203,13 +201,22 @@ int rms_stop_bridge(call_leg_media_t *m1, call_leg_media_t *m2)
 	return 1;
 }
 
-int rms_playfile(call_leg_media_t *m, char *file_name)
+
+int rms_get_dtmf(call_leg_media_t *m, char dtmf) {
+//	static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id, MSToneDetectorEvent *ev) {
+//			MS_UNUSED(data), MS_UNUSED(f), MS_UNUSED(event_id), MS_UNUSED(ev);
+//				ms_tester_tone_detected = TRUE;
+//	}
+	return 1;
+}
+
+int rms_playfile(call_leg_media_t *m, rms_action_t *a)
 {
 	int file_sample_rate = 8000;
 	if(!m->ms_player)
 		return 0;
-	ms_filter_add_notify_callback(m->ms_player, rms_player_eof, m->si, TRUE);
-	ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_OPEN, (void *)file_name);
+	ms_filter_add_notify_callback(m->ms_player, rms_player_eof, a, TRUE);
+	ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_OPEN, (void *)a->param.s);
 	ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_START, NULL);
 	ms_filter_call_method(m->ms_player, MS_FILTER_GET_SAMPLE_RATE, &file_sample_rate);
 	ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate);

+ 2 - 1
src/modules/rtp_media_server/rms_media.h

@@ -35,6 +35,7 @@
 #include <ortp/port.h>
 
 struct rms_session_info;
+typedef struct rms_action rms_action_t;
 
 typedef struct call_leg_media
 {
@@ -68,7 +69,7 @@ void rms_media_destroy();
 MSFactory *rms_get_factory();
 
 int rms_stop_media(call_leg_media_t *m);
-int rms_playfile(call_leg_media_t *m, char *file_name);
+int rms_playfile(call_leg_media_t *m, rms_action_t *a);
 int rms_start_media(call_leg_media_t *m, char *file_name);
 int rms_bridge(call_leg_media_t *m1, call_leg_media_t *m2);
 int rms_stop_bridge(call_leg_media_t *m1, call_leg_media_t *m2);

+ 133 - 61
src/modules/rtp_media_server/rtp_media_server.c

@@ -47,13 +47,15 @@ static int rms_hangup_f(struct sip_msg *);
 static int rms_sessions_dump_f(struct sip_msg *, char *, char *);
 
 static cmd_export_t cmds[] = {
-		{"rms_answer", (cmd_function)rms_answer_f, 0, 0, 0, ANY_ROUTE},
+		{"rms_answer", (cmd_function)rms_answer_f, 0, 0, 0, EVENT_ROUTE},
 		{"rms_play", (cmd_function)rms_action_play_f, 2, fixup_rms_action_play, 0,
 				ANY_ROUTE},
 		{"rms_sdp_offer", (cmd_function)rms_sdp_offer_f, 0, 0, 0, ANY_ROUTE},
-		{"rms_sdp_answer", (cmd_function)rms_sdp_answer_f, 0, 0, 0, ANY_ROUTE},
-		{"rms_media_stop", (cmd_function)rms_media_stop_f, 0, 0, 0, ANY_ROUTE},
-		{"rms_hangup", (cmd_function)rms_hangup_f, 0, 0, 0, ANY_ROUTE},
+		{"rms_sdp_answer", (cmd_function)rms_sdp_answer_f, 0, 0, 0, REQUEST_ROUTE
+				| FAILURE_ROUTE | ONREPLY_ROUTE},
+		{"rms_media_stop", (cmd_function)rms_media_stop_f, 0, 0, 0, REQUEST_ROUTE
+				| FAILURE_ROUTE | ONREPLY_ROUTE},
+		{"rms_hangup", (cmd_function)rms_hangup_f, 0, 0, 0, EVENT_ROUTE},
 		{"rms_sessions_dump", (cmd_function)rms_sessions_dump_f, 0, 0, 0,
 				ANY_ROUTE},
 		{0, 0, 0, 0, 0, 0}};
@@ -161,6 +163,53 @@ void rms_signal_handler(int signum)
 	LM_INFO("signal received [%d]\n", signum);
 }
 
+static rms_session_info_t* rms_session_action_check(rms_session_info_t *si)
+{
+	rms_action_t *a;
+	clist_foreach(&si->action, a, next)
+	{
+		if(a->type == RMS_HANGUP) {
+			LM_INFO("session action RMS_HANGUP [%s]\n", si->callid.s);
+			rms_hangup_call(si);
+			a->type = RMS_STOP;
+			return si;
+		} else if(a->type == RMS_STOP) {
+			LM_INFO("session action RMS_STOP [%s][%p|%p]\n", si->callid.s, si, si->prev);
+			rms_stop_media(&si->caller_media);
+			rms_session_info_t *tmp = si->prev;
+			clist_rm(si, next, prev);
+			rms_session_free(si);
+			si = tmp;
+			return si;
+		} else if(a->type == RMS_PLAY) {
+			LM_INFO("session action RMS_PLAY [%s]\n", si->callid.s);
+			rms_playfile(&si->caller_media, a);
+			a->type = RMS_NONE;
+		} else if(a->type == RMS_DONE) {
+			LM_INFO("session action RMS_DONE [%s][%s]\n", si->callid.s,
+					a->route.s);
+			if(a->route.s) {
+				run_action_route(si, a->route.s);
+				rms_action_t *tmp = a->prev;
+				clist_rm(a, next, prev);
+				shm_free(a);
+				a = tmp;
+			} else {
+				a->type = RMS_HANGUP;
+			}
+			return si;
+		} else if(a->type == RMS_START) {
+			create_call_leg_media(&si->caller_media);
+			LM_INFO("session action RMS_START [%s]\n", si->callid.s);
+			rms_start_media(&si->caller_media, a->param.s);
+			run_action_route(si, "rms:start");
+			a->type = RMS_NONE;
+			return si;
+		}
+	}
+	return si;
+}
+
 /**
  * Most interaction with the session and media streams that are controlled 
  * 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()
 		rms_session_info_t *si;
 		clist_foreach(rms_session_list, si, next)
 		{
-			if(si->action == RMS_HANGUP) {
-				LM_INFO("session action RMS_HANGUP [%s]\n", si->callid.s);
-				rms_hangup_call(si);
-				si->action = RMS_STOP;
-			} else if(si->action == RMS_STOP) {
-				LM_INFO("session action RMS_STOP [%s]\n", si->callid.s);
-				rms_stop_media(&si->caller_media);
-				rms_session_info_t *tmp = si->prev;
-				clist_rm(si, next, prev);
-				rms_session_free(si);
-				si = tmp;
-			} else if(si->action == RMS_PLAY) {
-				LM_INFO("session action RMS_PLAY [%s]\n", si->callid.s);
-				rms_playfile(&si->caller_media, si->action_param.s);
-				si->action = RMS_NONE;
-			} else if(si->action == RMS_DONE) {
-				LM_INFO("session action RMS_DONE [%s][%s]\n", si->callid.s,
-						si->action_route.s);
-				if(si->action_route.s) {
-					run_action_route(si, si->action_route.s);
-				} else {
-					si->action = RMS_HANGUP;
-				}
-			} else if(si->action == RMS_START) {
-				create_call_leg_media(&si->caller_media);
-				LM_INFO("session action RMS_START [%s]\n", si->callid.s);
-				rms_start_media(&si->caller_media, si->action_param.s);
-				si->action = RMS_NONE;
-				run_action_route(si, "rms:start");
-			}
+			si = rms_session_action_check(si);
 		}
 		unlock(&session_list_mutex);
 		usleep(2000);
@@ -362,20 +382,6 @@ static int rms_answer_call(struct sip_msg *msg, rms_session_info_t *si)
 	return 1;
 }
 
-static rms_session_info_t *rms_session_search(char *callid, int len)
-{
-	// lock(&session_list_mutex);
-	rms_session_info_t *si;
-	clist_foreach(rms_session_list, si, next)
-	{
-		if(strncmp(callid, si->callid.s, len) == 0) {
-			unlock(&session_list_mutex);
-			return si;
-		}
-	}
-	// unlock(&session_list_mutex);
-	return NULL;
-}
 
 static int rms_hangup_call(rms_session_info_t *si)
 {
@@ -421,8 +427,20 @@ static int rms_check_msg(struct sip_msg *msg)
 	return 1;
 }
 
+static void rms_action_free(rms_session_info_t *si)
+{
+	rms_action_t *a, *tmp;
+	clist_foreach(&si->action, a, next) {
+		tmp = a;
+		a = a->prev;
+		clist_rm(tmp, next, prev);
+		shm_free(tmp);
+	}
+}
+
 static int rms_session_free(rms_session_info_t *si)
 {
+	rms_action_free(si);
 	rms_sdp_info_free(&si->sdp_info_offer);
 	rms_sdp_info_free(&si->sdp_info_answer);
 	if(si->caller_media.pt) {
@@ -458,6 +476,14 @@ static int rms_session_free(rms_session_info_t *si)
 	return 1;
 }
 
+rms_action_t *rms_action_new(rms_action_type_t t) {
+	rms_action_t *a = shm_malloc(sizeof(rms_action_t));
+	if (!a) return NULL;
+	memset(a, 0, sizeof(rms_action_t));
+	a->type = t;
+	return a;
+}
+
 rms_session_info_t *rms_session_new(struct sip_msg *msg)
 {
 	struct hdr_field *hdr = NULL;
@@ -502,7 +528,7 @@ rms_session_info_t *rms_session_new(struct sip_msg *msg)
 		tmb.t_reply(msg, 488, "incompatible media format");
 		goto error;
 	}
-
+	clist_init(&si->action, next, prev);
 	return si;
 error:
 	rms_session_free(si);
@@ -552,6 +578,16 @@ static int rms_create_trans(struct sip_msg *msg) {
 	return 1;
 }
 
+static void rms_action_add(rms_session_info_t *si, rms_action_t *a) {
+	clist_append(&si->action, a, next, prev);
+}
+
+static void rms_action_add_sync(rms_session_info_t *si, rms_action_t *a) {
+	lock(&session_list_mutex);
+	rms_action_add(si, a);
+	unlock(&session_list_mutex);
+}
+
 static void rms_session_add(rms_session_info_t *si) {
 	lock(&session_list_mutex);
 	clist_append(rms_session_list, si, next, prev);
@@ -564,6 +600,26 @@ static void rms_session_rm(rms_session_info_t *si) {
 	unlock(&session_list_mutex);
 }
 
+static rms_session_info_t *rms_session_search(char *callid, int len)
+{
+	rms_session_info_t *si;
+	clist_foreach(rms_session_list, si, next)
+	{
+		if(strncmp(callid, si->callid.s, len) == 0) {
+			return si;
+		}
+	}
+	return NULL;
+}
+
+static rms_session_info_t *rms_session_search_sync(char *callid, int len)
+{
+	lock(&session_list_mutex);
+	rms_session_info_t *si = rms_session_search(callid, len);
+	unlock(&session_list_mutex);
+	return si;
+}
+
 static int rms_sdp_offer_f(struct sip_msg *msg, char *param1, char *param2)
 {
 	int status = rms_create_trans(msg);
@@ -595,7 +651,7 @@ static int rms_sdp_answer_f(struct sip_msg *msg, char *param1, char *param2)
 		LM_INFO("no callid ?\n");
 		return -1;
 	}
-	si = rms_session_search(msg->callid->body.s, msg->callid->body.len);
+	si = rms_session_search_sync(msg->callid->body.s, msg->callid->body.len);
 	if(!si) {
 		LM_INFO("session not found ci[%.*s]\n", msg->callid->body.len,
 				msg->callid->body.s);
@@ -642,7 +698,7 @@ static int rms_media_stop_f(struct sip_msg *msg, char *param1, char *param2)
 		LM_ERR("no callid\n");
 		return -1;
 	}
-	si = rms_session_search(msg->callid->body.s, msg->callid->body.len);
+	si = rms_session_search_sync(msg->callid->body.s, msg->callid->body.len);
 	if(!si) {
 		LM_INFO("session not found ci[%.*s]\n", msg->callid->body.len,
 				msg->callid->body.s);
@@ -651,13 +707,24 @@ static int rms_media_stop_f(struct sip_msg *msg, char *param1, char *param2)
 		}
 		return 0;
 	}
-	si->action = RMS_STOP;
+	rms_action_t *a = rms_action_new(RMS_STOP);
+	if(!a) return -1;
+	rms_action_add_sync(si, a);
 	if(!tmb.t_reply(msg, 200, "OK")) {
 		return -1;
 	}
 	return 0;
 }
 
+//static int rms_action_dtmf_f(struct sip_msg *msg, char dtmf, str *route)
+//	rms_session_info_t *si =
+//			rms_session_search(msg->callid->body.s, msg->callid->body.len);
+//	if(!si)
+//		return -1;
+//	rms_playfile();
+//	return 0;
+//}
+
 static int rms_action_play_f(struct sip_msg *msg, str *playback_fn, str *route)
 {
 	rms_session_info_t *si =
@@ -667,11 +734,14 @@ static int rms_action_play_f(struct sip_msg *msg, str *playback_fn, str *route)
 	LM_INFO("RTP session [%s:%d]<>[%s:%d]\n", si->caller_media.local_ip.s,
 			si->caller_media.local_port, si->caller_media.remote_ip.s,
 			si->caller_media.remote_port);
-	si->action = RMS_PLAY;
-	si->action_param.len = playback_fn->len;
-	si->action_param.s = playback_fn->s;
-	si->action_route.len = route->len;
-	si->action_route.s = route->s;
+
+	rms_action_t *a = rms_action_new(RMS_PLAY);
+	if(!a) return -1;
+	a->param.len = playback_fn->len;
+	a->param.s = playback_fn->s;
+	a->route.len = route->len;
+	a->route.s = route->s;
+	rms_action_add(si, a);
 	return 0;
 }
 
@@ -681,12 +751,12 @@ static int rms_hangup_f(struct sip_msg *msg)
 			rms_session_search(msg->callid->body.s, msg->callid->body.len);
 	if(!si)
 		return -1;
-	si->action = RMS_HANGUP;
+	rms_action_t *a = rms_action_new(RMS_HANGUP);
+	if(!a) return -1;
+	rms_action_add(si, a);
 	return 0;
 }
 
-
-
 static int rms_answer_f(struct sip_msg *msg)
 {
 	int status = rms_create_trans(msg);
@@ -707,7 +777,9 @@ static int rms_answer_f(struct sip_msg *msg)
 	LM_INFO("RTP session [%s:%d]<>[%s:%d]\n", si->caller_media.local_ip.s,
 			si->caller_media.local_port, si->caller_media.remote_ip.s,
 			si->caller_media.remote_port);
-	si->action = RMS_START;
+	rms_action_t *a = rms_action_new(RMS_START);
+	if(!a) return -1;
+	rms_action_add(si, a);
 	return 1;
 error:
 	rms_session_rm(si);

+ 11 - 3
src/modules/rtp_media_server/rtp_media_server.h

@@ -58,13 +58,23 @@ typedef struct ms_res
 	RtpProfile *rtp_profile;
 } ms_res_t;
 
-typedef enum rms_action {
+typedef enum rms_action_type
+{
 	RMS_NONE,
 	RMS_START,
 	RMS_STOP,
 	RMS_HANGUP,
 	RMS_PLAY,
 	RMS_DONE,
+} rms_action_type_t;
+
+typedef struct rms_action
+{
+	struct rms_action *next;
+	struct rms_action *prev;
+	str param;
+	str route;
+	rms_action_type_t type;
 } rms_action_t;
 
 typedef struct rms_session_info
@@ -85,8 +95,6 @@ typedef struct rms_session_info
 	call_leg_media_t caller_media;
 	call_leg_media_t callee_media;
 	rms_action_t action;
-	str action_param;
-	str action_route;
 } rms_session_info_t;
 
 #endif

BIN
src/modules/rtp_media_server/voice_file/Bach_10s_8000.wav