From a29d426c8cbb4143b947589e34c5df46180050c8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 15 Aug 2006 19:38:14 +0000 Subject: [PATCH] setting waypoint git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2300 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_ivr.h | 10 +++ src/switch_ivr.c | 141 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index b04703e581..b7ae95afd8 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -164,6 +164,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses void *buf, unsigned int buflen); +/*! + \brief Make an outgoing call + \param session originating session + \param bleg B leg session + \param bridgeto the desired remote callstring + \return SWITCH_STATUS_SUCCESS if bleg is a running session. +*/ +SWITCH_DECLARE(switch_status_t) switch_ivr_outcall(switch_core_session_t *session, + switch_core_session_t **bleg, + char *bridgeto); /*! \brief Bridge Audio from one session to another diff --git a/src/switch_ivr.c b/src/switch_ivr.c index af427eade6..d1bc775846 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -1141,6 +1141,147 @@ static const switch_state_handler_table_t audio_bridge_peer_state_handlers = { }; + +SWITCH_DECLARE(switch_status_t) switch_ivr_outcall(switch_core_session_t *session, + switch_core_session_t **bleg, + char *bridgeto) + +{ + switch_core_session_t *peer_session; + switch_caller_profile_t *caller_profile, *caller_caller_profile; + char *chan_type, *chan_data; + unsigned int timelimit = 60; + switch_channel_t *peer_channel; + time_t start; + switch_frame_t *read_frame = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_channel_t *caller_channel = NULL; + + *bleg = NULL; + chan_type = strdup(bridgeto); + + if ((chan_data = strchr(chan_type, '/')) != 0) { + *chan_data = '\0'; + chan_data++; + } + + if (session) { + caller_channel = switch_core_session_get_channel(session); + assert(caller_channel != NULL); + caller_caller_profile = switch_channel_get_caller_profile(caller_channel); + + + caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), + caller_caller_profile->username, + caller_caller_profile->dialplan, + caller_caller_profile->caller_id_name, + caller_caller_profile->caller_id_number, + caller_caller_profile->network_addr, + NULL, + NULL, + caller_caller_profile->rdnis, + caller_caller_profile->source, + caller_caller_profile->context, + chan_data); + } else { + + caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), + NULL, + NULL, + "FreeSWITCH", + "0000000000", + NULL, + NULL, + NULL, + NULL, + __FILE__, + NULL, + chan_data); + } + + + + if (switch_core_session_outgoing_channel(session, chan_type, caller_profile, &peer_session, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Create Outgoing Channel!\n"); + status = SWITCH_STATUS_FALSE; + goto done; + } + + peer_channel = switch_core_session_get_channel(peer_session); + assert(peer_channel != NULL); + + switch_channel_add_state_handler(peer_channel, &audio_bridge_peer_state_handlers); + + if (switch_core_session_runing(peer_session)) { + switch_channel_set_state(peer_channel, CS_RING); + } else { + switch_core_session_thread_launch(peer_session); + } + + time(&start); + + for (;;) { + int state = switch_channel_get_state(peer_channel); + if (state >= CS_RING) { + break; + } + + if (caller_channel && !switch_channel_ready(caller_channel)) { + break; + } + + if ((time(NULL) - start) > (time_t)timelimit) { + break; + } + switch_yield(1000); + } + + if (caller_channel) { + switch_channel_pre_answer(caller_channel); + } + + while ((!caller_channel || switch_channel_ready(caller_channel)) && + !switch_channel_test_flag(peer_channel, CF_ANSWERED) && + !switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) && + ((time(NULL) - start) < (time_t)timelimit)) { + + /* read from the channel while we wait if the audio is up on it */ + if (session && (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA))) { + switch_status_t status = switch_core_session_read_frame(session, &read_frame, 1000, 0); + + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + if (read_frame) { + if (switch_core_session_write_frame(session, read_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) { + break; + } + } + + } else { + switch_yield(1000); + } + + } + + if (caller_channel && switch_channel_test_flag(peer_channel, CF_ANSWERED)) { + switch_channel_answer(caller_channel); + } + + if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) { + *bleg = peer_session; + status = SWITCH_STATUS_SUCCESS; + } else { + switch_channel_hangup(peer_channel, SWITCH_CAUSE_NO_ANSWER); + status = SWITCH_STATUS_FALSE; + } + + done: + free(chan_type); + return status; +} + + SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_session_t *session, switch_core_session_t *peer_session, unsigned int timelimit,