2007-03-29 22:34:40 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2010-02-06 03:38:24 +00:00
* Copyright ( C ) 2005 - 2010 , Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
* Michael Jerris < mike @ jerris . com >
* Paul D . Tinsley < pdt at jackhammer . org >
*
*
2009-11-23 14:55:09 +00:00
* switch_core_state_machine . c - - Main Core Library ( state machine )
2007-03-29 22:34:40 +00:00
*
*/
2008-01-27 17:36:53 +00:00
2007-03-29 22:34:40 +00:00
# include <switch.h>
2007-05-14 17:10:46 +00:00
# include "private/switch_core_pvt.h"
2007-03-29 22:34:40 +00:00
static void switch_core_standard_on_init ( switch_core_session_t * session )
{
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard INIT \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-03-29 22:34:40 +00:00
}
static void switch_core_standard_on_hangup ( switch_core_session_t * session )
{
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard HANGUP, cause: %s \n " ,
2007-03-30 00:13:31 +00:00
switch_channel_get_name ( session - > channel ) , switch_channel_cause2str ( switch_channel_get_cause ( session - > channel ) ) ) ;
2007-03-29 22:34:40 +00:00
}
2009-03-04 04:19:33 +00:00
static void switch_core_standard_on_reporting ( switch_core_session_t * session )
{
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard REPORTING, cause: %s \n " ,
2009-03-04 04:19:33 +00:00
switch_channel_get_name ( session - > channel ) , switch_channel_cause2str ( switch_channel_get_cause ( session - > channel ) ) ) ;
}
2009-04-10 17:43:18 +00:00
static void switch_core_standard_on_destroy ( switch_core_session_t * session )
{
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard DESTROY \n " , switch_channel_get_name ( session - > channel ) ) ;
2009-04-10 17:43:18 +00:00
}
2007-07-03 02:10:35 +00:00
static void switch_core_standard_on_reset ( switch_core_session_t * session )
{
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard RESET \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-07-03 02:10:35 +00:00
}
2008-05-05 15:30:55 +00:00
static void switch_core_standard_on_routing ( switch_core_session_t * session )
2007-03-29 22:34:40 +00:00
{
switch_dialplan_interface_t * dialplan_interface = NULL ;
switch_caller_profile_t * caller_profile ;
switch_caller_extension_t * extension = NULL ;
2008-01-08 19:38:57 +00:00
char * expanded = NULL ;
char * dpstr = NULL ;
2007-03-29 22:34:40 +00:00
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard ROUTING \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-03-29 22:34:40 +00:00
2010-02-06 03:38:24 +00:00
if ( ( switch_channel_test_flag ( session - > channel , CF_ANSWERED ) | |
2009-11-03 16:50:16 +00:00
switch_channel_test_flag ( session - > channel , CF_EARLY_MEDIA ) | |
2010-02-06 03:38:24 +00:00
switch_channel_test_flag ( session - > channel , CF_SIGNAL_BRIDGE_TTL ) ) & & switch_channel_test_flag ( session - > channel , CF_PROXY_MODE ) ) {
2009-11-02 23:58:30 +00:00
switch_ivr_media ( session - > uuid_str , SMF_NONE ) ;
}
2007-03-29 22:34:40 +00:00
if ( ( caller_profile = switch_channel_get_caller_profile ( session - > channel ) ) = = 0 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Can't get profile! \n " ) ;
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( session - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return ;
} else {
char * dp [ 25 ] ;
int argc , x , count = 0 ;
2008-05-27 04:30:03 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( caller_profile - > dialplan ) ) {
2007-03-29 22:34:40 +00:00
if ( ( dpstr = switch_core_session_strdup ( session , caller_profile - > dialplan ) ) ) {
2008-01-08 19:38:57 +00:00
expanded = switch_channel_expand_variables ( session - > channel , dpstr ) ;
argc = switch_separate_string ( expanded , ' , ' , dp , ( sizeof ( dp ) / sizeof ( dp [ 0 ] ) ) ) ;
2007-03-29 22:34:40 +00:00
for ( x = 0 ; x < argc ; x + + ) {
char * dpname = dp [ x ] ;
char * dparg = NULL ;
2010-02-06 03:38:24 +00:00
2007-03-29 22:34:40 +00:00
if ( dpname ) {
if ( ( dparg = strchr ( dpname , ' : ' ) ) ) {
* dparg + + = ' \0 ' ;
}
2008-05-16 15:49:23 +00:00
} else {
continue ;
2007-03-29 22:34:40 +00:00
}
if ( ! ( dialplan_interface = switch_loadable_module_get_dialplan_interface ( dpname ) ) ) {
continue ;
}
2010-02-06 03:38:24 +00:00
2007-03-29 22:34:40 +00:00
count + + ;
2010-02-06 03:38:24 +00:00
2008-11-12 19:28:05 +00:00
extension = dialplan_interface - > hunt_function ( session , dparg , NULL ) ;
UNPROTECT_INTERFACE ( dialplan_interface ) ;
2010-02-06 03:38:24 +00:00
2008-11-12 19:28:05 +00:00
if ( extension ) {
2007-03-29 22:34:40 +00:00
switch_channel_set_caller_extension ( session - > channel , extension ) ;
2008-03-11 03:45:16 +00:00
switch_channel_set_state ( session - > channel , CS_EXECUTE ) ;
2008-01-08 19:38:57 +00:00
goto end ;
2007-03-29 22:34:40 +00:00
}
}
}
}
2010-12-16 22:03:05 +00:00
if ( ! count ) {
2010-12-16 02:59:23 +00:00
if ( switch_channel_direction ( session - > channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2008-10-28 16:01:15 +00:00
if ( switch_channel_test_flag ( session - > channel , CF_ANSWERED ) ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG ,
" No Dialplan on answered channel, changing state to HANGUP \n " ) ;
2008-10-28 16:01:15 +00:00
switch_channel_hangup ( session - > channel , SWITCH_CAUSE_NO_ROUTE_DESTINATION ) ;
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " No Dialplan, changing state to CONSUME_MEDIA \n " ) ;
2008-10-28 16:01:15 +00:00
switch_channel_set_state ( session - > channel , CS_CONSUME_MEDIA ) ;
}
2008-01-08 19:38:57 +00:00
goto end ;
2007-03-29 22:34:40 +00:00
}
}
}
if ( ! extension ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_INFO , " No Route, Aborting \n " ) ;
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( session - > channel , SWITCH_CAUSE_NO_ROUTE_DESTINATION ) ;
}
2008-05-27 04:30:03 +00:00
end :
2008-01-08 19:38:57 +00:00
if ( expanded & & dpstr & & expanded ! = dpstr ) {
free ( expanded ) ;
}
2007-03-29 22:34:40 +00:00
}
static void switch_core_standard_on_execute ( switch_core_session_t * session )
{
switch_caller_extension_t * extension ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard EXECUTE \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-03-29 22:34:40 +00:00
2010-10-13 21:17:36 +00:00
if ( switch_channel_get_variable ( session - > channel , " recovered " ) & & ! switch_channel_test_flag ( session - > channel , CF_RECOVERED ) ) {
switch_channel_set_flag ( session - > channel , CF_RECOVERED ) ;
}
2008-05-27 04:30:03 +00:00
top :
2007-07-26 00:49:02 +00:00
switch_channel_clear_flag ( session - > channel , CF_RESET ) ;
2010-10-13 21:17:36 +00:00
2007-03-29 22:34:40 +00:00
if ( ( extension = switch_channel_get_caller_extension ( session - > channel ) ) = = 0 ) {
switch_channel_hangup ( session - > channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
return ;
}
while ( switch_channel_get_state ( session - > channel ) = = CS_EXECUTE & & extension - > current_application ) {
2008-09-25 14:25:59 +00:00
switch_caller_application_t * current_application = extension - > current_application ;
extension - > current_application = extension - > current_application - > next ;
2008-05-27 04:30:03 +00:00
if ( switch_core_session_execute_application ( session ,
2008-09-25 14:25:59 +00:00
current_application - > application_name ,
current_application - > application_data ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
return ;
}
2008-05-27 04:30:03 +00:00
2007-07-26 00:49:02 +00:00
if ( switch_channel_test_flag ( session - > channel , CF_RESET ) ) {
goto top ;
}
2010-02-06 03:38:24 +00:00
2007-03-29 22:34:40 +00:00
}
2009-12-04 23:21:51 +00:00
if ( switch_channel_ready ( session - > channel ) & & switch_channel_get_state ( session - > channel ) = = CS_EXECUTE ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " %s has executed the last dialplan instruction, hanging up. \n " ,
2010-02-04 15:57:23 +00:00
switch_channel_get_name ( session - > channel ) ) ;
switch_channel_hangup ( session - > channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
2007-03-29 22:34:40 +00:00
}
}
2008-05-05 15:30:55 +00:00
static void switch_core_standard_on_exchange_media ( switch_core_session_t * session )
2007-03-29 22:34:40 +00:00
{
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard EXCHANGE_MEDIA \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-03-29 22:34:40 +00:00
}
2008-05-05 15:30:55 +00:00
static void switch_core_standard_on_soft_execute ( switch_core_session_t * session )
2007-03-29 22:34:40 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( session ! = NULL ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard SOFT_EXECUTE \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-03-29 22:34:40 +00:00
}
2007-12-13 22:17:20 +00:00
static void switch_core_standard_on_park ( switch_core_session_t * session )
{
switch_assert ( session ! = NULL ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard PARK \n " , switch_channel_get_name ( session - > channel ) ) ;
2009-01-09 20:34:01 +00:00
switch_core_session_reset ( session , SWITCH_TRUE , SWITCH_TRUE ) ;
2007-12-13 22:17:20 +00:00
switch_ivr_park ( session , NULL ) ;
}
2008-05-05 15:30:55 +00:00
static void switch_core_standard_on_consume_media ( switch_core_session_t * session )
2007-03-29 22:34:40 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( session ! = NULL ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard CONSUME_MEDIA \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-03-29 22:34:40 +00:00
}
static void switch_core_standard_on_hibernate ( switch_core_session_t * session )
{
2007-12-11 19:23:57 +00:00
switch_assert ( session ! = NULL ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Standard HIBERNATE \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-03-29 22:34:40 +00:00
}
2007-03-30 02:20:13 +00:00
void switch_core_state_machine_init ( switch_memory_pool_t * pool )
{
2009-09-18 15:55:10 +00:00
return ;
2007-03-30 02:20:13 +00:00
}
2007-10-04 20:22:37 +00:00
# define STATE_MACRO(__STATE, __STATE_STR) do { \
midstate = state ; \
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " (%s) State %s \n " , switch_channel_get_name ( session - > channel ) , __STATE_STR ) ; \
2008-03-11 14:08:33 +00:00
if ( ! driver_state_handler - > on_ # # __STATE | | ( driver_state_handler - > on_ # # __STATE ( session ) = = SWITCH_STATUS_SUCCESS \
2009-02-03 17:17:31 +00:00
) ) { \
2008-01-14 15:26:46 +00:00
while ( do_extra_handlers & & ( application_state_handler = switch_channel_get_state_handler ( session - > channel , index + + ) ) ! = 0 ) { \
2007-10-04 20:22:37 +00:00
if ( ! application_state_handler | | ! application_state_handler - > on_ # # __STATE \
| | ( application_state_handler - > on_ # # __STATE \
& & application_state_handler - > on_ # # __STATE ( session ) = = SWITCH_STATUS_SUCCESS \
2009-02-03 17:17:31 +00:00
) ) { \
2007-10-04 20:22:37 +00:00
proceed + + ; \
continue ; \
} else { \
proceed = 0 ; \
break ; \
} \
} \
index = 0 ; \
2009-02-03 17:17:31 +00:00
if ( ! proceed ) global_proceed = 0 ; \
proceed = 1 ; \
2008-01-14 15:26:46 +00:00
while ( do_extra_handlers & & proceed & & ( application_state_handler = switch_core_get_state_handler ( index + + ) ) ! = 0 ) { \
2007-10-04 20:22:37 +00:00
if ( ! application_state_handler | | ! application_state_handler - > on_ # # __STATE | | \
( application_state_handler - > on_ # # __STATE & & \
application_state_handler - > on_ # # __STATE ( session ) = = SWITCH_STATUS_SUCCESS \
2009-02-03 17:17:31 +00:00
) ) { \
2007-10-04 20:22:37 +00:00
proceed + + ; \
continue ; \
} else { \
proceed = 0 ; \
break ; \
} \
} \
2009-02-03 17:17:31 +00:00
if ( ! proceed | | midstate ! = switch_channel_get_state ( session - > channel ) ) global_proceed = 0 ; \
if ( global_proceed ) { \
2007-10-04 20:22:37 +00:00
switch_core_standard_on_ # # __STATE ( session ) ; \
} \
} \
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " (%s) State %s going to sleep \n " , switch_channel_get_name ( session - > channel ) , __STATE_STR ) ; \
2007-10-04 21:01:52 +00:00
} while ( silly )
2007-10-04 20:22:37 +00:00
2007-03-29 22:34:40 +00:00
SWITCH_DECLARE ( void ) switch_core_session_run ( switch_core_session_t * session )
{
2009-04-10 17:43:18 +00:00
switch_channel_state_t state = CS_NEW , midstate = CS_DESTROY , endstate ;
2007-03-29 22:34:40 +00:00
const switch_endpoint_interface_t * endpoint_interface ;
const switch_state_handler_table_t * driver_state_handler = NULL ;
const switch_state_handler_table_t * application_state_handler = NULL ;
2009-09-18 15:55:10 +00:00
int silly = 0 ;
2009-07-22 19:14:47 +00:00
uint32_t new_loops = 60000 ;
2007-03-29 22:34:40 +00:00
/*
Life of the channel . you have channel and pool in your session
everywhere you go you use the session to malloc with
switch_core_session_alloc ( session , < size > )
2008-10-06 23:05:55 +00:00
The endpoint module gets the first crack at implementing the state
if it wants to , it can cancel the default behavior by returning SWITCH_STATUS_FALSE
2007-03-29 22:34:40 +00:00
Next comes the channel ' s event handler table that can be set by an application
2008-10-06 23:05:55 +00:00
which also can veto the next behavior in line by returning SWITCH_STATUS_FALSE
2007-03-29 22:34:40 +00:00
2008-10-06 23:05:55 +00:00
Finally the default state behavior is called .
2007-03-29 22:34:40 +00:00
*/
2007-12-11 19:23:57 +00:00
switch_assert ( session ! = NULL ) ;
2007-03-29 22:34:40 +00:00
2010-05-03 17:29:56 +00:00
switch_set_flag ( session , SSF_THREAD_RUNNING ) ;
2007-03-29 22:34:40 +00:00
endpoint_interface = session - > endpoint_interface ;
2007-12-11 19:23:57 +00:00
switch_assert ( endpoint_interface ! = NULL ) ;
2007-03-29 22:34:40 +00:00
driver_state_handler = endpoint_interface - > state_handler ;
2007-12-11 19:23:57 +00:00
switch_assert ( driver_state_handler ! = NULL ) ;
2007-03-29 22:34:40 +00:00
switch_mutex_lock ( session - > mutex ) ;
2009-04-10 17:43:18 +00:00
while ( ( state = switch_channel_get_state ( session - > channel ) ) ! = CS_DESTROY ) {
2009-03-04 04:19:33 +00:00
switch_channel_wait_for_flag ( session - > channel , CF_BLOCK_STATE , SWITCH_FALSE , 0 , NULL ) ;
2010-02-06 03:38:24 +00:00
2007-10-05 16:09:47 +00:00
midstate = state ;
2009-03-04 04:19:33 +00:00
if ( state ! = switch_channel_get_running_state ( session - > channel ) | | state > = CS_HANGUP ) {
2007-03-29 22:34:40 +00:00
int index = 0 ;
int proceed = 1 ;
2009-02-03 17:17:31 +00:00
int global_proceed = 1 ;
2008-05-27 04:30:03 +00:00
int do_extra_handlers = 1 ;
2010-10-30 01:38:59 +00:00
switch_io_event_hook_state_run_t * ptr ;
switch_status_t rstatus = SWITCH_STATUS_SUCCESS ;
2010-02-06 03:38:24 +00:00
2008-03-08 21:07:15 +00:00
switch_channel_set_running_state ( session - > channel , state ) ;
2008-11-21 00:09:11 +00:00
switch_channel_clear_flag ( session - > channel , CF_TRANSFER ) ;
2008-11-25 17:53:35 +00:00
switch_channel_clear_flag ( session - > channel , CF_REDIRECT ) ;
2010-10-30 01:38:59 +00:00
if ( session - > endpoint_interface - > io_routines - > state_run ) {
rstatus = session - > endpoint_interface - > io_routines - > state_run ( session ) ;
}
if ( rstatus = = SWITCH_STATUS_SUCCESS ) {
for ( ptr = session - > event_hooks . state_run ; ptr ; ptr = ptr - > next ) {
if ( ( rstatus = ptr - > state_run ( session ) ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
}
}
2007-03-29 22:34:40 +00:00
switch ( state ) {
2010-02-06 03:38:24 +00:00
case CS_NEW : /* Just created, Waiting for first instructions */
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " (%s) State NEW \n " , switch_channel_get_name ( session - > channel ) ) ;
2007-03-29 22:34:40 +00:00
break ;
2009-04-10 17:43:18 +00:00
case CS_DESTROY :
2007-03-29 22:34:40 +00:00
goto done ;
2010-02-06 03:38:24 +00:00
case CS_REPORTING : /* Call Detail */
2008-01-14 15:26:46 +00:00
{
2009-04-28 14:13:05 +00:00
switch_core_session_reporting_state ( session ) ;
2009-04-10 17:43:18 +00:00
switch_channel_set_state ( session - > channel , CS_DESTROY ) ;
2009-03-04 04:19:33 +00:00
}
goto done ;
case CS_HANGUP : /* Deactivate and end the thread */
{
2010-02-06 03:38:24 +00:00
switch_core_session_hangup_state ( session , SWITCH_TRUE ) ;
2009-03-25 20:07:40 +00:00
switch_channel_set_state ( session - > channel , CS_REPORTING ) ;
2008-01-14 15:26:46 +00:00
}
2009-03-25 20:07:40 +00:00
2009-03-04 04:19:33 +00:00
break ;
2008-05-27 04:30:03 +00:00
case CS_INIT : /* Basic setup tasks */
2008-03-11 14:08:33 +00:00
STATE_MACRO ( init , " INIT " ) ;
2007-03-29 22:34:40 +00:00
break ;
2008-05-27 04:30:03 +00:00
case CS_ROUTING : /* Look for a dialplan and find something to do */
2008-05-05 15:30:55 +00:00
STATE_MACRO ( routing , " ROUTING " ) ;
2007-03-29 22:34:40 +00:00
break ;
2008-05-27 04:30:03 +00:00
case CS_RESET : /* Reset */
2007-10-04 20:22:37 +00:00
STATE_MACRO ( reset , " RESET " ) ;
2007-07-03 02:10:35 +00:00
break ;
2008-02-26 20:31:53 +00:00
/* These other states are intended for prolonged durations so we do not signal lock for them */
2008-05-27 04:30:03 +00:00
case CS_EXECUTE : /* Execute an Operation */
2007-10-04 20:22:37 +00:00
STATE_MACRO ( execute , " EXECUTE " ) ;
2007-03-29 22:34:40 +00:00
break ;
2008-05-27 04:30:03 +00:00
case CS_EXCHANGE_MEDIA : /* loop all data back to source */
2008-05-05 15:30:55 +00:00
STATE_MACRO ( exchange_media , " EXCHANGE_MEDIA " ) ;
2007-03-29 22:34:40 +00:00
break ;
2008-05-27 04:30:03 +00:00
case CS_SOFT_EXECUTE : /* send/recieve data to/from another channel */
2008-05-05 15:30:55 +00:00
STATE_MACRO ( soft_execute , " SOFT_EXECUTE " ) ;
2007-03-29 22:34:40 +00:00
break ;
2008-05-27 04:30:03 +00:00
case CS_PARK : /* wait in limbo */
2007-12-13 22:17:20 +00:00
STATE_MACRO ( park , " PARK " ) ;
break ;
2008-05-27 04:30:03 +00:00
case CS_CONSUME_MEDIA : /* wait in limbo */
2008-05-05 15:30:55 +00:00
STATE_MACRO ( consume_media , " CONSUME_MEDIA " ) ;
2007-03-29 22:34:40 +00:00
break ;
2008-05-27 04:30:03 +00:00
case CS_HIBERNATE : /* sleep */
2007-10-04 20:22:37 +00:00
STATE_MACRO ( hibernate , " HIBERNATE " ) ;
2007-03-29 22:34:40 +00:00
break ;
2007-12-19 23:24:55 +00:00
case CS_NONE :
abort ( ) ;
break ;
2007-03-29 22:34:40 +00:00
}
2008-05-27 04:30:03 +00:00
2009-04-10 17:43:18 +00:00
if ( midstate = = CS_DESTROY ) {
2007-03-29 22:34:40 +00:00
break ;
}
}
endstate = switch_channel_get_state ( session - > channel ) ;
2008-05-27 04:30:03 +00:00
2007-12-19 23:24:55 +00:00
if ( endstate = = switch_channel_get_running_state ( session - > channel ) ) {
2007-10-11 19:12:18 +00:00
if ( endstate = = CS_NEW ) {
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2009-07-21 19:17:22 +00:00
if ( ! - - new_loops ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_CRIT , " %s Timeout waiting for next instruction in CS_NEW! \n " ,
session - > uuid_str ) ;
2009-07-21 19:17:22 +00:00
switch_channel_hangup ( session - > channel , SWITCH_CAUSE_INVALID_CALL_REFERENCE ) ;
}
2007-10-11 19:12:18 +00:00
} else {
2009-10-12 22:23:55 +00:00
switch_core_session_message_t * message ;
2010-02-06 03:38:24 +00:00
2009-10-12 22:23:55 +00:00
while ( switch_core_session_dequeue_message ( session , & message ) = = SWITCH_STATUS_SUCCESS ) {
switch_core_session_receive_message ( session , message ) ;
message = NULL ;
}
2009-10-20 17:03:03 +00:00
2010-11-05 20:24:11 +00:00
switch_ivr_parse_all_events ( session ) ;
2010-02-06 03:38:24 +00:00
if ( switch_channel_get_state ( session - > channel ) = = switch_channel_get_running_state ( session - > channel ) ) {
switch_channel_set_flag ( session - > channel , CF_THREAD_SLEEPING ) ;
if ( switch_channel_get_state ( session - > channel ) = = switch_channel_get_running_state ( session - > channel ) ) {
switch_thread_cond_wait ( session - > cond , session - > mutex ) ;
}
switch_channel_clear_flag ( session - > channel , CF_THREAD_SLEEPING ) ;
}
2010-11-05 20:24:11 +00:00
switch_ivr_parse_all_events ( session ) ;
2009-10-12 22:23:55 +00:00
while ( switch_core_session_dequeue_message ( session , & message ) = = SWITCH_STATUS_SUCCESS ) {
switch_core_session_receive_message ( session , message ) ;
message = NULL ;
}
2007-10-11 19:12:18 +00:00
}
2007-03-29 22:34:40 +00:00
}
}
done :
switch_mutex_unlock ( session - > mutex ) ;
2010-05-03 17:29:56 +00:00
switch_clear_flag ( session , SSF_THREAD_RUNNING ) ;
2007-03-29 22:34:40 +00:00
}
2008-01-27 17:36:53 +00:00
2009-04-10 17:43:18 +00:00
SWITCH_DECLARE ( void ) switch_core_session_destroy_state ( switch_core_session_t * session )
{
switch_channel_state_t state = CS_DESTROY , midstate = CS_DESTROY ;
const switch_endpoint_interface_t * endpoint_interface ;
const switch_state_handler_table_t * driver_state_handler = NULL ;
const switch_state_handler_table_t * application_state_handler = NULL ;
int proceed = 1 ;
int global_proceed = 1 ;
int do_extra_handlers = 1 ;
int silly = 0 ;
int index = 0 ;
2010-06-07 23:01:02 +00:00
switch_channel_set_callstate ( session - > channel , CCS_DOWN ) ;
2009-04-10 17:43:18 +00:00
switch_assert ( session ! = NULL ) ;
2009-08-26 21:53:43 +00:00
switch_channel_set_running_state ( session - > channel , CS_DESTROY ) ;
2009-09-14 20:10:58 +00:00
switch_channel_clear_flag ( session - > channel , CF_TRANSFER ) ;
switch_channel_clear_flag ( session - > channel , CF_REDIRECT ) ;
2009-04-10 17:43:18 +00:00
endpoint_interface = session - > endpoint_interface ;
switch_assert ( endpoint_interface ! = NULL ) ;
driver_state_handler = endpoint_interface - > state_handler ;
switch_assert ( driver_state_handler ! = NULL ) ;
2010-02-06 03:38:24 +00:00
2009-04-10 17:43:18 +00:00
STATE_MACRO ( destroy , " DESTROY " ) ;
return ;
}
2010-07-21 19:48:08 +00:00
static void api_hook ( switch_core_session_t * session , const char * hook_var , int use_session )
{
if ( ! zstr ( hook_var ) ) {
switch_stream_handle_t stream = { 0 } ;
char * cmd = switch_core_session_strdup ( session , hook_var ) ;
char * arg = NULL ;
char * expanded = NULL ;
if ( ( arg = strchr ( cmd , ' : ' ) ) & & * ( arg + 1 ) = = ' : ' ) {
* arg + + = ' \0 ' ;
* arg + + = ' \0 ' ;
} else {
if ( ( arg = strchr ( cmd , ' ' ) ) ) {
* arg + + = ' \0 ' ;
}
}
SWITCH_STANDARD_STREAM ( stream ) ;
switch_channel_get_variables ( session - > channel , & stream . param_event ) ;
switch_channel_event_set_data ( session - > channel , stream . param_event ) ;
expanded = switch_channel_expand_variables ( session - > channel , arg ) ;
switch_api_execute ( cmd , expanded , use_session ? session : NULL , & stream ) ;
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Hangup Command %s %s(%s): \n %s \n " ,
use_session ? " with Session " : " with no Session " , cmd , switch_str_nil ( expanded ) ,
switch_str_nil ( ( char * ) stream . data ) ) ;
if ( expanded ! = arg ) {
switch_safe_free ( expanded ) ;
}
switch_safe_free ( stream . data ) ;
}
}
2009-04-28 14:13:05 +00:00
2009-12-11 00:28:54 +00:00
SWITCH_DECLARE ( void ) switch_core_session_hangup_state ( switch_core_session_t * session , switch_bool_t force )
2009-09-14 20:10:58 +00:00
{
switch_call_cause_t cause = switch_channel_get_cause ( session - > channel ) ;
switch_call_cause_t cause_q850 = switch_channel_get_cause_q850 ( session - > channel ) ;
int proceed = 1 ;
int global_proceed = 1 ;
int do_extra_handlers = 1 ;
int silly = 0 ;
int index = 0 ;
switch_channel_state_t state = switch_channel_get_state ( session - > channel ) , midstate = state ;
const switch_endpoint_interface_t * endpoint_interface ;
const switch_state_handler_table_t * driver_state_handler = NULL ;
const switch_state_handler_table_t * application_state_handler = NULL ;
2010-07-21 19:48:08 +00:00
const char * hook_var ;
2010-07-22 15:31:12 +00:00
int use_session = 0 ;
2010-02-06 03:38:24 +00:00
2009-12-11 00:28:54 +00:00
if ( ! force ) {
if ( ! switch_channel_test_flag ( session - > channel , CF_EARLY_HANGUP ) & & ! switch_test_flag ( ( & runtime ) , SCF_EARLY_HANGUP ) ) {
return ;
}
2009-09-14 20:10:58 +00:00
2009-12-11 00:28:54 +00:00
if ( switch_thread_self ( ) ! = session - > thread_id ) {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG10 , " %s thread mismatch skipping state handler. \n " ,
2009-12-11 00:28:54 +00:00
switch_channel_get_name ( session - > channel ) ) ;
return ;
}
2009-09-14 20:10:58 +00:00
}
if ( switch_test_flag ( session , SSF_HANGUP ) ) {
2009-12-11 00:28:54 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG10 , " %s handler already called, skipping state handler. \n " ,
2009-12-07 21:33:52 +00:00
switch_channel_get_name ( session - > channel ) ) ;
2009-09-14 20:10:58 +00:00
return ;
}
endpoint_interface = session - > endpoint_interface ;
switch_assert ( endpoint_interface ! = NULL ) ;
driver_state_handler = endpoint_interface - > state_handler ;
switch_assert ( driver_state_handler ! = NULL ) ;
switch_channel_set_hangup_time ( session - > channel ) ;
switch_core_media_bug_remove_all ( session ) ;
2010-02-06 03:38:24 +00:00
2009-09-14 20:10:58 +00:00
switch_channel_stop_broadcast ( session - > channel ) ;
2010-02-06 03:38:24 +00:00
2009-09-14 20:10:58 +00:00
switch_channel_set_variable ( session - > channel , " hangup_cause " , switch_channel_cause2str ( cause ) ) ;
switch_channel_set_variable_printf ( session - > channel , " hangup_cause_q850 " , " %d " , cause_q850 ) ;
2010-07-30 04:39:39 +00:00
//switch_channel_presence(session->channel, "unknown", switch_channel_cause2str(cause), NULL);
2010-02-06 03:38:24 +00:00
2009-09-14 20:10:58 +00:00
switch_channel_set_timestamps ( session - > channel ) ;
2010-02-06 03:38:24 +00:00
2009-09-14 20:10:58 +00:00
STATE_MACRO ( hangup , " HANGUP " ) ;
2010-07-21 19:48:08 +00:00
if ( ( hook_var = switch_channel_get_variable ( session - > channel , SWITCH_API_HANGUP_HOOK_VARIABLE ) ) ) {
2010-02-06 03:38:24 +00:00
2010-07-21 19:48:08 +00:00
if ( switch_true ( switch_channel_get_variable ( session - > channel , SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE ) ) ) {
use_session = 1 ;
2009-09-14 20:10:58 +00:00
}
2010-07-21 19:48:08 +00:00
api_hook ( session , hook_var , use_session ) ;
2009-09-14 20:10:58 +00:00
}
switch_set_flag ( session , SSF_HANGUP ) ;
2010-02-06 03:38:24 +00:00
2009-09-14 20:10:58 +00:00
}
2009-04-28 14:13:05 +00:00
SWITCH_DECLARE ( void ) switch_core_session_reporting_state ( switch_core_session_t * session )
{
switch_channel_state_t state = switch_channel_get_state ( session - > channel ) , midstate = state ;
const switch_endpoint_interface_t * endpoint_interface ;
const switch_state_handler_table_t * driver_state_handler = NULL ;
const switch_state_handler_table_t * application_state_handler = NULL ;
int proceed = 1 ;
int global_proceed = 1 ;
int do_extra_handlers = 1 ;
int silly = 0 ;
int index = 0 ;
2009-04-28 15:11:38 +00:00
const char * var = switch_channel_get_variable ( session - > channel , SWITCH_PROCESS_CDR_VARIABLE ) ;
2010-07-21 19:48:08 +00:00
const char * hook_var ;
2010-07-22 15:31:12 +00:00
int use_session = 0 ;
2010-07-21 19:48:08 +00:00
switch_event_t * event ;
switch_call_cause_t cause = switch_channel_get_cause ( session - > channel ) ;
2009-04-28 14:13:05 +00:00
if ( switch_channel_test_flag ( session - > channel , CF_REPORTING ) ) {
return ;
}
switch_channel_set_flag ( session - > channel , CF_REPORTING ) ;
2010-02-06 03:38:24 +00:00
2009-04-28 14:13:05 +00:00
switch_assert ( session ! = NULL ) ;
endpoint_interface = session - > endpoint_interface ;
switch_assert ( endpoint_interface ! = NULL ) ;
driver_state_handler = endpoint_interface - > state_handler ;
switch_assert ( driver_state_handler ! = NULL ) ;
2010-02-06 03:38:24 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( var ) ) {
2009-04-28 14:13:05 +00:00
if ( ! strcasecmp ( var , " a_only " ) ) {
if ( switch_channel_get_originator_caller_profile ( session - > channel ) ) {
do_extra_handlers = 0 ;
}
} else if ( ! strcasecmp ( var , " b_only " ) ) {
if ( switch_channel_get_originatee_caller_profile ( session - > channel ) ) {
do_extra_handlers = 0 ;
}
} else if ( ! switch_true ( var ) ) {
do_extra_handlers = 0 ;
}
}
STATE_MACRO ( reporting , " REPORTING " ) ;
2010-02-06 03:38:24 +00:00
2010-07-21 19:48:08 +00:00
if ( ( hook_var = switch_channel_get_variable ( session - > channel , SWITCH_API_REPORTING_HOOK_VARIABLE ) ) ) {
if ( switch_true ( switch_channel_get_variable ( session - > channel , SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE ) ) ) {
use_session = 1 ;
}
api_hook ( session , hook_var , use_session ) ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Hangup-Cause " , switch_channel_cause2str ( cause ) ) ;
switch_channel_event_set_data ( session - > channel , event ) ;
switch_event_fire ( & event ) ;
}
2009-04-28 14:13:05 +00:00
return ;
}
2008-01-27 17:36:53 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2008-01-27 17:36:53 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2008-07-03 19:12:26 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2008-01-27 17:36:53 +00:00
*/