diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 4f99cb6e2e..61019a2d56 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -538,7 +538,7 @@ CF_EARLY_MEDIA = (1 << 2) - Channel is ready for audio before answer CF_ORIGINATOR = (1 << 3) - Channel is an originator CF_TRANSFER = (1 << 4) - Channel is being transfered CF_ACCEPT_CNG = (1 << 5) - Channel will accept CNG frames -CF_LOCK_THREAD = (1 << 6) - Prevent the channel thread from exiting while this flag is set +CF_WAIT_FOR_ME = (1 << 6) - Channel wants you to wait CF_BRIDGED = (1 << 7) - Channel in a bridge CF_HOLD = (1 << 8) - Channel is on hold CF_SERVICE = (1 << 9) - Channel has a service thread @@ -565,7 +565,7 @@ typedef enum { CF_ORIGINATOR = (1 << 3), CF_TRANSFER = (1 << 4), CF_ACCEPT_CNG = (1 << 5), - CF_LOCK_THREAD = (1 << 6), + CF_WAIT_FOR_ME = (1 << 6), CF_BRIDGED = (1 << 7), CF_HOLD = (1 << 8), CF_SERVICE = (1 << 9), diff --git a/src/switch_ivr.c b/src/switch_ivr.c index b32c365eaf..b76b8a2ccb 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -272,13 +272,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se unsigned long CMD_NOMEDIA = switch_hashfunc_default("nomedia", &hlen); unsigned long CMD_UNICAST = switch_hashfunc_default("unicast", &hlen); char *lead_frames = switch_event_get_header(event, "lead-frames"); - + switch_status_t status = SWITCH_STATUS_SUCCESS; + assert(channel != NULL); assert(event != NULL); if (switch_strlen_zero(cmd)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Command!\n"); - return SWITCH_STATUS_FALSE; + status = SWITCH_STATUS_FALSE; + goto done; } hlen = (switch_size_t) strlen(cmd); @@ -289,12 +291,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se if (lead_frames) { switch_frame_t *read_frame; int frame_count = atoi(lead_frames); - switch_status_t status; - + while(frame_count > 0) { status = switch_core_session_read_frame(session, &read_frame, -1, 0); if (!SWITCH_READ_ACCEPTABLE(status)) { - return status; + goto done; } if (!switch_test_flag(read_frame, SFF_CNG)) { frame_count--; @@ -365,12 +366,33 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se switch_channel_hangup(channel, cause); } else if (cmd_hash == CMD_NOMEDIA) { char *uuid = switch_event_get_header(event, "nomedia-uuid"); + char *waitfor = switch_event_get_header(event, "wait-for"); + if (waitfor) { + switch_core_session_t *w_session; + + if ((w_session = switch_core_session_locate(waitfor))) { + switch_channel_t *w_channel = switch_core_session_get_channel(w_session); + int sanity = 0; + + while(switch_channel_test_flag(w_channel, CF_WAIT_FOR_ME)) { + switch_yield(1000); + if (++sanity > 10000) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Timeout waiting for channel %s\n", switch_channel_get_name(w_channel)); + switch_channel_clear_flag(w_channel, CF_WAIT_FOR_ME); + break; + } + } + switch_core_session_rwunlock(w_session); + } + + } switch_ivr_nomedia(uuid, SMF_REBRIDGE); } - + done: switch_channel_clear_flag(channel, CF_EVENT_PARSE); - return SWITCH_STATUS_SUCCESS; + switch_channel_clear_flag(channel, CF_WAIT_FOR_ME); + return status; } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index b787e312bf..b19df277d7 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -775,10 +775,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, swi char *p; master = session; - + channel = switch_core_session_get_channel(session); assert(channel != NULL); - + if ((nomedia = switch_channel_test_flag(channel, CF_BYPASS_MEDIA))) { switch_ivr_media(uuid, SMF_REBRIDGE); } @@ -796,8 +796,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, swi } } - if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) + if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(other_uuid))) { + if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-name", "%s", app); @@ -806,12 +807,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, swi if ((flags & SMF_LOOP)) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1); } - switch_core_session_queue_private_event(other_session, &event); } - switch_core_session_rwunlock(other_session); + master = other_session; + switch_core_session_rwunlock(other_session); + other_session = NULL; } @@ -833,6 +835,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, swi if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-command", "nomedia"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "nomedia-uuid", "%s", uuid); + if ((flags & SMF_ECHO_BLEG) && (flags & SMF_ECHO_ALEG)) { + switch_channel_t *channel = switch_core_session_get_channel(master); + char *bto = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE); + if ((other_session = switch_core_session_locate(bto))) { + switch_channel_t *other_channel = switch_core_session_get_channel(other_session); + switch_channel_set_flag(other_channel, CF_WAIT_FOR_ME); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "wait-for", "%s", bto); + switch_core_session_rwunlock(other_session); + } + } + switch_core_session_queue_private_event(master, &event); } }