]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Let's go Camping!
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 22 Oct 2009 22:11:28 +0000 (22:11 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 22 Oct 2009 22:11:28 +0000 (22:11 +0000)
Call Campon (part of bridge app)
Variables:
campon=[true|false]
campon_retries=<number of call attempts>
campon_timeout=<duration of each call attempt>
campon_sleep=<seconds to sleep between retries>
campon_fallback_exten=<extension to transfer to on failure>
campon_fallback_dialplan=<dialplan>
campon_fallback_context=<context>
campon_hold_music=<alternate music>

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15201 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_types.h
src/mod/applications/mod_dptools/mod_dptools.c
src/switch_channel.c
src/switch_ivr_originate.c

index 37fd18c022ea551615841ad5251137c6415397f8..3312ebd497f553f330b600fdb3bac603275be5cc 100644 (file)
@@ -917,6 +917,8 @@ typedef enum {
        CF_XFER_ZOMBIE,
        CF_MEDIA_ACK,
        CF_THREAD_SLEEPING,
+       CF_DISABLE_RINGBACK,
+       CF_NOT_READY,
        /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
        CF_FLAG_MAX
 } switch_channel_flag_t;
index 8aa72bd553ba219b5bd7cad8977acff8df2003a2..3d2791a43b370967c933164cedb9135f776f651a 100644 (file)
@@ -2054,13 +2054,47 @@ SWITCH_STANDARD_APP(stop_record_session_function)
 /*                                                             Bridge Functions                                                                */
 /********************************************************************************/
 
+struct camping_stake {
+       switch_core_session_t *session;
+       int running;
+       const char *moh;
+};
+
+static void *SWITCH_THREAD_FUNC camp_music_thread(switch_thread_t *thread, void *obj)
+{
+       struct camping_stake *stake = (struct camping_stake *) obj;
+       switch_core_session_t *session = stake->session;
+       switch_channel_t *channel = switch_core_session_get_channel(stake->session);
+       const char *moh = stake->moh;
+
+       switch_core_session_read_lock(session);
+       while(stake->running && switch_channel_ready(channel)) {
+               if (!strcasecmp(moh, "silence")) {
+                       switch_ivr_collect_digits_callback(session, NULL, 0, 0);
+               } else {
+                       switch_ivr_play_file(session, NULL, stake->moh, NULL);
+               }
+       }
+       switch_core_session_rwunlock(session);
+
+       return NULL;
+}
+
 SWITCH_STANDARD_APP(audio_bridge_function)
 {
        switch_channel_t *caller_channel = switch_core_session_get_channel(session);
        switch_core_session_t *peer_session = NULL;
-       const char *continue_on_fail = NULL, *failure_causes = NULL;
+       const char *continue_on_fail = NULL, *failure_causes = NULL, 
+               *v_campon = NULL, *v_campon_retries, *v_campon_sleep, *v_campon_timeout, *v_campon_fallback_exten = NULL;
        switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
-
+       int campon_retries = 100, campon_timeout = 10, campon_sleep = 10, tmp, do_xfer = 0, camping = 0, fail = 0, thread_started = 0;
+       struct camping_stake stake = { 0 };
+       const char *moh = NULL;
+       switch_thread_t *thread = NULL;
+       switch_threadattr_t *thd_attr = NULL;
+       char *camp_data = NULL;
+       switch_status_t status;
+       
        if (switch_strlen_zero(data)) {
                return;
        }
@@ -2068,7 +2102,133 @@ SWITCH_STANDARD_APP(audio_bridge_function)
        continue_on_fail = switch_channel_get_variable(caller_channel, "continue_on_fail");
        failure_causes = switch_channel_get_variable(caller_channel, "failure_causes");
 
-       if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE) != SWITCH_STATUS_SUCCESS) {
+       if ((v_campon = switch_channel_get_variable(caller_channel, "campon")) && switch_true(v_campon)) {
+               const char *cid_name = NULL;
+               const char *cid_number = NULL;
+               
+               if (!(cid_name = switch_channel_get_variable(caller_channel, "effective_caller_id_name"))) {
+                       cid_name = switch_channel_get_variable(caller_channel, "caller_id_name");
+               }
+
+               if (!(cid_number = switch_channel_get_variable(caller_channel, "effective_caller_id_number"))) {
+                       cid_number = switch_channel_get_variable(caller_channel, "caller_id_number");
+               }
+
+               if (cid_name && !cid_number) {
+                       cid_number = cid_name;
+               }
+
+               if (cid_number && !cid_name) {
+                       cid_name = cid_number;
+               }
+
+               v_campon_retries = switch_channel_get_variable(caller_channel, "campon_retries");
+               v_campon_timeout = switch_channel_get_variable(caller_channel, "campon_timeout");
+               v_campon_sleep = switch_channel_get_variable(caller_channel, "campon_sleep");
+               v_campon_fallback_exten = switch_channel_get_variable(caller_channel, "campon_fallback_exten");
+               
+               if (v_campon_retries) {
+                       if ((tmp = atoi(v_campon_retries)) > 0) {
+                               campon_retries = tmp;
+                       }
+               }
+
+               if (v_campon_timeout) {
+                       if ((tmp = atoi(v_campon_timeout)) > 0) {
+                               campon_timeout = tmp;
+                       }
+               }
+
+               if (v_campon_sleep) {
+                       if ((tmp = atoi(v_campon_sleep)) > 0) {
+                               campon_sleep = tmp;
+                       }
+               }
+
+               switch_channel_answer(caller_channel);
+               camping = 1;
+
+               if (cid_name && cid_number) {
+                       camp_data = switch_core_session_sprintf(session, "{origination_caller_id_name='%s',origination_caller_id_number='%s'}%s", 
+                                                                                                       cid_name, cid_number, data);
+               } else {
+                       camp_data = (char *)data;
+               }
+
+               if (!(moh = switch_channel_get_variable(caller_channel, "hold_music"))) {
+                       moh = switch_channel_get_variable(caller_channel, "campon_hold_music");
+               }
+
+               do {
+                       fail = 0;
+                       status = switch_ivr_originate(NULL, &peer_session, &cause, camp_data, campon_timeout, NULL, NULL, NULL, NULL, NULL, SOF_NONE);
+                       
+                       if (!switch_channel_ready(caller_channel)) {
+                               fail = 1;
+                               break;
+                       }
+                       
+                       if (status == SWITCH_STATUS_SUCCESS) {
+                               camping = 0;
+                               break;
+                       } else {
+                               fail = 1;
+                       }
+                       
+                       if (camping) {
+                               
+                               if (!thread_started && fail && moh && !switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && 
+                                       !switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) &&
+                                       !switch_true(switch_channel_get_variable(caller_channel, "bypass_media"))) {
+                                       switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
+                                       switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+                                       stake.running = 1;
+                                       stake.moh = moh;
+                                       stake.session = session;
+                                       switch_thread_create(&thread, thd_attr, camp_music_thread, &stake, switch_core_session_get_pool(session));
+                                       thread_started = 1;
+                               }
+
+
+                               if (--campon_retries <= 0) {
+                                       camping = 0;
+                                       do_xfer = 1;
+                                       break;
+                               }
+
+                               if (fail) {
+                                       int64_t wait = campon_sleep * 1000000;
+                                       
+                                       while(wait > 0 && switch_channel_ready(caller_channel)) {
+                                               switch_yield(100000);
+                                               wait -= 100000;
+                                       }
+                               }
+                       }
+               } while (camping);
+               
+               if (thread) {
+                       stake.running = 0;
+                       switch_channel_set_flag(caller_channel, CF_NOT_READY);
+                       switch_thread_join(&status, thread);
+                       switch_channel_clear_flag(caller_channel, CF_NOT_READY);
+               }
+               
+               if (do_xfer && !switch_strlen_zero(v_campon_fallback_exten)) {
+                       switch_ivr_session_transfer(session, 
+                                                                               v_campon_fallback_exten, 
+                                                                               switch_channel_get_variable(caller_channel, "campon_fallback_dialplan"),
+                                                                               switch_channel_get_variable(caller_channel, "campon_fallback_context"));
+                       return;
+               }
+
+       } else {
+               if ((status = switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE)) != SWITCH_STATUS_SUCCESS) {
+                       fail = 1;
+               }
+       }
+
+       if (fail) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed.  Cause: %s\n", switch_channel_cause2str(cause));
 
                /* 
index 7bb78be23f2de5fdf39b7c1c3f0838d9c8be7332..1e2af783d4727a6e6b53226392fe22eaa491d8df 100644 (file)
@@ -1080,7 +1080,7 @@ SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_
        ret = 0;
 
        if (!channel->hangup_cause && channel->state > CS_ROUTING && channel->state < CS_HANGUP && channel->state != CS_RESET &&
-               !switch_channel_test_flag(channel, CF_TRANSFER)) {
+               !switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_NOT_READY)) {
                ret++;
        }
 
index 7407f5d4c8ba970012d2566ea953b1d361d12b8d..2f9cbafbff153f3ac20b7f6481233cd25f42f058 100644 (file)
@@ -395,6 +395,12 @@ static uint8_t check_channel_status(originate_global_t *oglobals, originate_stat
                }
 
                if (switch_channel_test_flag(originate_status[i].peer_channel, CF_EARLY_MEDIA)) {
+                       if (oglobals->ignore_early_media == 2 && len == 1 && caller_channel && !oglobals->ignore_ring_ready) {
+                               switch_channel_pass_callee_id(originate_status[0].peer_channel, caller_channel);
+                               switch_channel_ring_ready(caller_channel);
+                               oglobals->sent_ring = 1;
+                       }
+
                        if (!originate_status[i].early_media) {
                                originate_status[i].early_media = 1;
                                if (oglobals->early_ok) {
@@ -765,6 +771,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t
                        }
                }
                
+               if (switch_channel_test_flag(caller_channel, CF_DISABLE_RINGBACK)) {
+                       ringback_data = NULL;
+               }
+
                if (ringback_data) {
                        char *tmp_data = NULL;
 
@@ -1301,9 +1311,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                *oglobals.file = '\0';
        }
 
-       if ((var_val = switch_event_get_header(var_event, "ignore_early_media")) && switch_true(var_val)) {
-               oglobals.early_ok = 0;
-               oglobals.ignore_early_media = 1;
+       if ((var_val = switch_event_get_header(var_event, "ignore_early_media"))) {
+               if (switch_true(var_val)) {
+                       oglobals.early_ok = 0;
+                       oglobals.ignore_early_media = 1;
+               } else if (!strcmp(var_val, "ring_ready")) {
+                       oglobals.early_ok = 0;
+                       oglobals.ignore_early_media = 2;
+               }
        }
 
        if ((var_val = switch_event_get_header(var_event, "originate_continue_on_timeout")) && switch_true(var_val)) {
@@ -1855,7 +1870,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                endfor1:
 
                        if (caller_channel) {
-                               if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
+                               if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || 
+                                       switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) || switch_channel_test_flag(caller_channel, CF_DISABLE_RINGBACK)) {
                                        ringback_data = NULL;
                                }
                        }