From a035ec592cd2718c0c4a019dc94d07045e2dc05b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 12 Jun 2007 21:35:37 +0000 Subject: [PATCH] doh git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5317 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- .../mod_bridgecall/mod_bridgecall.c | 90 +++++++++++++++++++ .../mod_spidermonkey/mod_spidermonkey.c | 2 + 2 files changed, 92 insertions(+) diff --git a/src/mod/applications/mod_bridgecall/mod_bridgecall.c b/src/mod/applications/mod_bridgecall/mod_bridgecall.c index dc455bcc93..884bbb7ec3 100644 --- a/src/mod/applications/mod_bridgecall/mod_bridgecall.c +++ b/src/mod/applications/mod_bridgecall/mod_bridgecall.c @@ -36,8 +36,98 @@ static const char modname[] = "mod_bridgecall"; +static void audio_bridge_function(switch_core_session_t *session, char *data) +{ + switch_channel_t *caller_channel; + switch_core_session_t *peer_session = NULL; + unsigned int timelimit = 60; + char *var; + uint8_t no_media_bridge = 0; + switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; + uint8_t do_continue = 0; + if (switch_strlen_zero(data)) { + return; + } + caller_channel = switch_core_session_get_channel(session); + assert(caller_channel != NULL); + + if ((var = switch_channel_get_variable(caller_channel, "call_timeout"))) { + timelimit = atoi(var); + } + + if ((var = switch_channel_get_variable(caller_channel, "continue_on_fail"))) { + do_continue = switch_true(var); + } + + if (switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA) + || ((var = switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_VARIABLE)) && switch_true(var))) { + if (!switch_channel_test_flag(caller_channel, CF_ANSWERED) + && !switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) { + switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel is already up, delaying point-to-point mode 'till both legs are up.\n"); + no_media_bridge = 1; + } + } + + if (switch_ivr_originate(session, &peer_session, &cause, data, timelimit, NULL, NULL, NULL, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Originate Failed. Cause: %s\n", switch_channel_cause2str(cause)); + if (!do_continue && cause != SWITCH_CAUSE_NO_ANSWER) { + /* All Causes besides NO_ANSWER terminate the originating session unless continue_on_fail is set. + We will pass the fail cause on when we hangup. */ + switch_channel_hangup(caller_channel, cause); + } + /* Otherwise.. nobody answered. Go back to the dialplan instructions in case there was more to do. */ + return; + } else { + if (no_media_bridge) { + switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session); + switch_frame_t *read_frame; + /* SIP won't let us redir media until the call has been answered #$^#%& so we will proxy any early media until they do */ + while (switch_channel_ready(caller_channel) && switch_channel_ready(peer_channel) + && !switch_channel_test_flag(peer_channel, CF_ANSWERED)) { + switch_status_t status = switch_core_session_read_frame(peer_session, &read_frame, -1, 0); + uint8_t bad = 1; + + if (SWITCH_READ_ACCEPTABLE(status) + && switch_core_session_write_frame(session, read_frame, -1, 0) == SWITCH_STATUS_SUCCESS) { + bad = 0; + } + if (bad) { + switch_channel_hangup(caller_channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_channel_hangup(peer_channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + goto end; + } + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Redirecting media to point-to-point mode.\n"); + switch_ivr_nomedia(switch_core_session_get_uuid(session), SMF_FORCE); + switch_ivr_nomedia(switch_core_session_get_uuid(peer_session), SMF_FORCE); + switch_ivr_signal_bridge(session, peer_session); + } else { + if (switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA)) { + switch_ivr_signal_bridge(session, peer_session); + } else { + switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL); + } + } + end: + if (peer_session) { + switch_core_session_rwunlock(peer_session); + } + } +} + +static const switch_application_interface_t bridge_application_interface = { + /*.interface_name */ "bridge", + /*.application_function */ audio_bridge_function, + /* long_desc */ "Bridge the audio between two sessions", + /* short_desc */ "Bridge Audio", + /* syntax */ "", + /* flags */ SAF_SUPPORT_NOMEDIA +}; static const switch_loadable_module_interface_t mod_bridgecall_module_interface = { /*.module_name = */ modname, diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c index 3c86948900..ec27254ccd 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c @@ -2392,6 +2392,8 @@ static void session_destroy(JSContext * cx, JSObject * obj) switch_channel_set_private(channel, "jss", NULL); } + switch_core_event_hook_remove_state_change(jss->session, hanguphook); + if (channel && switch_test_flag(jss, S_HUP)) { switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); }