rtp_media_server: support for multiple actions 1701/head
authorJulien Chavanton <jchavanton@gmail.com>
Sun, 11 Nov 2018 20:46:10 +0000 (20:46 +0000)
committerJulien Chavanton <jchavanton@gmail.com>
Tue, 13 Nov 2018 08:20:45 +0000 (08:20 +0000)
src/modules/rtp_media_server/config_example/kamailio.cfg
src/modules/rtp_media_server/doc/rtp_media_server_admin.xml
src/modules/rtp_media_server/install_bc.sh
src/modules/rtp_media_server/rms_media.c
src/modules/rtp_media_server/rms_media.h
src/modules/rtp_media_server/rtp_media_server.c
src/modules/rtp_media_server/rtp_media_server.h
src/modules/rtp_media_server/voice_file/Bach_10s_8000.wav [deleted file]

index 6ddb365..7ba6f30 100755 (executable)
@@ -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] {
index adaf1a9..8ce4c97 100644 (file)
@@ -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">
index 02cbaf1..713be1a 100755 (executable)
@@ -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 ..
+
index 747c56c..aa0ab21 100644 (file)
@@ -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);
index cc4499c..d9de594 100644 (file)
@@ -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);
index 538af15..d26f09d 100644 (file)
@@ -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);
index fe83912..594ca25 100644 (file)
@@ -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
diff --git a/src/modules/rtp_media_server/voice_file/Bach_10s_8000.wav b/src/modules/rtp_media_server/voice_file/Bach_10s_8000.wav
deleted file mode 100644 (file)
index f4bbac8..0000000
Binary files a/src/modules/rtp_media_server/voice_file/Bach_10s_8000.wav and /dev/null differ