]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
the same guy who added att xfer to asterisk was nice enough to add it to freeswitch too
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 13 Mar 2008 01:08:42 +0000 (01:08 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 13 Mar 2008 01:08:42 +0000 (01:08 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@7885 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_types.h
src/mod/applications/mod_commands/mod_commands.c
src/mod/applications/mod_dptools/mod_dptools.c
src/switch_core_state_machine.c
src/switch_ivr.c
src/switch_ivr_async.c
src/switch_ivr_bridge.c
src/switch_ivr_originate.c
src/switch_ivr_play_say.c
src/switch_rtp.c

index 51a79ee95b85a6f2a2452964a3d2b231ed76ece3..8da6118e4acb2b9211bca85ff3fa78d6835c00d6 100644 (file)
@@ -102,6 +102,9 @@ SWITCH_BEGIN_EXTERN_C
 #define SWITCH_PATH_SEPARATOR "/"
 #endif
 #define SWITCH_URL_SEPARATOR "://"
+#define SWITCH_CALL_TIMEOUT_VARIABLE "call_timeout"
+#define SWITCH_HOLDING_UUID_VARIABLE "holding_uuid"
+#define SWITCH_API_BRIDGE_END_VARIABLE "api_after_bridge"
 #define SWITCH_API_HANGUP_HOOK_VARIABLE "api_hangup_hook"
 #define SWITCH_PROCESS_CDR_VARIABLE "process_cdr"
 #define SWITCH_BRIDGE_CHANNEL_VARIABLE "bridge_channel"
@@ -564,7 +567,8 @@ typedef enum {
        SWITCH_STATUS_MORE_DATA,
        SWITCH_STATUS_NOTFOUND,
        SWITCH_STATUS_UNLOAD,
-       SWITCH_STATUS_NOUNLOAD
+       SWITCH_STATUS_NOUNLOAD,
+       SWITCH_STATUS_IGNORE
 } switch_status_t;
 
 
@@ -717,7 +721,8 @@ typedef enum {
        CF_RESET = (1 << 24),
        CF_ORIGINATING = (1 << 25),
        CF_STOP_BROADCAST = (1 << 26),
-       CF_PROXY_MEDIA = (1 << 27)
+       CF_PROXY_MEDIA = (1 << 27),
+       CF_INNER_BRIDGE = (1 << 28)
 } switch_channel_flag_t;
 
 
index 4b5a5517b8c510cd9f90baecd26ed69e5d59d8d4..e2178fe966f2301c41a878033f33dcf82fb5923d 100644 (file)
@@ -1172,10 +1172,25 @@ SWITCH_STANDARD_API(uuid_bridge_function)
                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
        }
 
-       if (switch_strlen_zero(cmd) || argc != 2) {
+       if (switch_strlen_zero(cmd) || argc < 2) {
                stream->write_function(stream, "-USAGE: %s\n", UUID_SYNTAX);
        } else {
-               if (switch_ivr_uuid_bridge(argv[0], argv[1]) != SWITCH_STATUS_SUCCESS) {
+               switch_status_t status;
+               char *who = NULL;
+               
+               if ((status = switch_ivr_uuid_bridge(argv[0], argv[1])) != SWITCH_STATUS_SUCCESS) {
+                       if (argv[2]) {
+                               if ((status = switch_ivr_uuid_bridge(argv[0], argv[2])) == SWITCH_STATUS_SUCCESS) {
+                                       who = argv[2];
+                               }
+                       } 
+               } else {
+                       who = argv[1];
+               }
+
+               if (status == SWITCH_STATUS_SUCCESS) {
+                       stream->write_function(stream, "+OK %s\n", who);
+               } else {
                        stream->write_function(stream, "-ERR Invalid uuid\n");
                }
        }
index 88763498811100cde97b2429496b841c4dfd5278..cb3fb72f6e0f59c620bce1ef25dcc388eedf7611 100644 (file)
@@ -222,6 +222,8 @@ SWITCH_STANDARD_APP(transfer_function)
                                                switch_ivr_session_transfer(b_session, argv[1], argv[2], argv[3]);
                                                switch_core_session_rwunlock(b_session);
                                        }
+                               } else {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No B-leg present.\n");
                                }
                                if (both) {
                                        switch_ivr_session_transfer(session, argv[1], argv[2], argv[3]);
@@ -1109,6 +1111,146 @@ SWITCH_STANDARD_APP(speak_function)
        switch_ivr_speak_text(session, engine, voice, text, &args);
 }
 
+static switch_status_t xfer_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
+{
+       switch_core_session_t *peer_session = (switch_core_session_t *) buf;
+
+       if (!buf || !peer_session) {
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       switch (itype) {
+       case SWITCH_INPUT_TYPE_DTMF:
+               {                       
+                       switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
+                       switch_channel_t *channel = switch_core_session_get_channel(session);
+                       switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+                       
+                       if (dtmf->digit == '#') {
+                               return SWITCH_STATUS_FALSE;
+                       }
+
+                       if (dtmf->digit == '0') {
+                               switch_caller_extension_t *extension = NULL;
+                               const char *app = "three_way";
+                               const char *app_arg = switch_core_session_get_uuid(session);
+                               const char *holding = switch_channel_get_variable(channel, SWITCH_HOLDING_UUID_VARIABLE);
+                               switch_core_session_t *b_session;
+
+                               if (holding && (b_session = switch_core_session_locate(holding))) {
+                                       switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+                                       if (!switch_channel_ready(b_channel)) {
+                                               app = "intercept";
+                                       }
+                                       switch_core_session_rwunlock(b_session);
+                               }
+                               
+                               if ((extension = switch_caller_extension_new(peer_session, app, app_arg)) == 0) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "memory error!\n");
+                                       abort();
+                               }
+                               
+                               switch_caller_extension_add_application(peer_session, extension, app, app_arg);
+                               switch_channel_set_caller_extension(peer_channel, extension);
+                               switch_channel_set_flag(peer_channel, CF_TRANSFER);
+                               switch_channel_set_state(peer_channel, CS_EXECUTE);
+
+                               return SWITCH_STATUS_FALSE;
+                       }
+                       
+               }
+               break;
+       default:
+               break;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+
+
+}
+
+static switch_status_t hanguphook(switch_core_session_t *session)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_channel_state_t state = switch_channel_get_state(channel);
+       const char *id = NULL;
+
+       if (state == CS_HANGUP || state == CS_RING) {
+               if ((id = switch_channel_get_variable(channel, "xfer_uuids"))) {
+                       switch_stream_handle_t stream = { 0 };
+                       SWITCH_STANDARD_STREAM(stream);
+                       switch_api_execute("uuid_bridge", id, NULL, &stream);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id, switch_str_nil((char *) stream.data));
+                       switch_safe_free(stream.data);
+               }
+               
+               switch_core_event_hook_remove_state_change(session, hanguphook);
+       }
+       return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_APP(att_xfer_function)
+{
+       const char *var;
+       switch_core_session_t *peer_session = NULL;
+       switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+       switch_channel_t *channel, *peer_channel = NULL;
+       const char *bond = NULL;
+       int timelimit = 60;
+
+       channel = switch_core_session_get_channel(session);
+
+       if ((bond = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
+               bond = switch_core_session_strdup(session, bond);
+       }
+
+       switch_channel_set_variable(channel, SWITCH_HOLDING_UUID_VARIABLE, bond);
+       
+       
+       if ((var = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
+               timelimit = atoi(var);
+       }
+
+       if (switch_ivr_originate(session, &peer_session, &cause, data, timelimit, NULL, NULL, NULL, NULL, SOF_NONE) != SWITCH_STATUS_SUCCESS) {
+               return;
+       }
+
+       peer_channel = switch_core_session_get_channel(peer_session);
+       switch_channel_set_flag(peer_channel, CF_INNER_BRIDGE);
+       switch_channel_set_flag(channel, CF_INNER_BRIDGE);
+       
+       switch_ivr_multi_threaded_bridge(session, peer_session, xfer_on_dtmf, peer_session, NULL);
+       
+       if (bond) {
+               switch_core_session_t *b_session;
+               char buf[128] = "";
+
+               if ((b_session = switch_core_session_locate(bond))) {
+                       switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+                       switch_snprintf(buf, sizeof(buf), "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
+                       switch_channel_set_variable(b_channel, "xfer_uuids", buf);
+
+                       switch_snprintf(buf, sizeof(buf), "%s %s", switch_core_session_get_uuid(peer_session), bond);
+                       switch_channel_set_variable(channel, "xfer_uuids", buf);
+                       
+                       switch_core_event_hook_add_state_change(session, hanguphook);
+                       switch_core_event_hook_add_state_change(b_session, hanguphook);
+
+                       switch_core_session_rwunlock(b_session);
+               }
+               
+               switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
+       }
+
+       if (peer_session) {
+               switch_core_session_rwunlock(peer_session);
+       }
+       
+       switch_channel_set_variable(channel, SWITCH_HOLDING_UUID_VARIABLE, NULL);
+
+}
+
+
 
 SWITCH_STANDARD_APP(read_function)
 {
@@ -1126,7 +1268,7 @@ SWITCH_STANDARD_APP(read_function)
        if (!switch_strlen_zero(data) && (mydata = switch_core_session_strdup(session, data))) {
                argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
        } else {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No file specified.\n");                
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No arguements specified.\n");          
                return;
        }
 
@@ -1347,7 +1489,7 @@ SWITCH_STANDARD_APP(audio_bridge_function)
                return;
        }
 
-       if ((var = switch_channel_get_variable(caller_channel, "call_timeout"))) {
+       if ((var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
                timelimit = atoi(var);
        }
 
@@ -1516,13 +1658,13 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
 
                if (session) {
                        channel = switch_core_session_get_channel(session);
-                       if ((var = switch_channel_get_variable(channel, "call_timeout"))) {
+                       if ((var = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
                                timelimit = atoi(var);
                        }
                        
                        switch_channel_set_variable(channel, "dialed_user", user);
                        switch_channel_set_variable(channel, "dialed_domain", domain);
-
+                       
                        d_dest = switch_channel_expand_variables(channel, dest);
 
                } else {
@@ -1650,7 +1792,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
        SWITCH_ADD_APP(app_interface, "sched_broadcast", SCHED_BROADCAST_DESCR, SCHED_BROADCAST_DESCR, sched_broadcast_function, "[+]<time> <path> [aleg|bleg|both]", SAF_SUPPORT_NOMEDIA);
        SWITCH_ADD_APP(app_interface, "sched_transfer", SCHED_TRANSF_DESCR, SCHED_TRANSF_DESCR, sched_transfer_function, "[+]<time> <extension> <dialplan> <context>", SAF_SUPPORT_NOMEDIA);
        SWITCH_ADD_APP(app_interface, "execute_extension", "Execute an extension", "Execute an extension", exe_function, EXE_SYNTAX, SAF_SUPPORT_NOMEDIA);
-       SWITCH_ADD_APP(app_interface, "bind_meta_app", "Bind a key to an application", "Bind a key to an application", dtmf_bind_function, BIND_SYNTAX, SAF_NONE);
+       SWITCH_ADD_APP(app_interface, "bind_meta_app", "Bind a key to an application", "Bind a key to an application", dtmf_bind_function, BIND_SYNTAX, SAF_SUPPORT_NOMEDIA);
        SWITCH_ADD_APP(app_interface, "intercept", "intercept", "intercept", intercept_function, INTERCEPT_SYNTAX, SAF_NONE);
        SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_NONE);
        SWITCH_ADD_APP(app_interface, "three_way", "three way call with a uuid", "three way call with a uuid", three_way_function, eavesdrop_SYNTAX, SAF_NONE);
@@ -1668,6 +1810,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
        SWITCH_ADD_APP(app_interface, "park_state", "Park State", "Park State", park_state_function, "", SAF_NONE);
        SWITCH_ADD_APP(app_interface, "gentones", "Generate Tones", "Generate tones to the channel", gentones_function, "<tgml_script>[|<loops>]", SAF_NONE);
        SWITCH_ADD_APP(app_interface, "playback", "Playback File", "Playback a file to the channel", playback_function, "<path>", SAF_NONE);
+       SWITCH_ADD_APP(app_interface, "att_xfer", "Read Digits", "Read Digits", att_xfer_function, "foo>", SAF_NONE);
        SWITCH_ADD_APP(app_interface, "read", "Read Digits", "Read Digits", read_function, "<min> <max> <file> <var name> <timeout> <terminators>", SAF_NONE);
        SWITCH_ADD_APP(app_interface, "stop_record_session", "Stop Record Session", STOP_SESS_REC_DESC, stop_record_session_function, "<path>", SAF_NONE);
        SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, "<path>", SAF_NONE);
index 4a81c8b1a24a22e1f75eddefdb32243a4c5392b4..dbf6accc3efe04cd5db53e8d49acd3ba17aa7c2f 100644 (file)
@@ -412,7 +412,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
                        case CS_HANGUP:     /* Deactivate and end the thread */
                                {
                                        const char *var = switch_channel_get_variable(session->channel, SWITCH_PROCESS_CDR_VARIABLE);
-                                       const char *hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE);
+                                       const char *hook_var;
 
                                        if (!switch_strlen_zero(var)) {
                                                if (!strcasecmp(var, "a_only")) {
@@ -431,6 +431,8 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
                                        STATE_MACRO(hangup, "HANGUP");
                                        switch_core_session_signal_unlock(session);
 
+                                       hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE);
+
                                        if (!switch_strlen_zero(hook_var)) {
                                                switch_stream_handle_t stream = { 0 };
                                                char *cmd = switch_core_session_strdup(session, hook_var);
@@ -439,7 +441,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
                                                        *arg++ = '\0';
                                                }
                                                SWITCH_STANDARD_STREAM(stream);
-                                               switch_api_execute(cmd, arg, session, &stream);
+                                               switch_api_execute(cmd, arg, NULL, &stream);
                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Hangup Command %s(%s):\n%s\n", cmd, arg, switch_str_nil((char *) stream.data));
                                                switch_safe_free(stream.data);
                                        }
index 1321c352c9e01ffdd31bb1afdb2f1c3588170efe..e9ca021425e16fc418948179376d6ea543ef436c 100644 (file)
@@ -310,6 +310,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se
                                        if (hold_bleg && switch_true(hold_bleg)) {
                                                if ((b_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
                                                        const char *stream;
+                                                       b_uuid = switch_core_session_strdup(session, b_uuid);
 
                                                        if (!(stream = switch_channel_get_variable_partner(channel, SWITCH_HOLD_MUSIC_VARIABLE))) {
                                                                stream = switch_channel_get_variable(channel, SWITCH_HOLD_MUSIC_VARIABLE);
@@ -318,7 +319,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se
                                                        if (stream) {
                                                                if ((b_session = switch_core_session_locate(b_uuid))) {
                                                                        switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
-
                                                                        switch_ivr_broadcast(b_uuid, stream, SMF_ECHO_ALEG | SMF_LOOP);
                                                                        switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_TRUE, 5000);
                                                                        switch_core_session_rwunlock(b_session);
@@ -336,6 +336,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se
                                                        break;
                                                }
                                        }
+
                                        if (b_uuid) {
                                                if ((b_session = switch_core_session_locate(b_uuid))) {
                                                        switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
@@ -344,6 +345,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se
                                                        switch_core_session_rwunlock(b_session);
                                                }
                                        }
+
                                        switch_channel_clear_flag(channel, CF_BROADCAST);                                       
                                }
                        }
index 4a46f2ed70adeced76eec16f0b84118bac5eb905..b6537f73b4428dcd14936c84b9b7a702aa020841 100644 (file)
@@ -1277,8 +1277,8 @@ static switch_status_t meta_on_dtmf(switch_core_session_t *session, const switch
        time_t now = switch_timestamp(NULL);
        char digit[2] = "";
        int dval;
-
-       if (!md) {
+       
+       if (!md || switch_channel_test_flag(channel, CF_INNER_BRIDGE)) {
                return SWITCH_STATUS_SUCCESS;
        }
 
index f52e164d09fec40857355aa66cfde90cb2c98bcf..9ad7b9d9269c450262b1494e68e42327891ac7a5 100644 (file)
@@ -98,6 +98,8 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
        switch_core_session_t *session_a, *session_b;
        uint32_t loop_count = 0;
        const char *app_name = NULL, *app_arg = NULL;
+       const char *hook_var = NULL;
+       int nosuspend  = 0;
 #ifdef SWITCH_VIDEO_IN_THREADS
     struct vid_helper vh = { 0 };
        uint32_t vid_launch = 0;
@@ -122,7 +124,9 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
        }
 
        switch_channel_set_flag(chan_a, CF_BRIDGED);
-
+       
+       nosuspend = switch_channel_test_flag(chan_a, CF_INNER_BRIDGE);
+       
        for (;;) {
                switch_channel_state_t b_state;
                switch_status_t status;
@@ -130,17 +134,17 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
                loop_count++;
 
                if (!switch_channel_ready(chan_a)) {
-                       break;
+                       goto end_of_bridge_loop;
                }
 
                if ((b_state = switch_channel_get_state(chan_b)) >= CS_HANGUP) {
-                       break;
+                       goto end_of_bridge_loop;
                }
 
                if (switch_channel_test_flag(chan_a, CF_TRANSFER) || switch_channel_test_flag(chan_b, CF_TRANSFER)) {
                        switch_channel_clear_flag(chan_a, CF_HOLD);
                        switch_channel_clear_flag(chan_a, CF_SUSPEND);
-                       break;
+                       goto end_of_bridge_loop;
                }
 
                if (loop_count > 50 && switch_core_session_private_event_count(session_a)) {
@@ -155,8 +159,8 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
                        switch_channel_clear_flag(chan_b, CF_SUSPEND);
                }
                
-               if (switch_channel_test_flag(chan_a, CF_SUSPEND) || switch_channel_test_flag(chan_b, CF_SUSPEND)) {
-                       switch_yield(1000);
+               if (!nosuspend && (switch_channel_test_flag(chan_a, CF_SUSPEND) || switch_channel_test_flag(chan_b, CF_SUSPEND))) {
+                       switch_yield(10000);
                        continue;
                }
 
@@ -173,16 +177,23 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
                while (switch_channel_has_dtmf(chan_a)) {
                        switch_dtmf_t dtmf = { 0, 0 };
                        if (switch_channel_dequeue_dtmf(chan_a, &dtmf) == SWITCH_STATUS_SUCCESS) {
+                               int send_dtmf = 1;
+                               
                                if (input_callback) {
-                                       if (input_callback(session_a, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
+                                       switch_status_t cb_status = input_callback(session_a, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0);
+                                       
+                                       if (cb_status == SWITCH_STATUS_IGNORE) {
+                                               send_dtmf = 0;
+                                       } if (cb_status != SWITCH_STATUS_SUCCESS) {
                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
                                                switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
-                                               break;
+                                               goto end_of_bridge_loop;
                                        }
                                }
                                
-
-                               switch_core_session_send_dtmf(session_b, &dtmf);
+                               if (send_dtmf) {
+                                       switch_core_session_send_dtmf(session_b, &dtmf);
+                               }
                        }
                }
 
@@ -211,13 +222,13 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
                        if (!ans_b && switch_channel_test_flag(chan_b, CF_ANSWERED)) {
                                if (switch_channel_answer(chan_a) != SWITCH_STATUS_SUCCESS) {
                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n", switch_channel_get_name(chan_a));
-                                       break;
+                                       goto end_of_bridge_loop;
                                }
                                ans_a++;
                        } else if (!pre_b && switch_channel_test_flag(chan_b, CF_EARLY_MEDIA)) {
                                if (switch_channel_pre_answer(chan_a) != SWITCH_STATUS_SUCCESS) {
                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n", switch_channel_get_name(chan_a));
-                                       break;
+                                       goto end_of_bridge_loop;
                                }
                                pre_b++;
                        }
@@ -233,7 +244,7 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
                        status = switch_core_session_read_video_frame(session_a, &read_frame, -1, 0);
                
                        if (!SWITCH_READ_ACCEPTABLE(status)) {
-                               break;
+                               goto end_of_bridge_loop;
                        }
                
                        switch_core_session_write_video_frame(session_b, read_frame, -1, 0);
@@ -252,15 +263,18 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
                                if (switch_core_session_write_frame(session_b, read_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "write: %s Bad Frame....[%u] Bubye!\n",
                                                                          switch_channel_get_name(chan_b), read_frame->datalen);
-                                       break;
+                                       goto end_of_bridge_loop;
                                }
                        }
                } else {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "read: %s Bad Frame.... Bubye!\n", switch_channel_get_name(chan_a));
-                       break;
+                       goto end_of_bridge_loop;
                }
        }
 
+ end_of_bridge_loop:
+
+
 #ifdef SWITCH_VIDEO_IN_THREADS
     if (vh.up) {
         vh.up = -1;
@@ -271,7 +285,24 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
     }
 #endif
 
+       if (!nosuspend) {
+               hook_var = switch_channel_get_variable(chan_a, SWITCH_API_BRIDGE_END_VARIABLE);
+       }
 
+       if (!switch_strlen_zero(hook_var)) {
+               switch_stream_handle_t stream = { 0 };
+               char *cmd = switch_core_session_strdup(session_a, hook_var);
+               char *arg = NULL;
+               if ((arg = strchr(cmd, ' '))) {
+                       *arg++ = '\0';
+               }
+               SWITCH_STANDARD_STREAM(stream);
+               switch_api_execute(cmd, arg, NULL, &stream);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\nPost-Bridge Command %s(%s):\n%s\n", cmd, arg, switch_str_nil((char *) stream.data));
+               switch_safe_free(stream.data);
+       }
+       
+       
        if (switch_channel_get_state(chan_b) >= CS_HANGUP) {    
                if (originator && switch_channel_ready(chan_a) && !switch_channel_test_flag(chan_a, CF_ANSWERED)) {
                        switch_channel_hangup(chan_a, switch_channel_get_cause(chan_b));
@@ -282,8 +313,8 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
        msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
        msg.from = __FILE__;
        switch_core_session_receive_message(session_a, &msg);
-
-       if (switch_channel_get_state(chan_a) < CS_HANGUP) {
+       
+       if (!nosuspend && switch_channel_get_state(chan_a) < CS_HANGUP) {
                if ((app_name = switch_channel_get_variable(chan_a, SWITCH_EXEC_AFTER_BRIDGE_APP_VARIABLE))) {
                        switch_caller_extension_t *extension = NULL;
                        if ((extension = switch_caller_extension_new(session_a, app_name, app_name)) == 0) {
@@ -412,12 +443,18 @@ static switch_status_t uuid_bridge_on_transmit(switch_core_session_t *session)
 
                switch_channel_wait_for_state(channel, other_channel, CS_RESET);
 
+               if (switch_ivr_wait_for_answer(session, other_session) != SWITCH_STATUS_SUCCESS) {
+                       switch_core_session_rwunlock(other_session);
+                       switch_channel_hangup(channel, SWITCH_CAUSE_ORIGINATOR_CANCEL);
+                       return SWITCH_STATUS_FALSE;
+               }
+
                if (switch_channel_get_state(other_channel) == CS_RESET) {
                        switch_channel_set_state(other_channel, CS_TRANSMIT);
                }
 
                switch_channel_wait_for_state(channel, other_channel, CS_TRANSMIT);
-               
+
                switch_channel_clear_flag(channel, CF_TRANSFER);
                switch_channel_clear_flag(other_channel, CF_TRANSFER);
                switch_core_session_reset(session, SWITCH_TRUE);
@@ -743,6 +780,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
 
   done:
 
+       switch_channel_clear_flag(caller_channel, CF_INNER_BRIDGE);
+       switch_channel_clear_flag(peer_channel, CF_INNER_BRIDGE);
+
        if (br && switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
                switch_channel_event_set_data(caller_channel, event);
                switch_event_fire(&event);
@@ -773,6 +813,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
                        originator_channel = switch_core_session_get_channel(originator_session);
                        originatee_channel = switch_core_session_get_channel(originatee_session);
 
+                       if (switch_channel_get_state(originator_channel) >= CS_HANGUP) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s is hungup refusing to bridge.\n", switch_channel_get_name(originatee_channel));
+                               switch_core_session_rwunlock(originator_session);
+                               switch_core_session_rwunlock(originatee_session);
+                               return SWITCH_STATUS_FALSE;
+                       }
+
                        if (!switch_channel_test_flag(originator_channel, CF_ANSWERED)) {
                                if (switch_channel_test_flag(originatee_channel, CF_ANSWERED)) {
                                        swap_session = originator_session;
@@ -861,10 +908,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
 
                } else {
                        switch_core_session_rwunlock(originator_session);
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "no channel for originatee uuid %s\n", originatee_uuid);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "originatee uuid %s is not present\n", originatee_uuid);
                }
        } else {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "no channel for originator uuid %s\n", originator_uuid);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "originator uuid %s is not present\n", originator_uuid);
        }
 
        return status;
index 1a017b47eaed9e7ab698d716c7638adb10aba866..ffe0181c5cdb86336da0a4378f2971c3a929b71c 100644 (file)
@@ -367,7 +367,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t
                }
        }
 
-       while (!(switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) {
+       while (switch_channel_ready(peer_channel) && !(switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) {
                int diff = (int)(switch_timestamp_now() - start);
                
                if (diff > timelimit) {
@@ -1120,6 +1120,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                                }
 
                                if (i != idx) {
+                                       const char *holding = NULL;
+                                       
                                        if (idx == IDX_CANCEL) {
                                                if (to) {
                                                        reason = SWITCH_CAUSE_NO_ANSWER;
@@ -1135,9 +1137,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                                                        reason = SWITCH_CAUSE_NO_ANSWER;
                                                }
                                        }
-
-
-                                       switch_channel_hangup(peer_channels[i], reason);
+                                       
+                                       if (caller_channel && i == 0) {
+                                               holding = switch_channel_get_variable(caller_channel, SWITCH_HOLDING_UUID_VARIABLE);
+                                               holding = switch_core_session_strdup(session, holding);
+                                               switch_channel_set_variable(caller_channel, SWITCH_HOLDING_UUID_VARIABLE, NULL);
+                                       }
+                                       if (holding) {
+                                               switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(peer_sessions[i]));
+                                       } else {
+                                               switch_channel_hangup(peer_channels[i], reason);
+                                       }
                                }
                        }
 
index 6189da51a70505e223f05bf0ebd5648f29755881..7e637acada58caaefcc72b27df1014f25bc6db0d 100644 (file)
@@ -1126,15 +1126,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_read(switch_core_session_t *session,
        args.buf = digit_buffer;
        args.buflen = digit_buffer_length;
 
-       if (!switch_strlen_zero(prompt_audio_file)) {
+       if (!switch_strlen_zero(prompt_audio_file) && strcasecmp(prompt_audio_file, "silence")) {
                status = switch_ivr_play_file(session, NULL, prompt_audio_file, &args);
        }
-
+       
        if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
                goto end;
        }
 
        len = strlen(digit_buffer);
+       
 
        if (len < min_digits && len < max_digits) {
                args.buf = digit_buffer + len;
@@ -1142,7 +1143,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_read(switch_core_session_t *session,
                status = switch_ivr_collect_digits_count(session, digit_buffer, digit_buffer_length, max_digits, valid_terminators, &terminator, timeout, 0, 0);
        }
 
-
+       
  end:
 
        if (var_name && !switch_strlen_zero(digit_buffer)) {
index b98bfb5223c2a5096b56a6796f05f3027ed75968..748a331731f510224113f1fca943aff6388338d9 100644 (file)
@@ -1143,8 +1143,18 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                                switch_core_timer_sync(&rtp_session->timer);
                        } else {
                                check = (uint8_t) (switch_core_timer_check(&rtp_session->timer, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS);                                         
+                               if (check && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTO_CNG) &&
+                                       rtp_session->timer.samplecount >= (rtp_session->last_write_samplecount + (rtp_session->samples_per_interval * 50))) {
+                                       uint8_t data[10] = { 0 };
+                                       switch_frame_flag_t frame_flags = SFF_NONE;
+                                       data[0] = 65;
+                                       rtp_session->cn++;
+                                       rtp_common_write(rtp_session, NULL, (void *) data, 2, rtp_session->cng_pt, 0, &frame_flags);
+                               }
                        }
-               } 
+               } else if (bytes) {
+                       check++;
+               }
 
                if (check) {
                        do_2833(rtp_session);
@@ -1295,19 +1305,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                        goto end;
                }
 
-               if (rtp_session->timer.interval) {
-                       if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTO_CNG) &&
-                               rtp_session->timer.samplecount >= (rtp_session->last_write_samplecount + (rtp_session->samples_per_interval * 50))) {
-                               uint8_t data[10] = { 0 };
-                               switch_frame_flag_t frame_flags = SFF_NONE;
-                               data[0] = 65;
-                               rtp_session->cn++;
-                               switch_mutex_lock(rtp_session->flag_mutex);
-                               rtp_common_write(rtp_session, NULL, (void *) data, 2, rtp_session->cng_pt, 0, &frame_flags);
-                               switch_mutex_unlock(rtp_session->flag_mutex);
-                       }
-               }
-
                if (check || (bytes && !rtp_session->timer.interval)) {
                        if (!bytes && rtp_session->max_missed_packets) {
                                if (++rtp_session->missed_count >= rtp_session->max_missed_packets) {