diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index 3eb9dc3091..2d2b1fde0b 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -256,7 +256,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir, \param filename the path to the module's dll or so file \return SWITCH_STATUS_SUCCESS on a successful load */ -SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename); +SWITCH_MOD_DECLARE(switch_status_t) switch_module_load( switch_loadable_module_interface_t **module_interface, char *filename); SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void); /*! diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 10b91dff3c..dcb314076f 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -53,7 +53,8 @@ typedef enum { SWITCH_SHN_ON_LOOPBACK, SWITCH_SHN_ON_TRANSMIT, SWITCH_SHN_ON_HOLD, - SWITCH_SHN_ON_HIBERNATE + SWITCH_SHN_ON_HIBERNATE, + SWITCH_SHN_ON_RESET, } switch_state_handler_name_t; struct switch_state_handler_table { @@ -73,6 +74,8 @@ struct switch_state_handler_table { switch_state_handler_t on_hold; /*! executed when the state changes to hibernate */ switch_state_handler_t on_hibernate; + /*! executed when the state changes to reset */ + switch_state_handler_t on_reset; void *padding[10]; }; diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 07c8109272..bab55250b7 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -527,6 +527,7 @@ CS_EXECUTE - Channel is executing it's dialplan CS_LOOPBACK - Channel is in loopback CS_HOLD - Channel is on hold CS_HIBERNATE - Channel is in a sleep state +CS_RESET - Channel is in a reset state CS_HANGUP - Channel is flagged for hangup and ready to end CS_DONE - Channel is ready to be destroyed and out of the state machine @@ -540,6 +541,7 @@ typedef enum { CS_LOOPBACK, CS_HOLD, CS_HIBERNATE, + CS_RESET, CS_HANGUP, CS_DONE } switch_channel_state_t; diff --git a/src/switch_channel.c b/src/switch_channel.c index b758430a53..b87bee64ea 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -509,7 +509,8 @@ SWITCH_DECLARE(uint8_t) switch_channel_ready(switch_channel_t *channel) assert(channel != NULL); - if (!channel->hangup_cause && channel->state > CS_RING && channel->state < CS_HANGUP && !switch_test_flag(channel, CF_TRANSFER)) { + if (!channel->hangup_cause && channel->state > CS_RING && channel->state < CS_HANGUP && channel->state != CS_RESET && + !switch_test_flag(channel, CF_TRANSFER)) { ret++; } @@ -525,6 +526,7 @@ static const char *state_names[] = { "CS_LOOPBACK", "CS_HOLD", "CS_HIBERNATE", + "CS_RESET", "CS_HANGUP", "CS_DONE", NULL @@ -589,6 +591,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c switch (last_state) { case CS_NEW: + case CS_RESET: switch (state) { default: ok++; @@ -604,6 +607,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c case CS_EXECUTE: case CS_HOLD: case CS_HIBERNATE: + case CS_RESET: ok++; default: break; @@ -617,6 +621,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c case CS_EXECUTE: case CS_HOLD: case CS_HIBERNATE: + case CS_RESET: ok++; default: break; @@ -630,6 +635,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c case CS_EXECUTE: case CS_HOLD: case CS_HIBERNATE: + case CS_RESET: ok++; default: break; @@ -643,6 +649,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c case CS_EXECUTE: case CS_TRANSMIT: case CS_HIBERNATE: + case CS_RESET: ok++; default: break; @@ -655,6 +662,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c case CS_EXECUTE: case CS_TRANSMIT: case CS_HOLD: + case CS_RESET: ok++; default: break; @@ -669,6 +677,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c case CS_TRANSMIT: case CS_HOLD: case CS_HIBERNATE: + case CS_RESET: ok++; default: break; @@ -682,6 +691,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c case CS_RING: case CS_HOLD: case CS_HIBERNATE: + case CS_RESET: ok++; default: break; @@ -752,6 +762,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c if (channel->state_flags) { channel->flags |= channel->state_flags; channel->state_flags = 0; + } switch_mutex_unlock(channel->flag_mutex); diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 2490f0ea2a..1608ea103f 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -47,6 +47,14 @@ static void switch_core_standard_on_hangup(switch_core_session_t *session) } +static void switch_core_standard_on_reset(switch_core_session_t *session) +{ + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard RESET %s\n", + switch_channel_get_name(session->channel)); + +} + static void switch_core_standard_on_ring(switch_core_session_t *session) { switch_dialplan_interface_t *dialplan_interface = NULL; @@ -433,6 +441,41 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) } } break; + case CS_RESET: /* Look for a dialplan and find something to do */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State RESET\n", switch_channel_get_name(session->channel)); + if (!driver_state_handler->on_reset + || (driver_state_handler->on_reset && driver_state_handler->on_reset(session) == SWITCH_STATUS_SUCCESS + && midstate == switch_channel_get_state(session->channel))) { + while ((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) { + if (!application_state_handler || !application_state_handler->on_reset + || (application_state_handler->on_reset + && application_state_handler->on_reset(session) == SWITCH_STATUS_SUCCESS + && midstate == switch_channel_get_state(session->channel))) { + proceed++; + continue; + } else { + proceed = 0; + break; + } + } + index = 0; + while (proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) { + if (!application_state_handler || !application_state_handler->on_reset || + (application_state_handler->on_reset && + application_state_handler->on_reset(session) == SWITCH_STATUS_SUCCESS + && midstate == switch_channel_get_state(session->channel))) { + proceed++; + continue; + } else { + proceed = 0; + break; + } + } + if (proceed) { + switch_core_standard_on_reset(session); + } + } + break; case CS_EXECUTE: /* Execute an Operation */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State EXECUTE\n", switch_channel_get_name(session->channel)); if (!driver_state_handler->on_execute diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 710d0483de..4b988c9965 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -262,11 +262,27 @@ static const switch_state_handler_table_t audio_bridge_peer_state_handlers = { }; +static switch_status_t uuid_bridge_on_reset(switch_core_session_t *session) +{ + switch_channel_t *channel = NULL; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CUSTOM RESET\n"); + + if (switch_channel_test_flag(channel, CF_ORIGINATOR)) { + switch_channel_set_state(channel, CS_TRANSMIT); + } + + return SWITCH_STATUS_SUCCESS; +} static switch_status_t uuid_bridge_on_transmit(switch_core_session_t *session) { switch_channel_t *channel = NULL; switch_core_session_t *other_session; + char *other_uuid = NULL; channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -274,13 +290,13 @@ static switch_status_t uuid_bridge_on_transmit(switch_core_session_t *session) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CUSTOM TRANSMIT\n"); switch_channel_clear_state_handler(channel, NULL); - switch_channel_set_flag(channel, CF_BREAK); - if (!switch_channel_test_flag(channel, CF_ORIGINATOR)) { + switch_channel_set_flag(channel, CF_TAGGED); return SWITCH_STATUS_FALSE; } - - if ((other_session = switch_channel_get_private(channel, SWITCH_UUID_BRIDGE))) { + + if ((other_uuid = switch_channel_get_variable(channel, SWITCH_UUID_BRIDGE)) && + (other_session = switch_core_session_locate(other_uuid))) { switch_channel_t *other_channel = switch_core_session_get_channel(other_session); switch_channel_state_t state = switch_channel_get_state(other_channel); switch_channel_state_t mystate = switch_channel_get_state(channel); @@ -288,20 +304,19 @@ static switch_status_t uuid_bridge_on_transmit(switch_core_session_t *session) uint8_t ready_a, ready_b; switch_caller_profile_t *profile, *new_profile; - - switch_channel_clear_flag(channel, CF_TRANSFER); - switch_channel_set_private(channel, SWITCH_UUID_BRIDGE, NULL); - - while (mystate <= CS_HANGUP && state <= CS_HANGUP && !switch_channel_test_flag(other_channel, CF_TAGGED)) { + switch_channel_set_variable(channel, SWITCH_UUID_BRIDGE, NULL); + switch_channel_set_state(other_channel, CS_TRANSMIT); + for(;;) { + if (mystate >= CS_HANGUP || state >= CS_HANGUP || switch_channel_test_flag(other_channel, CF_TAGGED)) { + break; + } switch_yield(1000); state = switch_channel_get_state(other_channel); mystate = switch_channel_get_state(channel); } - + switch_channel_clear_flag(channel, CF_TRANSFER); switch_channel_clear_flag(other_channel, CF_TRANSFER); switch_channel_clear_flag(other_channel, CF_TAGGED); - - switch_core_session_reset(session); switch_core_session_reset(other_session); @@ -316,6 +331,7 @@ static switch_status_t uuid_bridge_on_transmit(switch_core_session_t *session) if (!ready_b) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); } + switch_core_session_rwunlock(other_session); return SWITCH_STATUS_FALSE; } @@ -348,6 +364,7 @@ static switch_status_t uuid_bridge_on_transmit(switch_core_session_t *session) } switch_ivr_multi_threaded_bridge(session, other_session, NULL, NULL, NULL); + switch_core_session_rwunlock(other_session); } else { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); } @@ -364,7 +381,9 @@ static const switch_state_handler_table_t uuid_bridge_state_handlers = { /*.on_hangup */ NULL, /*.on_loopback */ NULL, /*.on_transmit */ uuid_bridge_on_transmit, - /*.on_hold */ NULL + /*.on_hold */ NULL, + /*.on_hibernate*/ NULL, + /*.on_reset*/ uuid_bridge_on_reset }; static switch_status_t signal_bridge_on_hibernate(switch_core_session_t *session) @@ -654,29 +673,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(char *originator_uuid, ch switch_channel_set_flag(originator_channel, CF_ORIGINATOR); switch_channel_add_state_handler(originator_channel, &uuid_bridge_state_handlers); switch_channel_add_state_handler(originatee_channel, &uuid_bridge_state_handlers); - switch_channel_set_flag(originatee_channel, CF_TAGGED); - switch_channel_set_private(originator_channel, SWITCH_UUID_BRIDGE, originatee_session); - + switch_channel_set_variable(originator_channel, SWITCH_UUID_BRIDGE, switch_core_session_get_uuid(originatee_session)); + switch_channel_set_flag(originator_channel, CF_BREAK); switch_channel_set_flag(originatee_channel, CF_BREAK); - /* switch_channel_set_state_flag sets flags you want to be set when the next state change happens */ - switch_channel_set_state_flag(originator_channel, CF_TRANSFER); - switch_channel_set_state_flag(originatee_channel, CF_TRANSFER); - /* change the states and let the chips fall where they may */ - switch_channel_set_state(originator_channel, CS_TRANSMIT); - switch_channel_set_state(originatee_channel, CS_TRANSMIT); + switch_channel_set_state(originator_channel, CS_RESET); + switch_channel_set_state(originatee_channel, CS_RESET); + + status = SWITCH_STATUS_SUCCESS; /* release the read locks we have on the channels */ switch_core_session_rwunlock(originator_session); switch_core_session_rwunlock(originatee_session); - status = SWITCH_STATUS_SUCCESS; - - while (switch_channel_get_state(originatee_channel) < CS_HANGUP && switch_channel_test_flag(originatee_channel, CF_TAGGED)) { - switch_yield(20000); - } } 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); diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index 963e31eed4..5ee4b61ee9 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -394,7 +394,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se for(;;) { switch_size_t len; - + if (!switch_channel_ready(channel)) { status = SWITCH_STATUS_FALSE; break; @@ -547,7 +547,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi for(;;) { switch_status_t status = switch_core_session_read_frame(session, &read_frame, 1000, 0); - + if (!switch_channel_ready(channel)) { status = SWITCH_STATUS_FALSE; break; @@ -556,6 +556,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi if (switch_channel_test_flag(channel, CF_BREAK)) { switch_channel_clear_flag(channel, CF_BREAK); + status = SWITCH_STATUS_BREAK; break; } @@ -799,13 +800,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess ilen = samples; - while (switch_channel_ready(channel)) { + for(;;) { int done = 0; int do_speed = 1; int last_speed = -1; + //printf("xxxxxxxxxxxWTF %d %d %d\n", switch_channel_get_state(channel), switch_channel_ready(channel), switch_channel_test_flag(channel, CF_TRANSFER)); + + if (!switch_channel_ready(channel)) { + status = SWITCH_STATUS_FALSE; + break; + } + if (switch_channel_test_flag(channel, CF_BREAK)) { switch_channel_clear_flag(channel, CF_BREAK); + status = SWITCH_STATUS_BREAK; break; } @@ -1176,11 +1185,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session } ilen = len; - while (switch_channel_ready(channel)) { + for(;;) { switch_event_t *event; + if (!switch_channel_ready(channel)) { + status = SWITCH_STATUS_FALSE; + break; + } + if (switch_channel_test_flag(channel, CF_BREAK)) { switch_channel_clear_flag(channel, CF_BREAK); + status = SWITCH_STATUS_BREAK; break; }