Let's go Camping!

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
This commit is contained in:
Anthony Minessale 2009-10-22 22:11:28 +00:00
parent f9df2e6bd8
commit e072a6095d
4 changed files with 186 additions and 8 deletions

View 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;

View 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));
/*

View 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++;
}

View 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;
}
}