2017-01-06 07:10:15 +00:00
/*
2005-11-19 20:07:43 +00:00
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2020-06-23 21:50:18 +00:00
* Copyright ( C ) 2005 - 2020 , Anthony Minessale II < anthm @ freeswitch . org >
2005-11-19 20:07:43 +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 >
2005-11-19 20:07:43 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
2017-01-06 07:10:15 +00:00
*
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2006-09-18 05:08:55 +00:00
* Michael Jerris < mike @ jerris . com >
2005-11-19 20:07:43 +00:00
*
*
* switch_channel . c - - Media Channel Interface
*
*/
2008-01-27 17:36:53 +00:00
2006-04-29 01:00:52 +00:00
# include <switch.h>
2006-04-29 06:05:03 +00:00
# include <switch_channel.h>
2014-10-23 17:47:27 +00:00
# include <pcre.h>
2012-07-27 23:53:04 +00:00
2006-04-22 18:12:17 +00:00
struct switch_cause_table {
const char * name ;
switch_call_cause_t cause ;
} ;
2013-06-05 16:19:44 +00:00
typedef struct switch_device_state_binding_s {
switch_device_state_function_t function ;
void * user_data ;
struct switch_device_state_binding_s * next ;
} switch_device_state_binding_t ;
static struct {
switch_memory_pool_t * pool ;
switch_hash_t * device_hash ;
switch_mutex_t * device_mutex ;
switch_device_state_binding_t * device_bindings ;
} globals ;
2006-04-22 18:12:17 +00:00
static struct switch_cause_table CAUSE_CHART [ ] = {
2008-07-03 22:51:09 +00:00
{ " NONE " , SWITCH_CAUSE_NONE } ,
2008-07-23 14:19:53 +00:00
{ " UNALLOCATED_NUMBER " , SWITCH_CAUSE_UNALLOCATED_NUMBER } ,
2007-03-29 22:31:56 +00:00
{ " NO_ROUTE_TRANSIT_NET " , SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET } ,
{ " NO_ROUTE_DESTINATION " , SWITCH_CAUSE_NO_ROUTE_DESTINATION } ,
{ " CHANNEL_UNACCEPTABLE " , SWITCH_CAUSE_CHANNEL_UNACCEPTABLE } ,
{ " CALL_AWARDED_DELIVERED " , SWITCH_CAUSE_CALL_AWARDED_DELIVERED } ,
{ " NORMAL_CLEARING " , SWITCH_CAUSE_NORMAL_CLEARING } ,
{ " USER_BUSY " , SWITCH_CAUSE_USER_BUSY } ,
{ " NO_USER_RESPONSE " , SWITCH_CAUSE_NO_USER_RESPONSE } ,
{ " NO_ANSWER " , SWITCH_CAUSE_NO_ANSWER } ,
{ " SUBSCRIBER_ABSENT " , SWITCH_CAUSE_SUBSCRIBER_ABSENT } ,
{ " CALL_REJECTED " , SWITCH_CAUSE_CALL_REJECTED } ,
{ " NUMBER_CHANGED " , SWITCH_CAUSE_NUMBER_CHANGED } ,
{ " REDIRECTION_TO_NEW_DESTINATION " , SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION } ,
{ " EXCHANGE_ROUTING_ERROR " , SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR } ,
{ " DESTINATION_OUT_OF_ORDER " , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER } ,
{ " INVALID_NUMBER_FORMAT " , SWITCH_CAUSE_INVALID_NUMBER_FORMAT } ,
{ " FACILITY_REJECTED " , SWITCH_CAUSE_FACILITY_REJECTED } ,
{ " RESPONSE_TO_STATUS_ENQUIRY " , SWITCH_CAUSE_RESPONSE_TO_STATUS_ENQUIRY } ,
{ " NORMAL_UNSPECIFIED " , SWITCH_CAUSE_NORMAL_UNSPECIFIED } ,
{ " NORMAL_CIRCUIT_CONGESTION " , SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION } ,
{ " NETWORK_OUT_OF_ORDER " , SWITCH_CAUSE_NETWORK_OUT_OF_ORDER } ,
{ " NORMAL_TEMPORARY_FAILURE " , SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE } ,
{ " SWITCH_CONGESTION " , SWITCH_CAUSE_SWITCH_CONGESTION } ,
{ " ACCESS_INFO_DISCARDED " , SWITCH_CAUSE_ACCESS_INFO_DISCARDED } ,
{ " REQUESTED_CHAN_UNAVAIL " , SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL } ,
{ " PRE_EMPTED " , SWITCH_CAUSE_PRE_EMPTED } ,
{ " FACILITY_NOT_SUBSCRIBED " , SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED } ,
{ " OUTGOING_CALL_BARRED " , SWITCH_CAUSE_OUTGOING_CALL_BARRED } ,
{ " INCOMING_CALL_BARRED " , SWITCH_CAUSE_INCOMING_CALL_BARRED } ,
{ " BEARERCAPABILITY_NOTAUTH " , SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH } ,
{ " BEARERCAPABILITY_NOTAVAIL " , SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL } ,
{ " SERVICE_UNAVAILABLE " , SWITCH_CAUSE_SERVICE_UNAVAILABLE } ,
2013-03-13 15:37:34 +00:00
{ " BEARERCAPABILITY_NOTIMPL " , SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL } ,
2007-03-29 22:31:56 +00:00
{ " CHAN_NOT_IMPLEMENTED " , SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED } ,
{ " FACILITY_NOT_IMPLEMENTED " , SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED } ,
{ " SERVICE_NOT_IMPLEMENTED " , SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED } ,
{ " INVALID_CALL_REFERENCE " , SWITCH_CAUSE_INVALID_CALL_REFERENCE } ,
{ " INCOMPATIBLE_DESTINATION " , SWITCH_CAUSE_INCOMPATIBLE_DESTINATION } ,
{ " INVALID_MSG_UNSPECIFIED " , SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED } ,
{ " MANDATORY_IE_MISSING " , SWITCH_CAUSE_MANDATORY_IE_MISSING } ,
{ " MESSAGE_TYPE_NONEXIST " , SWITCH_CAUSE_MESSAGE_TYPE_NONEXIST } ,
{ " WRONG_MESSAGE " , SWITCH_CAUSE_WRONG_MESSAGE } ,
{ " IE_NONEXIST " , SWITCH_CAUSE_IE_NONEXIST } ,
{ " INVALID_IE_CONTENTS " , SWITCH_CAUSE_INVALID_IE_CONTENTS } ,
{ " WRONG_CALL_STATE " , SWITCH_CAUSE_WRONG_CALL_STATE } ,
{ " RECOVERY_ON_TIMER_EXPIRE " , SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE } ,
{ " MANDATORY_IE_LENGTH_ERROR " , SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR } ,
{ " PROTOCOL_ERROR " , SWITCH_CAUSE_PROTOCOL_ERROR } ,
{ " INTERWORKING " , SWITCH_CAUSE_INTERWORKING } ,
2008-07-03 22:51:09 +00:00
{ " SUCCESS " , SWITCH_CAUSE_SUCCESS } ,
2007-03-29 22:31:56 +00:00
{ " ORIGINATOR_CANCEL " , SWITCH_CAUSE_ORIGINATOR_CANCEL } ,
{ " CRASH " , SWITCH_CAUSE_CRASH } ,
{ " SYSTEM_SHUTDOWN " , SWITCH_CAUSE_SYSTEM_SHUTDOWN } ,
{ " LOSE_RACE " , SWITCH_CAUSE_LOSE_RACE } ,
{ " MANAGER_REQUEST " , SWITCH_CAUSE_MANAGER_REQUEST } ,
{ " BLIND_TRANSFER " , SWITCH_CAUSE_BLIND_TRANSFER } ,
{ " ATTENDED_TRANSFER " , SWITCH_CAUSE_ATTENDED_TRANSFER } ,
{ " ALLOTTED_TIMEOUT " , SWITCH_CAUSE_ALLOTTED_TIMEOUT } ,
2007-06-08 22:28:32 +00:00
{ " USER_CHALLENGE " , SWITCH_CAUSE_USER_CHALLENGE } ,
2007-10-31 13:08:45 +00:00
{ " MEDIA_TIMEOUT " , SWITCH_CAUSE_MEDIA_TIMEOUT } ,
2007-12-08 00:14:21 +00:00
{ " PICKED_OFF " , SWITCH_CAUSE_PICKED_OFF } ,
2008-08-11 16:12:55 +00:00
{ " USER_NOT_REGISTERED " , SWITCH_CAUSE_USER_NOT_REGISTERED } ,
2008-10-09 00:38:59 +00:00
{ " PROGRESS_TIMEOUT " , SWITCH_CAUSE_PROGRESS_TIMEOUT } ,
2011-12-15 17:16:41 +00:00
{ " INVALID_GATEWAY " , SWITCH_CAUSE_INVALID_GATEWAY } ,
{ " GATEWAY_DOWN " , SWITCH_CAUSE_GATEWAY_DOWN } ,
{ " INVALID_URL " , SWITCH_CAUSE_INVALID_URL } ,
{ " INVALID_PROFILE " , SWITCH_CAUSE_INVALID_PROFILE } ,
2013-03-13 15:37:34 +00:00
{ " NO_PICKUP " , SWITCH_CAUSE_NO_PICKUP } ,
2014-06-28 01:18:50 +00:00
{ " SRTP_READ_ERROR " , SWITCH_CAUSE_SRTP_READ_ERROR } ,
2018-04-24 03:36:01 +00:00
{ " BOWOUT " , SWITCH_CAUSE_BOWOUT } ,
2019-04-30 23:26:41 +00:00
{ " BUSY_EVERYWHERE " , SWITCH_CAUSE_BUSY_EVERYWHERE } ,
{ " DECLINE " , SWITCH_CAUSE_DECLINE } ,
{ " DOES_NOT_EXIST_ANYWHERE " , SWITCH_CAUSE_DOES_NOT_EXIST_ANYWHERE } ,
2019-05-01 02:07:37 +00:00
{ " NOT_ACCEPTABLE " , SWITCH_CAUSE_NOT_ACCEPTABLE } ,
2019-04-30 23:26:41 +00:00
{ " UNWANTED " , SWITCH_CAUSE_UNWANTED } ,
2021-04-27 19:54:32 +00:00
{ " NO_IDENTITY " , SWITCH_CAUSE_NO_IDENTITY } ,
{ " BAD_IDENTITY_INFO " , SWITCH_CAUSE_BAD_IDENTITY_INFO } ,
{ " UNSUPPORTED_CERTIFICATE " , SWITCH_CAUSE_UNSUPPORTED_CERTIFICATE } ,
{ " INVALID_IDENTITY " , SWITCH_CAUSE_INVALID_IDENTITY } ,
{ " STALE_DATE " , SWITCH_CAUSE_STALE_DATE } ,
2023-06-16 17:30:15 +00:00
{ " REJECT_ALL " , SWITCH_CAUSE_REJECT_ALL } ,
2007-03-29 22:31:56 +00:00
{ NULL , 0 }
2006-04-22 18:12:17 +00:00
} ;
2010-05-03 17:29:56 +00:00
typedef enum {
OCF_HANGUP = ( 1 < < 0 )
} opaque_channel_flag_t ;
2011-08-04 22:20:02 +00:00
typedef enum {
LP_NEITHER ,
LP_ORIGINATOR ,
LP_ORIGINATEE
} switch_originator_type_t ;
2005-11-19 20:07:43 +00:00
struct switch_channel {
char * name ;
2009-02-23 16:31:59 +00:00
switch_call_direction_t direction ;
2013-10-31 20:28:24 +00:00
switch_call_direction_t logical_direction ;
2007-12-22 00:32:20 +00:00
switch_queue_t * dtmf_queue ;
2009-02-23 16:31:59 +00:00
switch_queue_t * dtmf_log_queue ;
2013-06-05 16:19:44 +00:00
switch_mutex_t * dtmf_mutex ;
2006-06-22 23:56:09 +00:00
switch_mutex_t * flag_mutex ;
2009-02-20 18:31:08 +00:00
switch_mutex_t * state_mutex ;
2012-11-15 19:16:50 +00:00
switch_mutex_t * thread_mutex ;
2006-04-28 19:46:57 +00:00
switch_mutex_t * profile_mutex ;
2006-04-29 06:05:03 +00:00
switch_core_session_t * session ;
2006-04-29 23:43:28 +00:00
switch_channel_state_t state ;
2007-12-08 00:14:21 +00:00
switch_channel_state_t running_state ;
2010-06-05 00:03:36 +00:00
switch_channel_callstate_t callstate ;
2009-08-26 17:42:36 +00:00
uint32_t flags [ CF_FLAG_MAX ] ;
2009-10-14 19:26:10 +00:00
uint32_t caps [ CC_FLAG_MAX ] ;
2008-12-11 15:20:24 +00:00
uint8_t state_flags [ CF_FLAG_MAX ] ;
2008-12-04 04:46:10 +00:00
uint32_t private_flags ;
2006-04-29 06:05:03 +00:00
switch_caller_profile_t * caller_profile ;
const switch_state_handler_table_t * state_handlers [ SWITCH_MAX_STATE_HANDLERS ] ;
2006-02-07 20:47:15 +00:00
int state_handler_index ;
2007-09-29 01:06:08 +00:00
switch_event_t * variables ;
2011-06-15 18:03:39 +00:00
switch_event_t * scope_variables ;
2006-09-07 03:58:01 +00:00
switch_hash_t * private_hash ;
2010-07-22 19:37:21 +00:00
switch_hash_t * app_flag_hash ;
2006-04-21 23:16:26 +00:00
switch_call_cause_t hangup_cause ;
2007-04-28 21:48:03 +00:00
int vi ;
2007-12-15 00:39:53 +00:00
int event_count ;
2008-02-26 23:29:58 +00:00
int profile_index ;
2010-05-03 17:29:56 +00:00
opaque_channel_flag_t opaque_flags ;
2011-08-04 22:20:02 +00:00
switch_originator_type_t last_profile_type ;
2011-08-31 20:33:53 +00:00
switch_caller_extension_t * queued_extension ;
2012-01-09 18:47:47 +00:00
switch_event_t * app_list ;
switch_event_t * api_list ;
switch_event_t * var_list ;
2012-09-07 23:17:57 +00:00
switch_hold_record_t * hold_record ;
2013-06-05 16:19:44 +00:00
switch_device_node_t * device_node ;
char * device_id ;
2019-03-07 15:26:34 +00:00
switch_event_t * log_tags ;
2005-11-19 20:07:43 +00:00
} ;
2013-06-05 16:19:44 +00:00
static void process_device_hup ( switch_channel_t * channel ) ;
static void switch_channel_check_device_state ( switch_channel_t * channel , switch_channel_callstate_t callstate ) ;
2012-09-07 23:17:57 +00:00
SWITCH_DECLARE ( switch_hold_record_t * ) switch_channel_get_hold_record ( switch_channel_t * channel )
{
return channel - > hold_record ;
}
2010-06-05 00:03:36 +00:00
2007-05-12 14:48:14 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_cause2str ( switch_call_cause_t cause )
2006-04-22 18:12:17 +00:00
{
uint8_t x ;
2007-05-12 14:48:14 +00:00
const char * str = " UNKNOWN " ;
2006-04-22 18:12:17 +00:00
2008-05-27 04:30:03 +00:00
for ( x = 0 ; x < ( sizeof ( CAUSE_CHART ) / sizeof ( struct switch_cause_table ) ) - 1 ; x + + ) {
2006-04-22 18:12:17 +00:00
if ( CAUSE_CHART [ x ] . cause = = cause ) {
2007-05-12 14:48:14 +00:00
str = CAUSE_CHART [ x ] . name ;
2008-05-21 20:00:00 +00:00
break ;
2006-04-22 18:12:17 +00:00
}
}
return str ;
}
2007-05-12 14:48:14 +00:00
SWITCH_DECLARE ( switch_call_cause_t ) switch_channel_str2cause ( const char * str )
2006-04-22 18:12:17 +00:00
{
uint8_t x ;
2016-01-12 22:29:37 +00:00
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING ;
if ( ! zstr ( str ) ) {
if ( * str > 47 & & * str < 58 ) {
cause = atoi ( str ) ;
} else {
for ( x = 0 ; x < ( sizeof ( CAUSE_CHART ) / sizeof ( struct switch_cause_table ) ) - 1 & & CAUSE_CHART [ x ] . name ; x + + ) {
if ( ! strcasecmp ( CAUSE_CHART [ x ] . name , str ) ) {
cause = CAUSE_CHART [ x ] . cause ;
break ;
}
2007-07-03 21:05:41 +00:00
}
2006-04-22 18:12:17 +00:00
}
}
2016-01-12 22:29:37 +00:00
2006-04-22 18:12:17 +00:00
return cause ;
}
2006-04-29 06:05:03 +00:00
SWITCH_DECLARE ( switch_call_cause_t ) switch_channel_get_cause ( switch_channel_t * channel )
2006-04-22 18:12:17 +00:00
{
return channel - > hangup_cause ;
}
2008-11-27 04:02:57 +00:00
2011-07-06 21:45:25 +00:00
SWITCH_DECLARE ( switch_call_cause_t * ) switch_channel_get_cause_ptr ( switch_channel_t * channel )
{
return & channel - > hangup_cause ;
}
2010-06-05 00:03:36 +00:00
struct switch_callstate_table {
const char * name ;
switch_channel_callstate_t callstate ;
} ;
2011-02-13 23:04:17 +00:00
static struct switch_callstate_table CALLSTATE_CHART [ ] = {
2016-03-17 13:55:00 +00:00
{ " DOWN " , CCS_DOWN } ,
{ " DIALING " , CCS_DIALING } ,
{ " RINGING " , CCS_RINGING } ,
{ " EARLY " , CCS_EARLY } ,
{ " ACTIVE " , CCS_ACTIVE } ,
{ " HELD " , CCS_HELD } ,
{ " RING_WAIT " , CCS_RING_WAIT } ,
{ " HANGUP " , CCS_HANGUP } ,
2014-05-30 19:30:59 +00:00
{ " UNHELD " , CCS_UNHELD } ,
2016-03-17 13:55:00 +00:00
{ NULL , 0 }
2013-06-05 16:19:44 +00:00
} ;
struct switch_device_state_table {
const char * name ;
switch_device_state_t device_state ;
} ;
static struct switch_device_state_table DEVICE_STATE_CHART [ ] = {
2016-03-17 13:55:00 +00:00
{ " DOWN " , SDS_DOWN } ,
{ " RINGING " , SDS_RINGING } ,
{ " ACTIVE " , SDS_ACTIVE } ,
{ " ACTIVE_MULTI " , SDS_ACTIVE_MULTI } ,
{ " HELD " , SDS_HELD } ,
{ " UNHELD " , SDS_UNHELD } ,
{ " HANGUP " , SDS_HANGUP } ,
{ NULL , 0 }
2010-06-05 00:03:36 +00:00
} ;
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( void ) switch_channel_perform_set_callstate ( switch_channel_t * channel , switch_channel_callstate_t callstate ,
2010-06-07 23:01:02 +00:00
const char * file , const char * func , int line )
2010-06-05 00:03:36 +00:00
{
2010-06-07 23:01:02 +00:00
switch_event_t * event ;
switch_channel_callstate_t o_callstate = channel - > callstate ;
2014-05-30 19:30:59 +00:00
if ( o_callstate = = callstate | | o_callstate = = CCS_HANGUP ) return ;
2017-01-06 07:10:15 +00:00
2010-06-05 00:03:36 +00:00
channel - > callstate = callstate ;
2013-06-05 16:19:44 +00:00
if ( channel - > device_node ) {
channel - > device_node - > callstate = callstate ;
}
2010-06-07 23:01:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_DEBUG ,
2017-01-06 07:10:15 +00:00
" (%s) Callstate Change %s -> %s \n " , channel - > name ,
2010-06-07 23:01:02 +00:00
switch_channel_callstate2str ( o_callstate ) , switch_channel_callstate2str ( callstate ) ) ;
2013-06-11 00:13:05 +00:00
2014-05-30 19:30:59 +00:00
switch_channel_check_device_state ( channel , channel - > callstate ) ;
2013-10-24 01:45:29 +00:00
2010-06-07 23:01:02 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_CALLSTATE ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Original-Channel-Call-State " , switch_channel_callstate2str ( o_callstate ) ) ;
2011-07-13 01:36:36 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Channel-Call-State-Number " , " %d " , callstate ) ;
2010-06-07 23:01:02 +00:00
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2010-06-05 00:03:36 +00:00
}
SWITCH_DECLARE ( switch_channel_callstate_t ) switch_channel_get_callstate ( switch_channel_t * channel )
{
return channel - > callstate ;
}
SWITCH_DECLARE ( const char * ) switch_channel_callstate2str ( switch_channel_callstate_t callstate )
{
uint8_t x ;
const char * str = " UNKNOWN " ;
2011-02-13 23:04:17 +00:00
for ( x = 0 ; x < ( sizeof ( CALLSTATE_CHART ) / sizeof ( struct switch_cause_table ) ) - 1 ; x + + ) {
if ( CALLSTATE_CHART [ x ] . callstate = = callstate ) {
str = CALLSTATE_CHART [ x ] . name ;
2010-06-05 00:03:36 +00:00
break ;
}
}
return str ;
}
2013-06-05 16:19:44 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_device_state2str ( switch_device_state_t device_state )
{
uint8_t x ;
const char * str = " UNKNOWN " ;
for ( x = 0 ; x < ( sizeof ( DEVICE_STATE_CHART ) / sizeof ( struct switch_cause_table ) ) - 1 ; x + + ) {
if ( DEVICE_STATE_CHART [ x ] . device_state = = device_state ) {
str = DEVICE_STATE_CHART [ x ] . name ;
break ;
}
}
return str ;
}
2011-02-13 23:04:17 +00:00
2012-10-22 14:24:45 +00:00
SWITCH_DECLARE ( switch_channel_callstate_t ) switch_channel_str2callstate ( const char * str )
2010-06-05 00:03:36 +00:00
{
uint8_t x ;
2012-01-08 20:19:16 +00:00
switch_channel_callstate_t callstate = ( switch_channel_callstate_t ) SWITCH_CAUSE_NONE ;
2010-06-05 00:03:36 +00:00
if ( * str > 47 & & * str < 58 ) {
callstate = atoi ( str ) ;
} else {
2011-02-13 23:04:17 +00:00
for ( x = 0 ; x < ( sizeof ( CALLSTATE_CHART ) / sizeof ( struct switch_callstate_table ) ) - 1 & & CALLSTATE_CHART [ x ] . name ; x + + ) {
if ( ! strcasecmp ( CALLSTATE_CHART [ x ] . name , str ) ) {
callstate = CALLSTATE_CHART [ x ] . callstate ;
2010-06-05 00:03:36 +00:00
break ;
}
}
}
2012-10-22 14:24:45 +00:00
return callstate ;
2010-06-05 00:03:36 +00:00
}
2010-02-18 17:26:15 +00:00
SWITCH_DECLARE ( void ) switch_channel_perform_audio_sync ( switch_channel_t * channel , const char * file , const char * func , int line )
2008-11-27 04:02:57 +00:00
{
2012-11-29 05:12:35 +00:00
if ( switch_channel_media_up ( channel ) ) {
2015-12-23 22:03:35 +00:00
switch_core_session_message_t * msg = NULL ;
msg = switch_core_session_alloc ( channel - > session , sizeof ( * msg ) ) ;
MESSAGE_STAMP_FFL ( msg ) ;
msg - > message_id = SWITCH_MESSAGE_INDICATE_AUDIO_SYNC ;
msg - > from = channel - > name ;
msg - > _file = file ;
msg - > _func = func ;
msg - > _line = line ;
switch_core_session_queue_message ( channel - > session , msg ) ;
2008-11-27 04:02:57 +00:00
}
}
2015-05-01 20:40:50 +00:00
SWITCH_DECLARE ( void ) switch_channel_perform_video_sync ( switch_channel_t * channel , const char * file , const char * func , int line )
{
2015-12-23 22:03:35 +00:00
2015-05-01 20:40:50 +00:00
if ( switch_channel_media_up ( channel ) ) {
2015-12-23 22:03:35 +00:00
switch_core_session_message_t * msg = NULL ;
msg = switch_core_session_alloc ( channel - > session , sizeof ( * msg ) ) ;
MESSAGE_STAMP_FFL ( msg ) ;
msg - > message_id = SWITCH_MESSAGE_INDICATE_VIDEO_SYNC ;
msg - > from = channel - > name ;
msg - > _file = file ;
msg - > _func = func ;
msg - > _line = line ;
2016-01-07 22:39:06 +00:00
switch_core_session_request_video_refresh ( channel - > session ) ;
2015-12-23 22:03:35 +00:00
switch_core_session_queue_message ( channel - > session , msg ) ;
2015-05-01 20:40:50 +00:00
}
}
2008-11-27 04:02:57 +00:00
2008-09-24 21:19:29 +00:00
SWITCH_DECLARE ( switch_call_cause_t ) switch_channel_cause_q850 ( switch_call_cause_t cause )
{
if ( cause < = SWITCH_CAUSE_INTERWORKING ) {
return cause ;
} else {
return SWITCH_CAUSE_NORMAL_CLEARING ;
}
}
SWITCH_DECLARE ( switch_call_cause_t ) switch_channel_get_cause_q850 ( switch_channel_t * channel )
{
return switch_channel_cause_q850 ( channel - > hangup_cause ) ;
}
2006-04-29 06:05:03 +00:00
SWITCH_DECLARE ( switch_channel_timetable_t * ) switch_channel_get_timetable ( switch_channel_t * channel )
2006-02-24 22:22:43 +00:00
{
2007-03-29 22:31:56 +00:00
switch_channel_timetable_t * times = NULL ;
2006-12-01 15:26:37 +00:00
2007-03-29 22:31:56 +00:00
if ( channel - > caller_profile ) {
switch_mutex_lock ( channel - > profile_mutex ) ;
times = channel - > caller_profile - > times ;
switch_mutex_unlock ( channel - > profile_mutex ) ;
}
2006-12-01 15:26:37 +00:00
return times ;
2006-02-24 22:22:43 +00:00
}
2005-11-19 20:07:43 +00:00
2013-10-15 21:24:32 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_direction ( switch_channel_t * channel , switch_call_direction_t direction )
{
if ( ! switch_core_session_in_thread ( channel - > session ) ) {
2013-10-31 20:28:24 +00:00
channel - > direction = channel - > logical_direction = direction ;
2014-07-29 17:20:31 +00:00
switch_channel_set_variable ( channel , " direction " , switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ? " outbound " : " inbound " ) ;
2013-10-15 21:24:32 +00:00
}
}
2009-04-21 17:47:22 +00:00
SWITCH_DECLARE ( switch_call_direction_t ) switch_channel_direction ( switch_channel_t * channel )
{
return channel - > direction ;
}
2013-10-31 20:28:24 +00:00
SWITCH_DECLARE ( switch_call_direction_t ) switch_channel_logical_direction ( switch_channel_t * channel )
{
return channel - > logical_direction ;
}
2009-02-23 16:31:59 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_alloc ( switch_channel_t * * channel , switch_call_direction_t direction , switch_memory_pool_t * pool )
2005-11-19 20:07:43 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( pool ! = NULL ) ;
2005-11-19 20:07:43 +00:00
2006-04-29 06:05:03 +00:00
if ( ( ( * channel ) = switch_core_alloc ( pool , sizeof ( switch_channel_t ) ) ) = = 0 ) {
2005-11-19 20:07:43 +00:00
return SWITCH_STATUS_MEMERR ;
}
2008-01-28 07:26:10 +00:00
2009-03-24 23:44:03 +00:00
switch_event_create_plain ( & ( * channel ) - > variables , SWITCH_EVENT_CHANNEL_DATA ) ;
2008-01-28 07:26:10 +00:00
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & ( * channel ) - > private_hash ) ;
2009-02-23 16:31:59 +00:00
switch_queue_create ( & ( * channel ) - > dtmf_queue , SWITCH_DTMF_LOG_LEN , pool ) ;
switch_queue_create ( & ( * channel ) - > dtmf_log_queue , SWITCH_DTMF_LOG_LEN , pool ) ;
2006-09-08 18:57:24 +00:00
2005-12-06 21:25:56 +00:00
switch_mutex_init ( & ( * channel ) - > dtmf_mutex , SWITCH_MUTEX_NESTED , pool ) ;
2006-06-22 23:56:09 +00:00
switch_mutex_init ( & ( * channel ) - > flag_mutex , SWITCH_MUTEX_NESTED , pool ) ;
2009-02-20 18:31:08 +00:00
switch_mutex_init ( & ( * channel ) - > state_mutex , SWITCH_MUTEX_NESTED , pool ) ;
2012-11-15 19:16:50 +00:00
switch_mutex_init ( & ( * channel ) - > thread_mutex , SWITCH_MUTEX_NESTED , pool ) ;
2006-04-28 19:46:57 +00:00
switch_mutex_init ( & ( * channel ) - > profile_mutex , SWITCH_MUTEX_NESTED , pool ) ;
2008-07-03 22:51:09 +00:00
( * channel ) - > hangup_cause = SWITCH_CAUSE_NONE ;
2008-02-26 23:29:58 +00:00
( * channel ) - > name = " " ;
2013-10-31 20:28:24 +00:00
( * channel ) - > direction = ( * channel ) - > logical_direction = direction ;
2010-04-26 09:18:46 +00:00
switch_channel_set_variable ( * channel , " direction " , switch_channel_direction ( * channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ? " outbound " : " inbound " ) ;
2005-12-22 01:57:32 +00:00
2005-11-19 20:07:43 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_dtmf_lock ( switch_channel_t * channel )
2012-11-26 19:52:06 +00:00
{
return switch_mutex_lock ( channel - > dtmf_mutex ) ;
}
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_try_dtmf_lock ( switch_channel_t * channel )
2012-11-26 19:52:06 +00:00
{
return switch_mutex_trylock ( channel - > dtmf_mutex ) ;
}
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_dtmf_unlock ( switch_channel_t * channel )
2012-11-26 19:52:06 +00:00
{
return switch_mutex_unlock ( channel - > dtmf_mutex ) ;
}
2006-04-29 06:05:03 +00:00
SWITCH_DECLARE ( switch_size_t ) switch_channel_has_dtmf ( switch_channel_t * channel )
2005-11-19 20:07:43 +00:00
{
2006-03-30 23:02:50 +00:00
switch_size_t has ;
2005-11-19 20:07:43 +00:00
2005-12-06 21:25:56 +00:00
switch_mutex_lock ( channel - > dtmf_mutex ) ;
2007-12-22 00:32:20 +00:00
has = switch_queue_size ( channel - > dtmf_queue ) ;
2005-12-06 21:25:56 +00:00
switch_mutex_unlock ( channel - > dtmf_mutex ) ;
return has ;
2005-11-19 20:07:43 +00:00
}
2013-02-26 21:32:19 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_queue_dtmf ( switch_channel_t * channel , const switch_dtmf_t * dtmf )
2005-11-19 20:07:43 +00:00
{
2006-04-29 23:43:28 +00:00
switch_status_t status ;
2007-12-22 00:32:20 +00:00
void * pop ;
2011-08-17 22:25:56 +00:00
switch_dtmf_t new_dtmf = { 0 } ;
2013-02-26 17:49:17 +00:00
switch_bool_t sensitive = switch_true ( switch_channel_get_variable_dup ( channel , SWITCH_SENSITIVE_DTMF_VARIABLE , SWITCH_FALSE , - 1 ) ) ;
2008-05-27 04:30:03 +00:00
2008-02-21 21:38:49 +00:00
switch_assert ( dtmf ) ;
2005-12-21 22:25:22 +00:00
2008-05-27 04:30:03 +00:00
switch_mutex_lock ( channel - > dtmf_mutex ) ;
2008-02-21 21:38:49 +00:00
new_dtmf = * dtmf ;
2008-05-27 04:30:03 +00:00
2013-02-26 21:32:19 +00:00
if ( sensitive ) {
switch_set_flag ( ( & new_dtmf ) , DTMF_FLAG_SENSITIVE ) ;
}
2007-06-12 21:00:26 +00:00
if ( ( status = switch_core_session_recv_dtmf ( channel - > session , dtmf ) ! = SWITCH_STATUS_SUCCESS ) ) {
goto done ;
}
2006-03-30 23:02:50 +00:00
2008-02-21 21:38:49 +00:00
if ( is_dtmf ( new_dtmf . digit ) ) {
2007-12-22 00:32:20 +00:00
switch_dtmf_t * dt ;
int x = 0 ;
2013-02-26 17:49:17 +00:00
if ( ! sensitive ) {
2015-10-02 15:41:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_INFO , " RECV DTMF %c:%d \n " , new_dtmf . digit , new_dtmf . duration ) ;
2013-02-26 17:49:17 +00:00
}
2011-11-14 18:37:45 +00:00
if ( new_dtmf . digit ! = ' w ' & & new_dtmf . digit ! = ' W ' ) {
if ( new_dtmf . duration > switch_core_max_dtmf_duration ( 0 ) ) {
2013-02-26 17:49:17 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_DEBUG , " %s EXCESSIVE DTMF DIGIT LEN [%d] \n " ,
switch_channel_get_name ( channel ) , new_dtmf . duration ) ;
2011-11-14 18:37:45 +00:00
new_dtmf . duration = switch_core_max_dtmf_duration ( 0 ) ;
} else if ( new_dtmf . duration < switch_core_min_dtmf_duration ( 0 ) ) {
2013-02-26 17:49:17 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_DEBUG , " %s SHORT DTMF DIGIT LEN [%d] \n " ,
switch_channel_get_name ( channel ) , new_dtmf . duration ) ;
2011-11-14 18:37:45 +00:00
new_dtmf . duration = switch_core_min_dtmf_duration ( 0 ) ;
2017-01-06 07:10:15 +00:00
}
2011-11-14 18:37:45 +00:00
}
2017-01-06 07:10:15 +00:00
2011-11-14 18:37:45 +00:00
if ( ! new_dtmf . duration ) {
2008-04-18 17:03:34 +00:00
new_dtmf . duration = switch_core_default_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
}
2017-01-06 07:10:15 +00:00
2008-05-27 04:30:03 +00:00
2007-12-22 00:32:20 +00:00
switch_zmalloc ( dt , sizeof ( * dt ) ) ;
2008-02-21 21:38:49 +00:00
* dt = new_dtmf ;
2013-10-15 21:24:32 +00:00
2007-12-22 00:32:20 +00:00
while ( switch_queue_trypush ( channel - > dtmf_queue , dt ) ! = SWITCH_STATUS_SUCCESS ) {
2009-02-27 19:29:52 +00:00
if ( switch_queue_trypop ( channel - > dtmf_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
free ( pop ) ;
}
2007-12-22 00:32:20 +00:00
if ( + + x > 100 ) {
status = SWITCH_STATUS_FALSE ;
free ( dt ) ;
2008-01-28 07:26:10 +00:00
goto done ;
2007-12-22 00:32:20 +00:00
}
2006-05-04 00:07:20 +00:00
}
}
2008-01-28 07:26:10 +00:00
2007-12-22 00:32:20 +00:00
status = SWITCH_STATUS_SUCCESS ;
2007-06-12 21:00:26 +00:00
2008-05-27 04:30:03 +00:00
done :
2007-06-12 21:00:26 +00:00
2005-12-06 21:25:56 +00:00
switch_mutex_unlock ( channel - > dtmf_mutex ) ;
2013-10-15 21:24:32 +00:00
switch_core_media_break ( channel - > session , SWITCH_MEDIA_TYPE_AUDIO ) ;
2005-12-06 21:25:56 +00:00
return status ;
2005-11-19 20:07:43 +00:00
}
2008-01-12 20:30:48 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_queue_dtmf_string ( switch_channel_t * channel , const char * dtmf_string )
{
char * p ;
2011-08-25 14:27:39 +00:00
switch_dtmf_t dtmf = { 0 , switch_core_default_dtmf_duration ( 0 ) , 0 , SWITCH_DTMF_APP } ;
2019-04-24 18:27:27 +00:00
int sent = 0 , dur , bad_input = 0 ;
2008-01-12 20:30:48 +00:00
char * string ;
int i , argc ;
char * argv [ 256 ] ;
2009-10-23 16:03:42 +00:00
if ( zstr ( dtmf_string ) ) {
2019-04-24 18:27:27 +00:00
return SWITCH_STATUS_GENERR ;
2008-01-12 20:30:48 +00:00
}
2011-09-13 21:19:00 +00:00
dtmf . flags = DTMF_FLAG_SKIP_PROCESS ;
if ( * dtmf_string = = ' ~ ' ) {
2010-10-08 18:50:15 +00:00
dtmf_string + + ;
2011-09-13 21:19:00 +00:00
dtmf . flags = 0 ;
2010-10-08 18:50:15 +00:00
}
2008-01-12 20:30:48 +00:00
string = switch_core_session_strdup ( channel - > session , dtmf_string ) ;
argc = switch_separate_string ( string , ' + ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
2008-01-28 07:26:10 +00:00
2008-05-27 04:30:03 +00:00
for ( i = 0 ; i < argc ; i + + ) {
2008-04-18 17:03:34 +00:00
dtmf . duration = switch_core_default_dtmf_duration ( 0 ) ;
dur = switch_core_default_dtmf_duration ( 0 ) / 8 ;
2008-01-12 20:30:48 +00:00
if ( ( p = strchr ( argv [ i ] , ' @ ' ) ) ) {
* p + + = ' \0 ' ;
2011-09-16 17:34:24 +00:00
if ( ( dur = atoi ( p ) ) > ( int ) switch_core_min_dtmf_duration ( 0 ) / 8 ) {
2008-01-12 20:30:48 +00:00
dtmf . duration = dur * 8 ;
}
}
for ( p = argv [ i ] ; p & & * p ; p + + ) {
if ( is_dtmf ( * p ) ) {
dtmf . digit = * p ;
2011-09-13 21:19:00 +00:00
if ( dtmf . duration > switch_core_max_dtmf_duration ( 0 ) ) {
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_WARNING , " EXCESSIVE DTMF DIGIT LEN %c %d \n " , dtmf . digit , dtmf . duration ) ;
dtmf . duration = switch_core_max_dtmf_duration ( 0 ) ;
} else if ( dtmf . duration < switch_core_min_dtmf_duration ( 0 ) ) {
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_WARNING , " SHORT DTMF DIGIT LEN %c %d \n " , dtmf . digit , dtmf . duration ) ;
dtmf . duration = switch_core_min_dtmf_duration ( 0 ) ;
} else if ( ! dtmf . duration ) {
dtmf . duration = switch_core_default_dtmf_duration ( 0 ) ;
}
2008-01-12 20:30:48 +00:00
if ( switch_channel_queue_dtmf ( channel , & dtmf ) = = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_DEBUG , " %s Queue dtmf \n digit=%c ms=%u samples=%u \n " ,
2008-05-27 04:30:03 +00:00
switch_channel_get_name ( channel ) , dtmf . digit , dur , dtmf . duration ) ;
2008-01-12 20:30:48 +00:00
sent + + ;
}
2019-04-24 18:27:27 +00:00
} else {
bad_input + + ;
2008-01-12 20:30:48 +00:00
}
}
2008-01-28 07:26:10 +00:00
2008-01-12 20:30:48 +00:00
}
2019-04-24 18:27:27 +00:00
if ( sent ) {
return SWITCH_STATUS_SUCCESS ;
}
return bad_input ? SWITCH_STATUS_GENERR : SWITCH_STATUS_FALSE ;
2008-01-12 20:30:48 +00:00
}
2007-12-22 00:32:20 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_dequeue_dtmf ( switch_channel_t * channel , switch_dtmf_t * dtmf )
2005-11-19 20:07:43 +00:00
{
2006-04-29 01:00:52 +00:00
switch_event_t * event ;
2007-12-22 00:32:20 +00:00
void * pop ;
switch_dtmf_t * dt ;
switch_status_t status = SWITCH_STATUS_FALSE ;
2013-02-26 17:49:17 +00:00
int sensitive = 0 ;
2005-11-19 20:07:43 +00:00
2005-12-06 21:25:56 +00:00
switch_mutex_lock ( channel - > dtmf_mutex ) ;
2007-12-22 00:32:20 +00:00
if ( switch_queue_trypop ( channel - > dtmf_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
dt = ( switch_dtmf_t * ) pop ;
* dtmf = * dt ;
2013-02-26 17:49:17 +00:00
sensitive = switch_test_flag ( dtmf , DTMF_FLAG_SENSITIVE ) ;
2009-02-23 16:31:59 +00:00
2013-02-26 17:49:17 +00:00
if ( ! sensitive & & switch_queue_trypush ( channel - > dtmf_log_queue , dt ) ! = SWITCH_STATUS_SUCCESS ) {
2010-02-06 03:38:24 +00:00
free ( dt ) ;
2009-02-23 16:31:59 +00:00
}
2010-02-06 03:38:24 +00:00
2009-02-23 16:31:59 +00:00
dt = NULL ;
2008-02-21 21:38:49 +00:00
2008-04-18 17:03:34 +00:00
if ( dtmf - > duration > switch_core_max_dtmf_duration ( 0 ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_WARNING , " %s EXCESSIVE DTMF DIGIT [%c] LEN [%d] \n " ,
2013-02-26 17:49:17 +00:00
switch_channel_get_name ( channel ) , sensitive ? ' S ' : dtmf - > digit , dtmf - > duration ) ;
2008-04-18 17:03:34 +00:00
dtmf - > duration = switch_core_max_dtmf_duration ( 0 ) ;
2009-09-16 21:24:22 +00:00
} else if ( dtmf - > duration < switch_core_min_dtmf_duration ( 0 ) ) {
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_WARNING , " %s SHORT DTMF DIGIT [%c] LEN [%d] \n " ,
2013-02-26 17:49:17 +00:00
switch_channel_get_name ( channel ) , sensitive ? ' S ' : dtmf - > digit , dtmf - > duration ) ;
2009-09-16 21:24:22 +00:00
dtmf - > duration = switch_core_min_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
} else if ( ! dtmf - > duration ) {
2008-04-18 17:03:34 +00:00
dtmf - > duration = switch_core_default_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
}
2007-12-22 00:32:20 +00:00
status = SWITCH_STATUS_SUCCESS ;
2005-11-19 20:07:43 +00:00
}
2005-12-06 21:25:56 +00:00
switch_mutex_unlock ( channel - > dtmf_mutex ) ;
2008-01-28 07:26:10 +00:00
2013-02-26 17:49:17 +00:00
if ( ! sensitive & & status = = SWITCH_STATUS_SUCCESS & & switch_event_create ( & event , SWITCH_EVENT_DTMF ) = = SWITCH_STATUS_SUCCESS ) {
2015-04-01 15:00:43 +00:00
const char * dtmf_source_str = NULL ;
2005-12-21 22:25:22 +00:00
switch_channel_event_set_data ( channel , event ) ;
2007-12-22 00:32:20 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " DTMF-Digit " , " %c " , dtmf - > digit ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " DTMF-Duration " , " %u " , dtmf - > duration ) ;
2015-04-01 15:00:43 +00:00
switch ( dtmf - > source ) {
case SWITCH_DTMF_INBAND_AUDIO : /* From audio */
dtmf_source_str = " INBAND_AUDIO " ;
break ;
case SWITCH_DTMF_RTP : /* From RTP as a telephone event */
dtmf_source_str = " RTP " ;
break ;
case SWITCH_DTMF_ENDPOINT : /* From endpoint signaling */
dtmf_source_str = " ENDPOINT " ;
break ;
case SWITCH_DTMF_APP : /* Injected by application */
dtmf_source_str = " APP " ;
break ;
case SWITCH_DTMF_UNKNOWN : /* Unknown source */
default :
dtmf_source_str = " UNKNOWN " ;
break ;
}
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " DTMF-Source " , " %s " , dtmf_source_str ) ;
2009-02-21 23:19:58 +00:00
if ( switch_channel_test_flag ( channel , CF_DIVERT_EVENTS ) ) {
switch_core_session_queue_event ( channel - > session , & event ) ;
} else {
switch_event_fire ( & event ) ;
}
2005-12-21 22:25:22 +00:00
}
2005-12-06 21:25:56 +00:00
2007-12-22 00:32:20 +00:00
return status ;
}
SWITCH_DECLARE ( switch_size_t ) switch_channel_dequeue_dtmf_string ( switch_channel_t * channel , char * dtmf_str , switch_size_t len )
{
switch_size_t x = 0 ;
2008-05-27 04:30:03 +00:00
switch_dtmf_t dtmf = { 0 } ;
2007-12-22 00:32:20 +00:00
memset ( dtmf_str , 0 , len ) ;
2008-05-27 04:30:03 +00:00
while ( x < len - 1 & & switch_channel_dequeue_dtmf ( channel , & dtmf ) = = SWITCH_STATUS_SUCCESS ) {
2007-12-22 00:32:20 +00:00
dtmf_str [ x + + ] = dtmf . digit ;
}
return x ;
2005-11-19 20:07:43 +00:00
}
2007-12-22 00:32:20 +00:00
SWITCH_DECLARE ( void ) switch_channel_flush_dtmf ( switch_channel_t * channel )
{
void * pop ;
2009-02-21 22:50:35 +00:00
2007-12-22 00:32:20 +00:00
switch_mutex_lock ( channel - > dtmf_mutex ) ;
2008-05-27 04:30:03 +00:00
while ( switch_queue_trypop ( channel - > dtmf_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
2009-02-23 16:31:59 +00:00
switch_dtmf_t * dt = ( switch_dtmf_t * ) pop ;
if ( channel - > state > = CS_HANGUP | | switch_queue_trypush ( channel - > dtmf_log_queue , dt ) ! = SWITCH_STATUS_SUCCESS ) {
free ( dt ) ;
}
2007-12-22 00:32:20 +00:00
}
switch_mutex_unlock ( channel - > dtmf_mutex ) ;
}
2006-09-08 18:57:24 +00:00
SWITCH_DECLARE ( void ) switch_channel_uninit ( switch_channel_t * channel )
{
2009-02-23 16:31:59 +00:00
void * pop ;
2007-12-22 02:15:50 +00:00
switch_channel_flush_dtmf ( channel ) ;
2009-02-23 16:31:59 +00:00
while ( switch_queue_trypop ( channel - > dtmf_log_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
switch_safe_free ( pop ) ;
}
2012-08-16 17:09:19 +00:00
if ( channel - > private_hash ) {
switch_core_hash_destroy ( & channel - > private_hash ) ;
}
2010-07-23 05:36:40 +00:00
if ( channel - > app_flag_hash ) {
switch_core_hash_destroy ( & channel - > app_flag_hash ) ;
}
2012-08-16 17:09:19 +00:00
2008-10-30 22:40:39 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2007-09-29 01:06:08 +00:00
switch_event_destroy ( & channel - > variables ) ;
2012-01-09 18:47:47 +00:00
switch_event_destroy ( & channel - > api_list ) ;
switch_event_destroy ( & channel - > var_list ) ;
switch_event_destroy ( & channel - > app_list ) ;
2019-03-07 15:26:34 +00:00
if ( channel - > log_tags ) {
switch_event_destroy ( & channel - > log_tags ) ;
}
2008-10-30 22:40:39 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2006-09-08 18:57:24 +00:00
}
2007-03-30 00:15:25 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_init ( switch_channel_t * channel , switch_core_session_t * session , switch_channel_state_t state ,
2008-12-11 15:20:24 +00:00
switch_channel_flag_t flag )
2005-11-19 20:07:43 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2005-11-19 20:07:43 +00:00
channel - > state = state ;
2008-12-11 15:20:24 +00:00
switch_channel_set_flag ( channel , flag ) ;
2005-11-19 20:07:43 +00:00
channel - > session = session ;
2007-12-19 23:24:55 +00:00
channel - > running_state = CS_NONE ;
2005-11-19 20:07:43 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2010-06-18 18:39:55 +00:00
SWITCH_DECLARE ( void ) switch_channel_perform_presence ( switch_channel_t * channel , const char * rpid , const char * status , const char * id ,
const char * file , const char * func , int line )
2006-10-21 04:58:15 +00:00
{
switch_event_t * event ;
switch_event_types_t type = SWITCH_EVENT_PRESENCE_IN ;
2009-12-24 05:44:23 +00:00
const char * call_info = NULL ;
2012-02-15 00:59:37 +00:00
char * call_info_state = " active " ;
2006-10-21 04:58:15 +00:00
2012-07-03 13:05:41 +00:00
if ( switch_channel_test_flag ( channel , CF_NO_PRESENCE ) ) {
return ;
}
2006-10-21 04:58:15 +00:00
if ( ! status ) {
type = SWITCH_EVENT_PRESENCE_OUT ;
2014-04-28 20:21:45 +00:00
status = " idle " ;
2006-10-21 04:58:15 +00:00
}
2008-08-25 16:30:28 +00:00
if ( ! id ) {
id = switch_channel_get_variable ( channel , " presence_id " ) ;
}
2006-10-21 04:58:15 +00:00
if ( ! id ) {
return ;
}
2009-12-24 05:44:23 +00:00
call_info = switch_channel_get_variable ( channel , " presence_call_info " ) ;
2006-10-21 04:58:15 +00:00
if ( switch_event_create ( & event , type ) = = SWITCH_STATUS_SUCCESS ) {
2007-12-15 00:39:53 +00:00
switch_channel_event_set_data ( channel , event ) ;
2011-10-22 01:00:34 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " proto " , " any " ) ;
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " login " , __FILE__ ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " from " , id ) ;
2006-10-21 04:58:15 +00:00
if ( type = = SWITCH_EVENT_PRESENCE_IN ) {
if ( ! rpid ) {
rpid = " unknown " ;
}
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " rpid " , rpid ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " status " , status ) ;
2006-10-21 04:58:15 +00:00
}
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alt_event_type " , " dialog " ) ;
2010-02-06 03:38:24 +00:00
2010-01-07 06:09:35 +00:00
2013-09-10 18:14:30 +00:00
if ( ! strcasecmp ( status , " idle " ) | | ! switch_channel_up_nosig ( channel ) ) {
2012-02-15 00:59:37 +00:00
call_info_state = " idle " ;
} else if ( ! strcasecmp ( status , " hold-private " ) ) {
call_info_state = " held-private " ;
} else if ( ! strcasecmp ( status , " hold " ) ) {
call_info_state = " held " ;
} else if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
if ( channel - > direction = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
call_info_state = " progressing " ;
} else {
2013-09-10 21:55:31 +00:00
if ( switch_channel_test_flag ( channel , CF_SLA_INTERCEPT ) ) {
call_info_state = " idle " ;
} else {
call_info_state = " alerting " ;
}
2012-02-15 00:59:37 +00:00
}
}
2017-01-06 07:10:15 +00:00
2012-02-15 00:59:37 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " presence-call-info-state " , call_info_state ) ;
2017-01-06 07:10:15 +00:00
2012-02-15 00:59:37 +00:00
if ( call_info ) {
2009-12-24 05:44:23 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " presence-call-info " , call_info ) ;
}
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " presence-call-direction " ,
channel - > direction = = SWITCH_CALL_DIRECTION_OUTBOUND ? " outbound " : " inbound " ) ;
2007-12-15 00:39:53 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_count " , " %d " , channel - > event_count + + ) ;
2010-06-18 18:39:55 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Presence-Calling-File " , file ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Presence-Calling-Function " , func ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Presence-Calling-Line " , " %d " , line ) ;
2011-06-07 11:58:12 +00:00
if ( switch_true ( switch_channel_get_variable ( channel , " presence_privacy " ) ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Presence-Privacy " , " true " ) ;
}
2006-10-21 04:58:15 +00:00
switch_event_fire ( & event ) ;
}
}
2010-06-05 00:03:36 +00:00
SWITCH_DECLARE ( void ) switch_channel_mark_hold ( switch_channel_t * channel , switch_bool_t on )
{
switch_event_t * event ;
2011-04-15 19:22:45 +00:00
if ( ! ! on = = ! ! switch_channel_test_flag ( channel , CF_LEG_HOLDING ) ) {
2011-06-01 03:22:09 +00:00
goto end ;
2011-04-15 19:22:45 +00:00
}
2017-01-06 07:10:15 +00:00
2010-06-05 00:03:36 +00:00
if ( on ) {
switch_channel_set_flag ( channel , CF_LEG_HOLDING ) ;
} else {
switch_channel_clear_flag ( channel , CF_LEG_HOLDING ) ;
}
if ( switch_event_create ( & event , on ? SWITCH_EVENT_CHANNEL_HOLD : SWITCH_EVENT_CHANNEL_UNHOLD ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2011-06-01 03:22:09 +00:00
end :
if ( on ) {
if ( switch_true ( switch_channel_get_variable ( channel , " flip_record_on_hold " ) ) ) {
switch_core_session_t * other_session ;
if ( switch_core_session_get_partner ( channel - > session , & other_session ) = = SWITCH_STATUS_SUCCESS ) {
2018-03-20 08:20:37 +00:00
switch_ivr_transfer_recordings ( channel - > session , other_session ) ;
2011-06-01 03:22:09 +00:00
switch_core_session_rwunlock ( other_session ) ;
}
}
}
2010-06-05 00:03:36 +00:00
}
2011-01-05 23:53:27 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_get_hold_music ( switch_channel_t * channel )
{
2011-01-06 00:58:56 +00:00
const char * var ;
2011-01-05 23:53:27 +00:00
2011-01-06 00:58:56 +00:00
if ( ! ( var = switch_channel_get_variable ( channel , SWITCH_TEMP_HOLD_MUSIC_VARIABLE ) ) ) {
2011-01-05 23:53:27 +00:00
var = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ;
}
2012-07-26 18:17:39 +00:00
if ( ! zstr ( var ) ) {
char * expanded = switch_channel_expand_variables ( channel , var ) ;
2017-01-06 07:10:15 +00:00
2012-07-26 18:17:39 +00:00
if ( expanded ! = var ) {
var = switch_core_session_strdup ( channel - > session , expanded ) ;
free ( expanded ) ;
}
}
2011-01-05 23:53:27 +00:00
return var ;
}
SWITCH_DECLARE ( const char * ) switch_channel_get_hold_music_partner ( switch_channel_t * channel )
{
switch_core_session_t * session ;
const char * r = NULL ;
if ( switch_core_session_get_partner ( channel - > session , & session ) = = SWITCH_STATUS_SUCCESS ) {
r = switch_channel_get_hold_music ( switch_core_session_get_channel ( session ) ) ;
switch_core_session_rwunlock ( session ) ;
}
return r ;
}
2011-06-15 18:03:39 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_scope_variables ( switch_channel_t * channel , switch_event_t * * event )
{
switch_mutex_lock ( channel - > profile_mutex ) ;
2011-06-16 14:43:32 +00:00
if ( event & & * event ) { /* push */
( * event ) - > next = channel - > scope_variables ;
2011-06-15 18:03:39 +00:00
channel - > scope_variables = * event ;
* event = NULL ;
2011-06-16 14:43:32 +00:00
} else if ( channel - > scope_variables ) { /* pop */
switch_event_t * top_event = channel - > scope_variables ;
channel - > scope_variables = channel - > scope_variables - > next ;
switch_event_destroy ( & top_event ) ;
2011-06-15 18:03:39 +00:00
}
2011-06-16 14:43:32 +00:00
2011-06-15 18:03:39 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2017-01-06 07:10:15 +00:00
2011-06-15 18:03:39 +00:00
}
SWITCH_DECLARE ( switch_status_t ) switch_channel_get_scope_variables ( switch_channel_t * channel , switch_event_t * * event )
{
switch_status_t status = SWITCH_STATUS_FALSE ;
2011-06-16 14:43:32 +00:00
switch_event_t * new_event ;
2011-06-15 18:03:39 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > scope_variables ) {
2011-06-16 14:43:32 +00:00
switch_event_t * ep ;
switch_event_header_t * hp ;
switch_event_create_plain ( & new_event , SWITCH_EVENT_CHANNEL_DATA ) ;
status = SWITCH_STATUS_SUCCESS ;
* event = new_event ;
for ( ep = channel - > scope_variables ; ep ; ep = ep - > next ) {
for ( hp = ep - > headers ; hp ; hp = hp - > next ) {
if ( ! switch_event_get_header ( new_event , hp - > value ) ) {
switch_event_add_header_string ( new_event , SWITCH_STACK_BOTTOM , hp - > name , hp - > value ) ;
}
}
}
2011-06-15 18:03:39 +00:00
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
return status ;
}
2011-05-25 20:42:36 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_get_variable_dup ( switch_channel_t * channel , const char * varname , switch_bool_t dup , int idx )
2005-11-19 20:07:43 +00:00
{
2011-02-02 21:43:26 +00:00
const char * v = NULL , * r = NULL , * vdup = NULL ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-10-20 06:55:30 +00:00
2007-04-28 21:48:03 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2011-06-15 18:03:39 +00:00
2015-11-04 06:33:11 +00:00
if ( ! zstr ( varname ) ) {
if ( channel - > scope_variables ) {
switch_event_t * ep ;
2011-06-16 14:43:32 +00:00
2015-11-04 06:33:11 +00:00
for ( ep = channel - > scope_variables ; ep ; ep = ep - > next ) {
if ( ( v = switch_event_get_header_idx ( ep , varname , idx ) ) ) {
break ;
}
2011-06-16 14:43:32 +00:00
}
}
2011-06-15 18:03:39 +00:00
2015-11-04 06:33:11 +00:00
if ( ! v & & ( ! channel - > variables | | ! ( v = switch_event_get_header_idx ( channel - > variables , varname , idx ) ) ) ) {
switch_caller_profile_t * cp = switch_channel_get_caller_profile ( channel ) ;
2008-01-28 07:26:10 +00:00
2015-11-04 06:33:11 +00:00
if ( cp ) {
if ( ! strncmp ( varname , " aleg_ " , 5 ) ) {
cp = cp - > originator_caller_profile ;
varname + = 5 ;
} else if ( ! strncmp ( varname , " bleg_ " , 5 ) ) {
cp = cp - > originatee_caller_profile ;
varname + = 5 ;
}
2006-11-09 05:39:04 +00:00
}
2007-12-06 19:51:55 +00:00
2015-11-04 06:33:11 +00:00
if ( ! cp | | ! ( v = switch_caller_get_field_by_name ( cp , varname ) ) ) {
if ( ( vdup = switch_core_get_variable_pdup ( varname , switch_core_session_get_pool ( channel - > session ) ) ) ) {
v = vdup ;
}
2011-02-02 21:43:26 +00:00
}
2007-12-06 19:51:55 +00:00
}
2006-10-20 06:55:30 +00:00
}
2009-03-20 01:50:50 +00:00
2011-02-02 21:43:26 +00:00
if ( dup & & v ! = vdup ) {
if ( v ) {
2010-02-06 03:38:24 +00:00
r = switch_core_session_strdup ( channel - > session , v ) ;
2011-02-02 21:43:26 +00:00
}
2010-02-06 03:38:24 +00:00
} else {
r = v ;
}
2007-04-28 21:48:03 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2007-03-29 22:31:56 +00:00
2009-03-21 16:47:57 +00:00
return r ;
2005-11-19 20:07:43 +00:00
}
2023-06-27 23:51:24 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_get_variable_strdup ( switch_channel_t * channel , const char * varname )
{
const char * value = switch_channel_get_variable_dup ( channel , varname , SWITCH_FALSE , - 1 ) ;
return value ? ( const char * ) strdup ( value ) : NULL ;
}
SWITCH_DECLARE ( switch_status_t ) switch_channel_get_variable_buf ( switch_channel_t * channel , const char * varname , char * buf , switch_size_t buflen )
{
const char * value = switch_channel_get_variable_dup ( channel , varname , SWITCH_FALSE , - 1 ) ;
if ( value & & buf & & buflen & & switch_copy_string ( buf , value , buflen ) ) {
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_FALSE ;
}
2008-02-07 22:42:27 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_get_variable_partner ( switch_channel_t * channel , const char * varname )
{
const char * uuid ;
2009-03-21 16:47:57 +00:00
const char * val = NULL , * r = NULL ;
2008-02-07 22:42:27 +00:00
switch_assert ( channel ! = NULL ) ;
2010-02-06 03:38:24 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( varname ) ) {
2012-05-29 18:10:15 +00:00
if ( ( uuid = switch_channel_get_partner_uuid ( channel ) ) ) {
2008-02-07 22:42:27 +00:00
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
switch_channel_t * tchannel = switch_core_session_get_channel ( session ) ;
val = switch_channel_get_variable ( tchannel , varname ) ;
switch_core_session_rwunlock ( session ) ;
}
}
}
2010-02-06 03:38:24 +00:00
if ( val )
r = switch_core_session_strdup ( channel - > session , val ) ;
2009-03-20 01:50:50 +00:00
2009-03-21 16:47:57 +00:00
return r ;
2008-02-07 22:42:27 +00:00
}
2007-04-28 21:48:03 +00:00
SWITCH_DECLARE ( void ) switch_channel_variable_last ( switch_channel_t * channel )
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-10-09 15:29:18 +00:00
if ( ! channel - > vi ) {
return ;
2007-04-28 21:48:03 +00:00
}
2007-10-09 15:29:18 +00:00
channel - > vi = 0 ;
switch_mutex_unlock ( channel - > profile_mutex ) ;
2008-01-28 07:26:10 +00:00
2007-04-28 21:48:03 +00:00
}
2007-09-29 01:06:08 +00:00
SWITCH_DECLARE ( switch_event_header_t * ) switch_channel_variable_first ( switch_channel_t * channel )
2006-06-13 01:49:18 +00:00
{
2007-10-09 15:29:18 +00:00
switch_event_header_t * hi = NULL ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-10-09 15:29:18 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2011-03-10 16:47:26 +00:00
if ( channel - > variables & & ( hi = channel - > variables - > headers ) ) {
2007-10-09 15:29:18 +00:00
channel - > vi = 1 ;
} else {
switch_mutex_unlock ( channel - > profile_mutex ) ;
2007-04-28 21:48:03 +00:00
}
2007-10-09 15:29:18 +00:00
return hi ;
2006-06-13 01:49:18 +00:00
}
2007-05-12 14:48:14 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_private ( switch_channel_t * channel , const char * key , const void * private_info )
2005-11-19 20:07:43 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-09-29 01:06:08 +00:00
switch_core_hash_insert_locked ( channel - > private_hash , key , private_info , channel - > profile_mutex ) ;
2005-11-19 20:07:43 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-05-12 14:48:14 +00:00
SWITCH_DECLARE ( void * ) switch_channel_get_private ( switch_channel_t * channel , const char * key )
2005-11-19 20:07:43 +00:00
{
2007-04-28 21:48:03 +00:00
void * val ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-10-09 15:29:18 +00:00
val = switch_core_hash_find_locked ( channel - > private_hash , key , channel - > profile_mutex ) ;
2007-04-28 21:48:03 +00:00
return val ;
2005-11-19 20:07:43 +00:00
}
2010-02-03 19:19:10 +00:00
SWITCH_DECLARE ( void * ) switch_channel_get_private_partner ( switch_channel_t * channel , const char * key )
{
const char * uuid ;
void * val = NULL ;
switch_assert ( channel ! = NULL ) ;
2012-05-29 18:10:15 +00:00
if ( ( uuid = switch_channel_get_partner_uuid ( channel ) ) ) {
2010-02-03 19:19:10 +00:00
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
val = switch_core_hash_find_locked ( channel - > private_hash , key , channel - > profile_mutex ) ;
switch_core_session_rwunlock ( session ) ;
}
}
return val ;
}
2007-05-12 14:48:14 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_name ( switch_channel_t * channel , const char * name )
2005-11-19 20:07:43 +00:00
{
2008-02-26 23:29:58 +00:00
const char * old = NULL ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2009-10-23 16:03:42 +00:00
if ( ! zstr ( channel - > name ) ) {
2008-02-26 23:29:58 +00:00
old = channel - > name ;
}
2005-11-19 20:07:43 +00:00
channel - > name = NULL ;
if ( name ) {
2006-04-28 19:46:57 +00:00
char * uuid = switch_core_session_get_uuid ( channel - > session ) ;
2005-11-19 20:07:43 +00:00
channel - > name = switch_core_session_strdup ( channel - > session , name ) ;
2007-12-06 19:51:55 +00:00
switch_channel_set_variable ( channel , SWITCH_CHANNEL_NAME_VARIABLE , name ) ;
2008-02-26 23:29:58 +00:00
if ( old ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_NOTICE , " Rename Channel %s->%s [%s] \n " , old , name , uuid ) ;
2008-02-26 23:29:58 +00:00
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_NOTICE , " New Channel %s [%s] \n " , name , uuid ) ;
2008-02-26 23:29:58 +00:00
}
2005-11-19 20:07:43 +00:00
}
return SWITCH_STATUS_SUCCESS ;
}
2006-04-29 06:05:03 +00:00
SWITCH_DECLARE ( char * ) switch_channel_get_name ( switch_channel_t * channel )
2005-11-19 20:07:43 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2009-10-23 16:03:42 +00:00
return ( ! zstr ( channel - > name ) ) ? channel - > name : " N/A " ;
2005-11-19 20:07:43 +00:00
}
2009-10-19 19:58:23 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_profile_var ( switch_channel_t * channel , const char * name , const char * val )
{
char * v ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
switch_mutex_lock ( channel - > profile_mutex ) ;
2013-06-05 16:19:44 +00:00
if ( ! strcasecmp ( name , " device_id " ) & & ! zstr ( val ) ) {
const char * device_id ;
if ( ! ( device_id = switch_channel_set_device_id ( channel , val ) ) ) {
/* one time setting */
switch_mutex_unlock ( channel - > profile_mutex ) ;
return status ;
}
val = device_id ;
}
2009-10-23 16:03:42 +00:00
if ( ! zstr ( val ) ) {
2009-10-19 19:58:23 +00:00
v = switch_core_strdup ( channel - > caller_profile - > pool , val ) ;
} else {
v = SWITCH_BLANK_STRING ;
}
2010-02-06 03:38:24 +00:00
2009-10-19 19:58:23 +00:00
if ( ! strcasecmp ( name , " dialplan " ) ) {
channel - > caller_profile - > dialplan = v ;
} else if ( ! strcasecmp ( name , " username " ) ) {
channel - > caller_profile - > username = v ;
} else if ( ! strcasecmp ( name , " caller_id_name " ) ) {
channel - > caller_profile - > caller_id_name = v ;
} else if ( ! strcasecmp ( name , " caller_id_number " ) ) {
channel - > caller_profile - > caller_id_number = v ;
} else if ( ! strcasecmp ( name , " callee_id_name " ) ) {
channel - > caller_profile - > callee_id_name = v ;
} else if ( ! strcasecmp ( name , " callee_id_number " ) ) {
channel - > caller_profile - > callee_id_number = v ;
} else if ( val & & ! strcasecmp ( name , " caller_ton " ) ) {
channel - > caller_profile - > caller_ton = ( uint8_t ) atoi ( v ) ;
} else if ( val & & ! strcasecmp ( name , " caller_numplan " ) ) {
channel - > caller_profile - > caller_numplan = ( uint8_t ) atoi ( v ) ;
} else if ( val & & ! strcasecmp ( name , " destination_number_ton " ) ) {
channel - > caller_profile - > destination_number_ton = ( uint8_t ) atoi ( v ) ;
} else if ( val & & ! strcasecmp ( name , " destination_number_numplan " ) ) {
channel - > caller_profile - > destination_number_numplan = ( uint8_t ) atoi ( v ) ;
} else if ( ! strcasecmp ( name , " ani " ) ) {
channel - > caller_profile - > ani = v ;
} else if ( ! strcasecmp ( name , " aniii " ) ) {
channel - > caller_profile - > aniii = v ;
} else if ( ! strcasecmp ( name , " network_addr " ) ) {
channel - > caller_profile - > network_addr = v ;
} else if ( ! strcasecmp ( name , " rdnis " ) ) {
channel - > caller_profile - > rdnis = v ;
} else if ( ! strcasecmp ( name , " destination_number " ) ) {
channel - > caller_profile - > destination_number = v ;
} else if ( ! strcasecmp ( name , " uuid " ) ) {
channel - > caller_profile - > uuid = v ;
} else if ( ! strcasecmp ( name , " source " ) ) {
channel - > caller_profile - > source = v ;
} else if ( ! strcasecmp ( name , " context " ) ) {
channel - > caller_profile - > context = v ;
} else if ( ! strcasecmp ( name , " chan_name " ) ) {
channel - > caller_profile - > chan_name = v ;
} else {
2011-05-13 20:29:40 +00:00
profile_node_t * pn , * n = switch_core_alloc ( channel - > caller_profile - > pool , sizeof ( * n ) ) ;
2013-05-28 13:17:44 +00:00
int var_found ;
2017-01-06 07:10:15 +00:00
2011-05-13 20:29:40 +00:00
n - > var = switch_core_strdup ( channel - > caller_profile - > pool , name ) ;
n - > val = v ;
if ( ! channel - > caller_profile - > soft ) {
channel - > caller_profile - > soft = n ;
} else {
2013-05-28 13:17:44 +00:00
var_found = 0 ;
2017-01-06 07:10:15 +00:00
2013-05-28 13:17:44 +00:00
for ( pn = channel - > caller_profile - > soft ; pn ; pn = pn - > next ) {
if ( ! strcasecmp ( pn - > var , n - > var ) ) {
pn - > val = n - > val ;
var_found = 1 ;
break ;
}
if ( ! pn - > next ) {
break ;
}
}
2017-01-06 07:10:15 +00:00
2013-05-28 13:17:44 +00:00
if ( pn & & ! pn - > next & & ! var_found ) {
2011-05-13 20:29:40 +00:00
pn - > next = n ;
}
}
2009-10-19 19:58:23 +00:00
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
return status ;
}
2010-10-01 22:26:03 +00:00
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( void ) switch_channel_process_export ( switch_channel_t * channel , switch_channel_t * peer_channel ,
2010-10-01 22:26:03 +00:00
switch_event_t * var_event , const char * export_varname )
2010-04-01 19:49:32 +00:00
{
2010-10-01 22:26:03 +00:00
const char * export_vars = switch_channel_get_variable ( channel , export_varname ) ;
char * cptmp = switch_core_session_strdup ( channel - > session , export_vars ) ;
int argc ;
char * argv [ 256 ] ;
if ( zstr ( export_vars ) ) return ;
if ( var_event ) {
switch_event_del_header ( var_event , export_varname ) ;
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , export_varname , export_vars ) ;
}
2017-01-06 07:10:15 +00:00
2010-10-01 22:26:03 +00:00
if ( peer_channel ) {
switch_channel_set_variable ( peer_channel , export_varname , export_vars ) ;
}
if ( ( argc = switch_separate_string ( cptmp , ' , ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) ) {
int x ;
2017-01-06 07:10:15 +00:00
2010-10-01 22:26:03 +00:00
for ( x = 0 ; x < argc ; x + + ) {
const char * vval ;
if ( ( vval = switch_channel_get_variable ( channel , argv [ x ] ) ) ) {
char * vvar = argv [ x ] ;
2011-08-18 00:30:15 +00:00
if ( ! strncasecmp ( vvar , " nolocal: " , 8 ) ) { /* remove this later ? */
2010-10-01 22:26:03 +00:00
vvar + = 8 ;
2011-08-18 00:30:15 +00:00
} else if ( ! strncasecmp ( vvar , " _nolocal_ " , 9 ) ) {
vvar + = 9 ;
2010-10-01 22:26:03 +00:00
}
if ( var_event ) {
switch_event_del_header ( var_event , vvar ) ;
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , vvar , vval ) ;
2017-01-06 07:10:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( channel - > session ) , SWITCH_LOG_DEBUG ,
" %s EXPORTING[%s] [%s]=[%s] to event \n " ,
switch_channel_get_name ( channel ) ,
2010-10-01 22:26:03 +00:00
export_varname ,
vvar , vval ) ;
}
if ( peer_channel ) {
2017-01-06 07:10:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( channel - > session ) , SWITCH_LOG_DEBUG ,
" %s EXPORTING[%s] [%s]=[%s] to %s \n " ,
switch_channel_get_name ( channel ) ,
2010-10-01 22:26:03 +00:00
export_varname ,
vvar , vval , switch_channel_get_name ( peer_channel ) ) ;
switch_channel_set_variable ( peer_channel , vvar , vval ) ;
}
}
}
2010-04-01 19:49:32 +00:00
}
2010-10-01 22:26:03 +00:00
}
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_export_variable_var_check ( switch_channel_t * channel ,
const char * varname , const char * val ,
2010-10-01 22:26:03 +00:00
const char * export_varname , switch_bool_t var_check )
{
char * var_name = NULL ;
const char * exports ;
char * var , * new_exports , * new_exports_d = NULL ;
int local = 1 ;
exports = switch_channel_get_variable ( channel , export_varname ) ;
var = switch_core_session_strdup ( channel - > session , varname ) ;
if ( var ) {
2011-08-18 00:30:15 +00:00
if ( ! strncasecmp ( var , " nolocal: " , 8 ) ) { /* remove this later ? */
2010-10-01 22:26:03 +00:00
var_name = var + 8 ;
local = 0 ;
2011-08-18 00:30:15 +00:00
} else if ( ! strncasecmp ( var , " _nolocal_ " , 9 ) ) {
var_name = var + 9 ;
local = 0 ;
2010-10-01 22:26:03 +00:00
} else {
var_name = var ;
}
}
2017-01-06 07:10:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( channel - > session ) , SWITCH_LOG_DEBUG , " EXPORT (%s) %s[%s]=[%s] \n " ,
2010-10-01 22:26:03 +00:00
export_varname , local ? " " : " (REMOTE ONLY) " ,
var_name ? var_name : " " , val ? val : " UNDEF " ) ;
2017-01-06 07:10:15 +00:00
2010-10-01 22:26:03 +00:00
switch_channel_set_variable_var_check ( channel , var , val , var_check ) ;
if ( var & & val ) {
2010-04-01 19:49:32 +00:00
if ( exports ) {
2010-10-01 22:26:03 +00:00
new_exports_d = switch_mprintf ( " %s,%s " , exports , var ) ;
new_exports = new_exports_d ;
2010-04-01 19:49:32 +00:00
} else {
2010-10-01 22:26:03 +00:00
new_exports = var ;
2010-04-01 19:49:32 +00:00
}
2010-10-01 22:26:03 +00:00
switch_channel_set_variable ( channel , export_varname , new_exports ) ;
switch_safe_free ( new_exports_d ) ;
2010-04-01 19:49:32 +00:00
}
2010-10-01 22:26:03 +00:00
return SWITCH_STATUS_SUCCESS ;
2010-04-01 19:49:32 +00:00
}
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_export_variable_printf ( switch_channel_t * channel , const char * varname ,
2010-10-01 22:26:03 +00:00
const char * export_varname , const char * fmt , . . . )
2010-04-07 18:55:55 +00:00
{
switch_status_t status = SWITCH_STATUS_FALSE ;
char * data = NULL ;
va_list ap ;
int ret ;
2017-01-06 07:10:15 +00:00
2010-04-07 18:55:55 +00:00
switch_assert ( channel ! = NULL ) ;
2017-01-06 07:10:15 +00:00
2010-04-07 18:55:55 +00:00
va_start ( ap , fmt ) ;
ret = switch_vasprintf ( & data , fmt , ap ) ;
va_end ( ap ) ;
2017-01-06 07:10:15 +00:00
2010-04-07 18:55:55 +00:00
if ( ret = = - 1 ) {
return SWITCH_STATUS_FALSE ;
}
2017-01-06 07:10:15 +00:00
2014-07-24 13:28:38 +00:00
status = switch_channel_export_variable ( channel , varname , data , export_varname ) ;
2017-01-06 07:10:15 +00:00
2010-04-07 18:55:55 +00:00
free ( data ) ;
2017-01-06 07:10:15 +00:00
2010-04-07 18:55:55 +00:00
return status ;
}
2011-11-02 15:58:38 +00:00
SWITCH_DECLARE ( uint32_t ) switch_channel_del_variable_prefix ( switch_channel_t * channel , const char * prefix )
{
switch_event_t * event ;
switch_event_header_t * hp ;
uint32_t r = 0 ;
switch_channel_get_variables ( channel , & event ) ;
if ( event ) {
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
if ( zstr ( prefix ) | | ! strncasecmp ( hp - > name , prefix , strlen ( prefix ) ) ) {
switch_channel_set_variable ( channel , hp - > name , NULL ) ;
}
}
}
switch_event_destroy ( & event ) ;
return r ;
}
2013-04-08 17:09:44 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_transfer_variable_prefix ( switch_channel_t * orig_channel , switch_channel_t * new_channel , const char * prefix )
{
switch_event_header_t * hi = NULL ;
int x = 0 ;
if ( ( hi = switch_channel_variable_first ( orig_channel ) ) ) {
for ( ; hi ; hi = hi - > next ) {
char * var = hi - > name ;
char * val = hi - > value ;
if ( zstr ( prefix ) | | ! strncasecmp ( var , prefix , strlen ( prefix ) ) ) {
x + + ;
switch_channel_set_variable ( new_channel , var , val ) ;
}
}
switch_channel_variable_last ( orig_channel ) ;
}
2017-01-06 07:10:15 +00:00
2013-04-08 17:09:44 +00:00
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
}
2012-05-10 17:15:25 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_presence_data_vals ( switch_channel_t * channel , const char * presence_data_cols )
{
2014-07-04 00:03:01 +00:00
char * cols [ 128 ] = { 0 } ;
char header_name [ 128 ] = " " ;
int col_count = 0 , i = 0 ;
char * data_copy = NULL ;
2017-01-06 07:10:15 +00:00
2014-07-04 00:03:01 +00:00
if ( zstr ( presence_data_cols ) ) {
presence_data_cols = switch_channel_get_variable_dup ( channel , " presence_data_cols " , SWITCH_FALSE , - 1 ) ;
2012-05-10 17:15:25 +00:00
if ( zstr ( presence_data_cols ) ) {
2014-07-04 00:03:01 +00:00
return ;
2012-05-10 17:15:25 +00:00
}
2014-07-04 00:03:01 +00:00
}
2017-01-06 07:10:15 +00:00
2014-07-04 00:03:01 +00:00
data_copy = strdup ( presence_data_cols ) ;
2017-01-06 07:10:15 +00:00
2014-07-04 00:03:01 +00:00
col_count = switch_split ( data_copy , ' : ' , cols ) ;
2017-01-06 07:10:15 +00:00
2014-07-04 00:03:01 +00:00
for ( i = 0 ; i < col_count ; i + + ) {
const char * val = NULL ;
switch_snprintf ( header_name , sizeof ( header_name ) , " PD-%s " , cols [ i ] ) ;
val = switch_channel_get_variable ( channel , cols [ i ] ) ;
switch_channel_set_profile_var ( channel , header_name , val ) ;
2012-05-10 17:15:25 +00:00
}
2017-01-06 07:10:15 +00:00
2014-07-04 00:03:01 +00:00
switch_safe_free ( data_copy ) ;
2012-05-10 17:15:25 +00:00
}
2019-03-07 15:26:34 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_log_tag ( switch_channel_t * channel , const char * tagname , const char * tagvalue )
{
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( ! zstr ( tagname ) ) {
if ( ! channel - > log_tags ) {
switch_event_create_plain ( & channel - > log_tags , SWITCH_EVENT_CHANNEL_DATA ) ;
}
if ( zstr ( tagvalue ) ) {
switch_event_del_header ( channel - > log_tags , tagname ) ;
} else {
switch_event_add_header_string ( channel - > log_tags , SWITCH_STACK_BOTTOM , tagname , tagvalue ) ;
}
status = SWITCH_STATUS_SUCCESS ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
return status ;
}
SWITCH_DECLARE ( switch_status_t ) switch_channel_get_log_tags ( switch_channel_t * channel , switch_event_t * * log_tags )
{
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_assert ( channel ! = NULL ) ;
2019-03-09 18:19:19 +00:00
if ( ! channel - > log_tags ) {
return status ;
}
2019-03-07 15:26:34 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > log_tags & & log_tags ) {
status = switch_event_dup ( log_tags , channel - > log_tags ) ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
return status ;
}
2012-05-10 17:15:25 +00:00
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_variable_var_check ( switch_channel_t * channel ,
2009-01-21 21:34:31 +00:00
const char * varname , const char * value , switch_bool_t var_check )
2005-11-19 20:07:43 +00:00
{
2009-03-25 20:07:40 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2010-02-06 03:38:24 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2008-01-28 07:26:10 +00:00
2009-03-25 20:07:40 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2009-10-23 16:03:42 +00:00
if ( channel - > variables & & ! zstr ( varname ) ) {
2011-05-31 14:53:39 +00:00
if ( zstr ( value ) ) {
switch_event_del_header ( channel - > variables , varname ) ;
} else {
2009-01-21 21:34:31 +00:00
int ok = 1 ;
2010-02-06 03:38:24 +00:00
2009-01-21 21:34:31 +00:00
if ( var_check ) {
2009-01-22 03:42:22 +00:00
ok = ! switch_string_var_check_const ( value ) ;
2009-01-21 21:34:31 +00:00
}
if ( ok ) {
switch_event_add_header_string ( channel - > variables , SWITCH_STACK_BOTTOM , varname , value ) ;
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_CRIT , " Invalid data (${%s} contains a variable) \n " , varname ) ;
2009-01-21 21:34:31 +00:00
}
2008-05-27 04:30:03 +00:00
}
2009-03-25 20:07:40 +00:00
status = SWITCH_STATUS_SUCCESS ;
2007-02-19 22:57:27 +00:00
}
2009-03-25 20:07:40 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2007-02-19 22:57:27 +00:00
2009-03-25 20:07:40 +00:00
return status ;
2007-02-19 22:57:27 +00:00
}
2021-04-01 00:37:10 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_variable_strip_quotes_var_check ( switch_channel_t * channel ,
const char * varname , const char * value , switch_bool_t var_check )
{
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > variables & & ! zstr ( varname ) ) {
if ( zstr ( value ) ) {
switch_event_del_header ( channel - > variables , varname ) ;
} else {
int ok = 1 ;
char * t = ( char * ) value ;
char * r = ( char * ) value ;
2021-04-05 20:23:37 +00:00
char * tmp = NULL ;
2021-04-01 00:37:10 +00:00
if ( t & & * t = = ' " ' ) {
t + + ;
if ( end_of ( t ) = = ' " ' ) {
2021-04-05 20:23:37 +00:00
r = tmp = strdup ( t ) ;
2021-04-01 00:37:10 +00:00
switch_assert ( r ) ;
end_of ( r ) = ' \0 ' ;
}
}
if ( var_check ) {
ok = ! switch_string_var_check_const ( r ) ;
}
if ( ok ) {
switch_event_add_header_string ( channel - > variables , SWITCH_STACK_BOTTOM , varname , r ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_CRIT , " Invalid data (${%s} contains a variable) \n " , varname ) ;
}
2021-04-05 20:23:37 +00:00
switch_safe_free ( tmp ) ;
2021-04-01 00:37:10 +00:00
}
status = SWITCH_STATUS_SUCCESS ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
return status ;
}
2011-05-25 20:42:36 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_add_variable_var_check ( switch_channel_t * channel ,
const char * varname , const char * value , switch_bool_t var_check , switch_stack_t stack )
{
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > variables & & ! zstr ( varname ) ) {
2011-05-31 14:53:39 +00:00
if ( zstr ( value ) ) {
switch_event_del_header ( channel - > variables , varname ) ;
} else {
2011-05-25 20:42:36 +00:00
int ok = 1 ;
if ( var_check ) {
ok = ! switch_string_var_check_const ( value ) ;
}
if ( ok ) {
switch_event_add_header_string ( channel - > variables , stack , varname , value ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_CRIT , " Invalid data (${%s} contains a variable) \n " , varname ) ;
}
}
status = SWITCH_STATUS_SUCCESS ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
return status ;
}
2008-09-29 17:48:43 +00:00
switch_status_t switch_event_base_add_header ( switch_event_t * event , switch_stack_t stack , const char * header_name , char * data ) ;
2010-01-30 02:55:49 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_variable_printf ( switch_channel_t * channel , const char * varname , const char * fmt , . . . )
2008-09-29 17:48:43 +00:00
{
int ret = 0 ;
char * data ;
va_list ap ;
2009-03-25 20:07:40 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2008-09-29 17:48:43 +00:00
switch_assert ( channel ! = NULL ) ;
2009-03-25 20:07:40 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2009-10-23 16:03:42 +00:00
if ( channel - > variables & & ! zstr ( varname ) ) {
2008-09-29 17:48:43 +00:00
switch_event_del_header ( channel - > variables , varname ) ;
va_start ( ap , fmt ) ;
ret = switch_vasprintf ( & data , fmt , ap ) ;
va_end ( ap ) ;
if ( ret = = - 1 ) {
switch_mutex_unlock ( channel - > profile_mutex ) ;
return SWITCH_STATUS_MEMERR ;
}
2010-01-30 02:55:49 +00:00
status = switch_channel_set_variable ( channel , varname , data ) ;
free ( data ) ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
2010-02-06 03:38:24 +00:00
2010-01-30 02:55:49 +00:00
return status ;
}
2008-09-29 17:48:43 +00:00
2010-01-30 02:55:49 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_variable_name_printf ( switch_channel_t * channel , const char * val , const char * fmt , . . . )
{
int ret = 0 ;
char * varname ;
va_list ap ;
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
va_start ( ap , fmt ) ;
ret = switch_vasprintf ( & varname , fmt , ap ) ;
va_end ( ap ) ;
2010-02-06 03:38:24 +00:00
2010-01-30 02:55:49 +00:00
if ( ret = = - 1 ) {
switch_mutex_unlock ( channel - > profile_mutex ) ;
return SWITCH_STATUS_MEMERR ;
2008-09-29 17:48:43 +00:00
}
2010-02-06 03:38:24 +00:00
2010-01-30 02:55:49 +00:00
status = switch_channel_set_variable ( channel , varname , val ) ;
free ( varname ) ;
2009-03-25 20:07:40 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2008-09-29 17:48:43 +00:00
2009-03-25 20:07:40 +00:00
return status ;
2008-09-29 17:48:43 +00:00
}
2007-12-20 21:42:00 +00:00
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_variable_partner_var_check ( switch_channel_t * channel ,
2009-01-21 21:34:31 +00:00
const char * varname , const char * value , switch_bool_t var_check )
2007-12-20 21:42:00 +00:00
{
const char * uuid ;
switch_assert ( channel ! = NULL ) ;
2008-01-28 07:26:10 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( varname ) ) {
2012-05-29 18:10:15 +00:00
if ( ( uuid = switch_channel_get_partner_uuid ( channel ) ) ) {
2007-12-20 21:42:00 +00:00
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
switch_channel_t * tchannel = switch_core_session_get_channel ( session ) ;
2009-01-21 21:34:31 +00:00
switch_channel_set_variable_var_check ( tchannel , varname , value , var_check ) ;
2007-12-20 21:42:00 +00:00
switch_core_session_rwunlock ( session ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
}
return SWITCH_STATUS_FALSE ;
}
2008-12-11 15:20:24 +00:00
SWITCH_DECLARE ( uint32_t ) switch_channel_test_flag ( switch_channel_t * channel , switch_channel_flag_t flag )
2005-11-19 20:07:43 +00:00
{
2010-02-06 03:38:24 +00:00
uint32_t r = 0 ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2010-02-06 03:38:24 +00:00
switch_mutex_lock ( channel - > flag_mutex ) ;
r = channel - > flags [ flag ] ;
switch_mutex_unlock ( channel - > flag_mutex ) ;
return r ;
2005-11-19 20:07:43 +00:00
}
2008-12-11 15:20:24 +00:00
SWITCH_DECLARE ( switch_bool_t ) switch_channel_set_flag_partner ( switch_channel_t * channel , switch_channel_flag_t flag )
2007-03-30 22:13:19 +00:00
{
2007-11-01 11:28:26 +00:00
const char * uuid ;
2007-03-30 22:13:19 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-03-30 22:13:19 +00:00
2012-05-29 18:10:15 +00:00
if ( ( uuid = switch_channel_get_partner_uuid ( channel ) ) ) {
2007-03-30 22:13:19 +00:00
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
2008-12-11 15:20:24 +00:00
switch_channel_set_flag ( switch_core_session_get_channel ( session ) , flag ) ;
2007-03-30 22:13:19 +00:00
switch_core_session_rwunlock ( session ) ;
return SWITCH_TRUE ;
}
}
return SWITCH_FALSE ;
}
2009-04-23 13:15:03 +00:00
SWITCH_DECLARE ( uint32_t ) switch_channel_test_flag_partner ( switch_channel_t * channel , switch_channel_flag_t flag )
{
const char * uuid ;
int r = 0 ;
2010-02-06 03:38:24 +00:00
2009-04-23 13:15:03 +00:00
switch_assert ( channel ! = NULL ) ;
2012-05-29 18:10:15 +00:00
if ( ( uuid = switch_channel_get_partner_uuid ( channel ) ) ) {
2009-04-23 13:15:03 +00:00
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
r = switch_channel_test_flag ( switch_core_session_get_channel ( session ) , flag ) ;
switch_core_session_rwunlock ( session ) ;
}
}
return r ;
}
2008-12-11 15:20:24 +00:00
SWITCH_DECLARE ( switch_bool_t ) switch_channel_clear_flag_partner ( switch_channel_t * channel , switch_channel_flag_t flag )
2007-03-30 22:13:19 +00:00
{
2007-11-01 11:28:26 +00:00
const char * uuid ;
2007-03-30 22:13:19 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-03-30 22:13:19 +00:00
2012-05-29 18:10:15 +00:00
if ( ( uuid = switch_channel_get_partner_uuid ( channel ) ) ) {
2007-03-30 22:13:19 +00:00
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
2008-12-11 15:20:24 +00:00
switch_channel_clear_flag ( switch_core_session_get_channel ( session ) , flag ) ;
2007-03-30 22:13:19 +00:00
switch_core_session_rwunlock ( session ) ;
return SWITCH_TRUE ;
}
}
return SWITCH_FALSE ;
}
2007-12-08 00:14:21 +00:00
SWITCH_DECLARE ( void ) switch_channel_wait_for_state ( switch_channel_t * channel , switch_channel_t * other_channel , switch_channel_state_t want_state )
{
2008-01-28 07:26:10 +00:00
2011-04-26 14:43:22 +00:00
switch_assert ( channel ) ;
2017-01-06 07:10:15 +00:00
2008-05-27 04:30:03 +00:00
for ( ; ; ) {
2012-01-11 18:05:16 +00:00
if ( ( channel - > state < CS_HANGUP & & channel - > state = = channel - > running_state & & channel - > running_state = = want_state ) | |
2012-04-02 21:03:37 +00:00
( other_channel & & switch_channel_down_nosig ( other_channel ) ) | | switch_channel_down ( channel ) ) {
2007-12-08 00:14:21 +00:00
break ;
}
2012-05-18 01:10:53 +00:00
switch_cond_next ( ) ;
2007-12-08 00:14:21 +00:00
}
}
2009-05-07 17:27:15 +00:00
2011-03-03 02:50:33 +00:00
SWITCH_DECLARE ( void ) switch_channel_wait_for_state_timeout ( switch_channel_t * channel , switch_channel_state_t want_state , uint32_t timeout )
2009-05-07 17:27:15 +00:00
{
2011-04-22 21:43:29 +00:00
2009-05-07 17:27:15 +00:00
uint32_t count = 0 ;
for ( ; ; ) {
2011-03-03 02:50:33 +00:00
if ( ( channel - > state = = channel - > running_state & & channel - > running_state = = want_state ) | | channel - > state > = CS_HANGUP ) {
2009-05-07 17:27:15 +00:00
break ;
}
2011-03-03 02:50:33 +00:00
2012-04-02 21:03:37 +00:00
switch_channel_check_signal ( channel , SWITCH_TRUE ) ;
2009-05-07 17:27:15 +00:00
switch_cond_next ( ) ;
2011-03-03 02:50:33 +00:00
2009-05-07 17:27:15 +00:00
if ( + + count > = timeout ) {
break ;
}
}
}
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_wait_for_flag ( switch_channel_t * channel ,
switch_channel_flag_t want_flag ,
switch_bool_t pres , uint32_t to , switch_channel_t * super_channel )
2008-01-05 20:44:54 +00:00
{
2010-02-06 03:38:24 +00:00
2008-01-05 20:44:54 +00:00
if ( to ) {
to + + ;
}
2008-05-27 04:30:03 +00:00
for ( ; ; ) {
2008-01-05 22:17:26 +00:00
if ( pres ) {
2008-12-11 15:20:24 +00:00
if ( switch_channel_test_flag ( channel , want_flag ) ) {
2008-01-05 22:17:26 +00:00
break ;
}
} else {
2008-12-11 15:20:24 +00:00
if ( ! switch_channel_test_flag ( channel , want_flag ) ) {
2008-01-05 22:17:26 +00:00
break ;
}
}
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2008-09-09 16:31:53 +00:00
if ( super_channel & & ! switch_channel_ready ( super_channel ) ) {
return SWITCH_STATUS_FALSE ;
}
2012-03-29 17:13:59 +00:00
if ( switch_channel_down ( channel ) ) {
2008-09-09 16:31:53 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-01-05 20:44:54 +00:00
if ( to & & ! - - to ) {
return SWITCH_STATUS_TIMEOUT ;
}
}
2008-01-28 07:26:10 +00:00
2008-01-05 20:44:54 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2019-06-04 22:12:47 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_wait_for_app_flag ( switch_channel_t * channel ,
uint32_t app_flag ,
const char * key , switch_bool_t pres , uint32_t to )
{
2019-06-17 16:02:51 +00:00
int r = 0 ;
2019-06-04 22:12:47 +00:00
if ( to ) {
to + + ;
}
for ( ; ; ) {
if ( pres ) {
2019-06-17 16:02:51 +00:00
if ( ( r = switch_channel_test_app_flag_key ( key , channel , app_flag ) ) ) {
2019-06-04 22:12:47 +00:00
break ;
}
} else {
2019-06-17 16:02:51 +00:00
if ( ! ( r = switch_channel_test_app_flag_key ( key , channel , app_flag ) ) ) {
2019-06-04 22:12:47 +00:00
break ;
}
}
switch_cond_next ( ) ;
if ( switch_channel_down ( channel ) ) {
2019-06-17 16:02:51 +00:00
return r ;
2019-06-04 22:12:47 +00:00
}
if ( to & & ! - - to ) {
2019-06-17 16:02:51 +00:00
return r ;
2019-06-04 22:12:47 +00:00
}
}
2019-06-17 16:02:51 +00:00
return r ;
2019-06-04 22:12:47 +00:00
}
2009-10-14 19:26:10 +00:00
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_cap_value ( switch_channel_t * channel , switch_channel_cap_t cap , uint32_t value )
2009-10-14 19:26:10 +00:00
{
switch_assert ( channel ) ;
switch_assert ( channel - > flag_mutex ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
2010-02-06 03:38:24 +00:00
channel - > caps [ cap ] = value ;
2009-10-14 19:26:10 +00:00
switch_mutex_unlock ( channel - > flag_mutex ) ;
}
SWITCH_DECLARE ( void ) switch_channel_clear_cap ( switch_channel_t * channel , switch_channel_cap_t cap )
{
switch_assert ( channel ! = NULL ) ;
switch_assert ( channel - > flag_mutex ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
channel - > caps [ cap ] = 0 ;
switch_mutex_unlock ( channel - > flag_mutex ) ;
}
SWITCH_DECLARE ( uint32_t ) switch_channel_test_cap ( switch_channel_t * channel , switch_channel_cap_t cap )
{
switch_assert ( channel ! = NULL ) ;
return channel - > caps [ cap ] ? 1 : 0 ;
}
2011-01-05 22:25:07 +00:00
SWITCH_DECLARE ( uint32_t ) switch_channel_test_cap_partner ( switch_channel_t * channel , switch_channel_cap_t cap )
{
const char * uuid ;
int r = 0 ;
switch_assert ( channel ! = NULL ) ;
2012-05-29 18:10:15 +00:00
if ( ( uuid = switch_channel_get_partner_uuid ( channel ) ) ) {
2011-01-05 22:25:07 +00:00
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
r = switch_channel_test_cap ( switch_core_session_get_channel ( session ) , cap ) ;
switch_core_session_rwunlock ( session ) ;
}
}
return r ;
}
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( char * ) switch_channel_get_flag_string ( switch_channel_t * channel )
{
switch_stream_handle_t stream = { 0 } ;
char * r ;
int i = 0 ;
SWITCH_STANDARD_STREAM ( stream ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
for ( i = 0 ; i < CF_FLAG_MAX ; i + + ) {
if ( channel - > flags [ i ] ) {
stream . write_function ( & stream , " %d=%d; " , i , channel - > flags [ i ] ) ;
}
}
switch_mutex_unlock ( channel - > flag_mutex ) ;
r = ( char * ) stream . data ;
if ( end_of ( r ) = = ' ; ' ) {
end_of ( r ) = ' \0 ' ;
}
return r ;
}
SWITCH_DECLARE ( char * ) switch_channel_get_cap_string ( switch_channel_t * channel )
{
switch_stream_handle_t stream = { 0 } ;
char * r ;
int i = 0 ;
SWITCH_STANDARD_STREAM ( stream ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
for ( i = 0 ; i < CC_FLAG_MAX ; i + + ) {
if ( channel - > caps [ i ] ) {
stream . write_function ( & stream , " %d=%d; " , i , channel - > caps [ i ] ) ;
}
}
switch_mutex_unlock ( channel - > flag_mutex ) ;
r = ( char * ) stream . data ;
if ( end_of ( r ) = = ' ; ' ) {
end_of ( r ) = ' \0 ' ;
}
return r ;
}
SWITCH_DECLARE ( void ) switch_channel_set_flag_value ( switch_channel_t * channel , switch_channel_flag_t flag , uint32_t value )
2005-11-19 20:07:43 +00:00
{
2010-07-16 16:43:14 +00:00
int HELD = 0 ;
2015-05-05 18:27:52 +00:00
int just_set = 0 ;
2008-12-11 15:20:24 +00:00
switch_assert ( channel ) ;
switch_assert ( channel - > flag_mutex ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
2010-06-24 15:09:39 +00:00
if ( flag = = CF_LEG_HOLDING & & ! channel - > flags [ flag ] & & channel - > flags [ CF_ANSWERED ] ) {
2010-07-16 16:43:14 +00:00
HELD = 1 ;
2010-06-24 15:09:39 +00:00
}
2015-05-05 18:27:52 +00:00
if ( channel - > flags [ flag ] ! = value ) {
just_set = 1 ;
channel - > flags [ flag ] = value ;
}
2008-12-11 15:20:24 +00:00
switch_mutex_unlock ( channel - > flag_mutex ) ;
2015-05-05 18:27:52 +00:00
if ( flag = = CF_VIDEO_READY & & just_set ) {
switch_core_session_request_video_refresh ( channel - > session ) ;
}
2013-10-30 19:08:27 +00:00
if ( flag = = CF_ORIGINATOR & & switch_channel_test_flag ( channel , CF_ANSWERED ) & & switch_channel_up_nosig ( channel ) ) {
switch_channel_set_callstate ( channel , CCS_RING_WAIT ) ;
}
2013-10-31 20:28:24 +00:00
if ( flag = = CF_DIALPLAN ) {
if ( channel - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
channel - > logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND ;
if ( channel - > device_node ) {
channel - > device_node - > direction = SWITCH_CALL_DIRECTION_INBOUND ;
}
} else {
channel - > logical_direction = SWITCH_CALL_DIRECTION_INBOUND ;
if ( channel - > device_node ) {
channel - > device_node - > direction = SWITCH_CALL_DIRECTION_OUTBOUND ;
}
}
}
2010-07-16 16:43:14 +00:00
if ( HELD ) {
2012-09-07 23:17:57 +00:00
switch_hold_record_t * hr ;
const char * brto = switch_channel_get_partner_uuid ( channel ) ;
2010-07-16 16:43:14 +00:00
switch_channel_set_callstate ( channel , CCS_HELD ) ;
2011-06-27 18:27:52 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
channel - > caller_profile - > times - > last_hold = switch_time_now ( ) ;
2012-09-07 23:17:57 +00:00
hr = switch_core_session_alloc ( channel - > session , sizeof ( * hr ) ) ;
hr - > on = switch_time_now ( ) ;
if ( brto ) {
hr - > uuid = switch_core_session_strdup ( channel - > session , brto ) ;
}
2017-01-06 07:10:15 +00:00
2012-09-07 23:17:57 +00:00
if ( channel - > hold_record ) {
hr - > next = channel - > hold_record ;
}
channel - > hold_record = hr ;
2011-06-27 18:27:52 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2010-07-16 16:43:14 +00:00
}
2008-12-11 15:20:24 +00:00
if ( flag = = CF_OUTBOUND ) {
2008-10-22 18:32:54 +00:00
switch_channel_set_variable ( channel , " is_outbound " , " true " ) ;
}
2010-06-05 00:03:36 +00:00
2010-10-13 21:17:36 +00:00
if ( flag = = CF_RECOVERED ) {
switch_channel_set_variable ( channel , " recovered " , " true " ) ;
}
2015-05-27 06:15:28 +00:00
if ( flag = = CF_VIDEO_ECHO | | flag = = CF_VIDEO_BLANK | | flag = = CF_VIDEO_DECODED_READ | | flag = = CF_VIDEO_PASSIVE ) {
switch_core_session_start_video_thread ( channel - > session ) ;
}
2017-01-06 07:10:15 +00:00
2015-12-14 20:23:31 +00:00
if ( flag = = CF_VIDEO_DECODED_READ & & channel - > flags [ CF_VIDEO ] ) {
2015-05-23 03:08:27 +00:00
switch_core_session_request_video_refresh ( channel - > session ) ;
2015-03-03 01:55:36 +00:00
}
2005-11-19 20:07:43 +00:00
}
2009-08-26 17:42:36 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_flag_recursive ( switch_channel_t * channel , switch_channel_flag_t flag )
{
switch_assert ( channel ) ;
switch_assert ( channel - > flag_mutex ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
channel - > flags [ flag ] + + ;
switch_mutex_unlock ( channel - > flag_mutex ) ;
if ( flag = = CF_OUTBOUND ) {
switch_channel_set_variable ( channel , " is_outbound " , " true " ) ;
}
2010-10-13 21:17:36 +00:00
if ( flag = = CF_RECOVERED ) {
switch_channel_set_variable ( channel , " recovered " , " true " ) ;
}
2009-08-26 17:42:36 +00:00
}
2008-12-04 04:46:10 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_private_flag ( switch_channel_t * channel , uint32_t flags )
{
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
channel - > private_flags | = flags ;
switch_mutex_unlock ( channel - > flag_mutex ) ;
}
SWITCH_DECLARE ( void ) switch_channel_clear_private_flag ( switch_channel_t * channel , uint32_t flags )
{
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
channel - > private_flags & = ~ flags ;
switch_mutex_unlock ( channel - > flag_mutex ) ;
}
SWITCH_DECLARE ( int ) switch_channel_test_private_flag ( switch_channel_t * channel , uint32_t flags )
{
switch_assert ( channel ! = NULL ) ;
return ( channel - > private_flags & flags ) ;
}
2010-07-22 19:37:21 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_app_flag_key ( const char * key , switch_channel_t * channel , uint32_t flags )
2009-01-22 14:01:15 +00:00
{
2010-07-22 19:37:21 +00:00
uint32_t * flagp = NULL ;
2010-09-15 23:57:54 +00:00
switch_byte_t new = 0 ;
2009-01-22 14:01:15 +00:00
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
2010-09-15 23:57:54 +00:00
if ( ! channel - > app_flag_hash ) {
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & channel - > app_flag_hash ) ;
2010-09-15 23:57:54 +00:00
new + + ;
}
2017-01-06 07:10:15 +00:00
2010-09-15 23:57:54 +00:00
if ( new | | ! ( flagp = switch_core_hash_find ( channel - > app_flag_hash , key ) ) ) {
2010-07-22 19:37:21 +00:00
flagp = switch_core_session_alloc ( channel - > session , sizeof ( uint32_t ) ) ;
switch_core_hash_insert ( channel - > app_flag_hash , key , flagp ) ;
}
2010-09-15 23:57:54 +00:00
switch_assert ( flagp ) ;
* flagp | = flags ;
2009-01-22 14:01:15 +00:00
switch_mutex_unlock ( channel - > flag_mutex ) ;
}
2010-07-22 19:37:21 +00:00
SWITCH_DECLARE ( void ) switch_channel_clear_app_flag_key ( const char * key , switch_channel_t * channel , uint32_t flags )
2009-01-22 14:01:15 +00:00
{
2010-07-22 19:37:21 +00:00
uint32_t * flagp = NULL ;
2017-01-06 07:10:15 +00:00
2009-01-22 14:01:15 +00:00
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
2010-07-22 19:37:21 +00:00
if ( channel - > app_flag_hash & & ( flagp = switch_core_hash_find ( channel - > app_flag_hash , key ) ) ) {
if ( ! flags ) {
* flagp = 0 ;
} else {
* flagp & = ~ flags ;
}
2009-01-22 14:01:15 +00:00
}
switch_mutex_unlock ( channel - > flag_mutex ) ;
}
2010-07-22 19:37:21 +00:00
SWITCH_DECLARE ( int ) switch_channel_test_app_flag_key ( const char * key , switch_channel_t * channel , uint32_t flags )
2009-01-22 14:01:15 +00:00
{
2010-07-22 19:37:21 +00:00
int r = 0 ;
uint32_t * flagp = NULL ;
2009-01-22 14:01:15 +00:00
switch_assert ( channel ! = NULL ) ;
2010-07-22 19:37:21 +00:00
switch_mutex_lock ( channel - > flag_mutex ) ;
if ( channel - > app_flag_hash & & ( flagp = switch_core_hash_find ( channel - > app_flag_hash , key ) ) ) {
r = ( * flagp & flags ) ;
}
switch_mutex_unlock ( channel - > flag_mutex ) ;
2017-01-06 07:10:15 +00:00
2010-07-22 19:37:21 +00:00
return r ;
2009-01-22 14:01:15 +00:00
}
2008-12-11 15:20:24 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_state_flag ( switch_channel_t * channel , switch_channel_flag_t flag )
2006-09-19 02:18:24 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-09-19 02:18:24 +00:00
switch_mutex_lock ( channel - > flag_mutex ) ;
2008-12-11 15:20:24 +00:00
channel - > state_flags [ 0 ] = 1 ;
channel - > state_flags [ flag ] = 1 ;
2006-09-19 02:18:24 +00:00
switch_mutex_unlock ( channel - > flag_mutex ) ;
}
2011-12-07 21:13:59 +00:00
SWITCH_DECLARE ( void ) switch_channel_clear_state_flag ( switch_channel_t * channel , switch_channel_flag_t flag )
{
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
channel - > state_flags [ flag ] = 0 ;
switch_mutex_unlock ( channel - > flag_mutex ) ;
}
2008-12-11 15:20:24 +00:00
SWITCH_DECLARE ( void ) switch_channel_clear_flag ( switch_channel_t * channel , switch_channel_flag_t flag )
2005-11-19 20:07:43 +00:00
{
2010-07-16 16:43:14 +00:00
int ACTIVE = 0 ;
2013-10-17 20:32:31 +00:00
int CLEAR = 0 ;
2010-07-16 16:43:14 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2008-12-11 15:20:24 +00:00
switch_assert ( channel - > flag_mutex ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
2010-06-24 15:09:39 +00:00
if ( flag = = CF_LEG_HOLDING & & channel - > flags [ flag ] & & channel - > flags [ CF_ANSWERED ] ) {
2010-07-16 16:43:14 +00:00
ACTIVE = 1 ;
2010-06-24 15:09:39 +00:00
}
2013-10-17 20:32:31 +00:00
2015-12-10 01:02:23 +00:00
if ( flag = = CF_VIDEO_PASSIVE & & channel - > flags [ CF_VIDEO ] ) {
2015-03-27 19:02:07 +00:00
channel - > flags [ CF_VIDEO_READY ] = 1 ;
2015-12-10 01:02:23 +00:00
2015-03-27 19:02:07 +00:00
if ( channel - > flags [ flag ] ) {
CLEAR = 1 ;
}
2013-10-17 20:32:31 +00:00
}
2008-12-11 15:20:24 +00:00
channel - > flags [ flag ] = 0 ;
switch_mutex_unlock ( channel - > flag_mutex ) ;
2010-02-06 03:38:24 +00:00
2013-10-31 20:28:24 +00:00
if ( flag = = CF_DIALPLAN ) {
if ( channel - > direction = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
channel - > logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND ;
if ( channel - > device_node ) {
channel - > device_node - > direction = SWITCH_CALL_DIRECTION_INBOUND ;
}
}
}
2010-07-16 16:43:14 +00:00
if ( ACTIVE ) {
2014-05-30 19:30:59 +00:00
switch_channel_set_callstate ( channel , CCS_UNHELD ) ;
2011-06-27 18:27:52 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > caller_profile - > times - > last_hold ) {
channel - > caller_profile - > times - > hold_accum + = ( switch_time_now ( ) - channel - > caller_profile - > times - > last_hold ) ;
}
2012-09-07 23:17:57 +00:00
if ( channel - > hold_record ) {
channel - > hold_record - > off = switch_time_now ( ) ;
}
2014-05-30 19:30:59 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) & & switch_channel_test_flag ( channel , CF_BRIDGED ) ) {
switch_channel_set_callstate ( channel , CCS_ACTIVE ) ;
}
2011-06-27 18:27:52 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2010-07-16 16:43:14 +00:00
}
2013-10-30 19:08:27 +00:00
if ( flag = = CF_ORIGINATOR & & switch_channel_test_flag ( channel , CF_ANSWERED ) & & switch_channel_up_nosig ( channel ) ) {
switch_channel_set_callstate ( channel , CCS_ACTIVE ) ;
}
2008-12-11 15:20:24 +00:00
if ( flag = = CF_OUTBOUND ) {
2008-10-22 18:32:54 +00:00
switch_channel_set_variable ( channel , " is_outbound " , NULL ) ;
}
2010-10-13 21:17:36 +00:00
if ( flag = = CF_RECOVERED ) {
switch_channel_set_variable ( channel , " recovered " , NULL ) ;
}
2013-06-18 00:52:37 +00:00
2013-10-17 20:32:31 +00:00
if ( flag = = CF_VIDEO_PASSIVE & & CLEAR ) {
2013-06-18 00:52:37 +00:00
switch_core_session_wake_video_thread ( channel - > session ) ;
}
2020-04-19 04:03:41 +00:00
if ( flag = = CF_RECOVERING & & ! channel - > hangup_cause & & ! switch_channel_test_flag ( channel , CF_NO_RECOVER ) ) {
2014-07-16 16:40:18 +00:00
switch_core_recovery_track ( channel - > session ) ;
}
2005-11-19 20:07:43 +00:00
}
2009-08-26 17:42:36 +00:00
SWITCH_DECLARE ( void ) switch_channel_clear_flag_recursive ( switch_channel_t * channel , switch_channel_flag_t flag )
{
switch_assert ( channel ! = NULL ) ;
switch_assert ( channel - > flag_mutex ) ;
switch_mutex_lock ( channel - > flag_mutex ) ;
if ( channel - > flags [ flag ] ) {
channel - > flags [ flag ] - - ;
}
switch_mutex_unlock ( channel - > flag_mutex ) ;
2010-02-06 03:38:24 +00:00
2009-08-26 17:42:36 +00:00
if ( flag = = CF_OUTBOUND ) {
switch_channel_set_variable ( channel , " is_outbound " , NULL ) ;
}
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_channel_state_t ) switch_channel_get_state ( switch_channel_t * channel )
2005-11-19 20:07:43 +00:00
{
2006-09-16 00:43:58 +00:00
switch_channel_state_t state ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-09-16 00:43:58 +00:00
state = channel - > state ;
return state ;
2005-11-19 20:07:43 +00:00
}
2007-12-08 00:14:21 +00:00
SWITCH_DECLARE ( switch_channel_state_t ) switch_channel_get_running_state ( switch_channel_t * channel )
{
switch_channel_state_t state ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-12-08 00:14:21 +00:00
state = channel - > running_state ;
return state ;
}
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( int ) switch_channel_state_change_pending ( switch_channel_t * channel )
2010-06-03 02:57:16 +00:00
{
2011-11-18 19:17:56 +00:00
if ( switch_channel_down_nosig ( channel ) | | ! switch_core_session_in_thread ( channel - > session ) ) {
2011-03-21 17:01:51 +00:00
return 0 ;
}
2010-06-03 02:57:16 +00:00
return channel - > running_state ! = channel - > state ;
}
2011-07-12 14:40:44 +00:00
SWITCH_DECLARE ( int ) switch_channel_check_signal ( switch_channel_t * channel , switch_bool_t in_thread_only )
{
2016-02-08 10:25:48 +00:00
switch_ivr_parse_signal_data ( channel - > session , SWITCH_FALSE , in_thread_only ) ;
2011-07-12 14:40:44 +00:00
return 0 ;
}
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( int ) switch_channel_test_ready ( switch_channel_t * channel , switch_bool_t check_ready , switch_bool_t check_media )
2006-03-01 22:55:28 +00:00
{
2009-02-10 19:09:06 +00:00
int ret = 0 ;
2007-03-30 22:13:19 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2008-01-28 07:26:10 +00:00
2011-07-12 14:40:44 +00:00
switch_channel_check_signal ( channel , SWITCH_TRUE ) ;
2010-02-06 03:38:24 +00:00
if ( check_media ) {
ret = ( ( switch_channel_test_flag ( channel , CF_ANSWERED ) | |
switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) ) & & ! switch_channel_test_flag ( channel , CF_PROXY_MODE ) & &
2009-02-10 19:09:06 +00:00
switch_core_session_get_read_codec ( channel - > session ) & & switch_core_session_get_write_codec ( channel - > session ) ) ;
2017-01-06 07:10:15 +00:00
2009-02-10 19:09:06 +00:00
2010-02-06 03:38:24 +00:00
if ( ! ret )
return ret ;
2009-02-10 19:09:06 +00:00
}
2010-02-06 03:38:24 +00:00
if ( ! check_ready )
return ret ;
2009-02-10 19:09:06 +00:00
ret = 0 ;
2008-05-27 04:30:03 +00:00
if ( ! channel - > hangup_cause & & channel - > state > CS_ROUTING & & channel - > state < CS_HANGUP & & channel - > state ! = CS_RESET & &
2017-01-06 07:10:15 +00:00
! switch_channel_test_flag ( channel , CF_TRANSFER ) & & ! switch_channel_test_flag ( channel , CF_NOT_READY ) & &
2010-06-03 02:57:16 +00:00
! switch_channel_state_change_pending ( channel ) ) {
2008-05-27 04:30:03 +00:00
ret + + ;
2007-03-30 22:13:19 +00:00
}
2011-07-12 14:40:44 +00:00
2011-06-27 16:32:52 +00:00
2007-03-30 22:13:19 +00:00
return ret ;
2006-03-01 22:55:28 +00:00
}
2005-12-21 22:25:22 +00:00
static const char * state_names [ ] = {
" CS_NEW " ,
" CS_INIT " ,
2008-05-05 15:30:55 +00:00
" CS_ROUTING " ,
" CS_SOFT_EXECUTE " ,
2005-12-21 22:25:22 +00:00
" CS_EXECUTE " ,
2008-05-05 15:30:55 +00:00
" CS_EXCHANGE_MEDIA " ,
2007-12-13 22:17:20 +00:00
" CS_PARK " ,
2008-05-05 15:30:55 +00:00
" CS_CONSUME_MEDIA " ,
2006-10-31 21:38:06 +00:00
" CS_HIBERNATE " ,
2007-07-03 02:10:35 +00:00
" CS_RESET " ,
2005-12-21 22:25:22 +00:00
" CS_HANGUP " ,
2009-03-04 04:19:33 +00:00
" CS_REPORTING " ,
2009-04-10 17:43:18 +00:00
" CS_DESTROY " ,
2011-02-13 23:04:17 +00:00
" CS_NONE " ,
2006-06-06 23:07:37 +00:00
NULL
2005-12-21 22:25:22 +00:00
} ;
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_state_name ( switch_channel_state_t state )
2005-12-21 22:25:22 +00:00
{
return state_names [ state ] ;
}
2006-06-06 23:07:37 +00:00
2007-05-12 14:48:14 +00:00
SWITCH_DECLARE ( switch_channel_state_t ) switch_channel_name_state ( const char * name )
2006-06-06 23:07:37 +00:00
{
uint32_t x = 0 ;
2007-03-29 22:31:56 +00:00
for ( x = 0 ; state_names [ x ] ; x + + ) {
2006-06-06 23:07:37 +00:00
if ( ! strcasecmp ( state_names [ x ] , name ) ) {
return ( switch_channel_state_t ) x ;
}
}
2009-04-10 17:43:18 +00:00
return CS_DESTROY ;
2006-06-06 23:07:37 +00:00
}
2012-11-15 19:16:50 +00:00
static inline void careful_set ( switch_channel_t * channel , switch_channel_state_t * state , switch_channel_state_t val ) {
if ( switch_mutex_trylock ( channel - > thread_mutex ) = = SWITCH_STATUS_SUCCESS ) {
* state = val ;
switch_mutex_unlock ( channel - > thread_mutex ) ;
} else {
switch_mutex_t * mutex = switch_core_session_get_mutex ( channel - > session ) ;
int x = 0 ;
for ( x = 0 ; x < 100 ; x + + ) {
if ( switch_mutex_trylock ( mutex ) = = SWITCH_STATUS_SUCCESS ) {
* state = val ;
switch_mutex_unlock ( mutex ) ;
break ;
} else {
switch_cond_next ( ) ;
}
}
if ( x = = 100 ) {
* state = val ;
}
}
}
2008-03-08 21:07:15 +00:00
SWITCH_DECLARE ( switch_channel_state_t ) switch_channel_perform_set_running_state ( switch_channel_t * channel , switch_channel_state_t state ,
2007-12-08 00:14:21 +00:00
const char * file , const char * func , int line )
{
2008-12-11 15:20:24 +00:00
int x ;
2007-12-08 00:14:21 +00:00
2011-05-13 13:43:45 +00:00
switch_mutex_lock ( channel - > flag_mutex ) ;
2008-12-11 15:20:24 +00:00
if ( channel - > state_flags [ 0 ] ) {
2010-02-06 03:38:24 +00:00
for ( x = 1 ; x < CF_FLAG_MAX ; x + + ) {
2008-12-11 15:20:24 +00:00
if ( channel - > state_flags [ x ] ) {
channel - > flags [ x ] = 1 ;
channel - > state_flags [ x ] = 0 ;
}
}
channel - > state_flags [ 0 ] = 0 ;
2007-12-19 23:24:55 +00:00
}
2011-05-13 13:43:45 +00:00
switch_mutex_unlock ( channel - > flag_mutex ) ;
2008-01-28 07:26:10 +00:00
2008-12-11 15:20:24 +00:00
switch_channel_clear_flag ( channel , CF_TAGGED ) ;
2017-01-06 07:10:15 +00:00
2011-05-13 13:43:45 +00:00
2016-07-19 18:03:12 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_DEBUG , " (%s) Running State Change %s (Cur %d Tot % " SWITCH_SIZE_T_FMT " ) \n " ,
channel - > name , state_names [ state ] , switch_core_session_count ( ) , switch_core_session_id ( ) - 1 ) ;
2011-05-13 13:43:45 +00:00
2012-04-04 22:20:35 +00:00
switch_mutex_lock ( channel - > state_mutex ) ;
2012-11-15 19:16:50 +00:00
careful_set ( channel , & channel - > running_state , state ) ;
2008-05-15 15:57:29 +00:00
2009-08-26 21:53:43 +00:00
if ( state < = CS_DESTROY ) {
2007-12-08 00:14:21 +00:00
switch_event_t * event ;
2010-06-05 00:03:36 +00:00
2013-02-23 18:55:53 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
if ( state < CS_HANGUP ) {
if ( state = = CS_ROUTING ) {
switch_channel_set_callstate ( channel , CCS_RINGING ) ;
} else if ( switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
switch_channel_set_callstate ( channel , CCS_ACTIVE ) ;
} else if ( switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) ) {
switch_channel_set_callstate ( channel , CCS_EARLY ) ;
}
2010-06-07 23:01:02 +00:00
}
2010-06-05 00:03:36 +00:00
}
2007-12-08 00:14:21 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_STATE ) = = SWITCH_STATUS_SUCCESS ) {
2013-05-24 14:14:13 +00:00
switch_channel_event_set_data ( channel , event ) ;
2007-12-08 00:14:21 +00:00
switch_event_fire ( & event ) ;
}
}
2009-02-20 18:31:08 +00:00
switch_mutex_unlock ( channel - > state_mutex ) ;
2007-12-08 00:14:21 +00:00
2012-01-08 20:19:16 +00:00
return ( switch_channel_state_t ) SWITCH_STATUS_SUCCESS ;
2007-12-08 00:14:21 +00:00
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_channel_state_t ) switch_channel_perform_set_state ( switch_channel_t * channel ,
2007-03-30 00:13:31 +00:00
const char * file , const char * func , int line , switch_channel_state_t state )
2005-11-19 20:07:43 +00:00
{
2006-04-29 23:43:28 +00:00
switch_channel_state_t last_state ;
2005-11-19 20:07:43 +00:00
int ok = 0 ;
2005-12-21 22:25:22 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2009-04-10 17:43:18 +00:00
switch_assert ( state < = CS_DESTROY ) ;
2009-02-20 18:31:08 +00:00
switch_mutex_lock ( channel - > state_mutex ) ;
2006-09-16 00:43:58 +00:00
2005-11-19 20:07:43 +00:00
last_state = channel - > state ;
2009-04-10 17:43:18 +00:00
switch_assert ( last_state < = CS_DESTROY ) ;
2005-11-19 20:07:43 +00:00
if ( last_state = = state ) {
2006-09-16 00:43:58 +00:00
goto done ;
2005-11-19 20:07:43 +00:00
}
2006-02-13 17:37:10 +00:00
if ( last_state > = CS_HANGUP & & state < last_state ) {
2006-09-16 00:43:58 +00:00
goto done ;
2005-12-06 17:18:56 +00:00
}
2007-03-29 22:31:56 +00:00
2005-11-19 20:07:43 +00:00
/* STUB for more dev
2008-05-27 04:30:03 +00:00
case CS_INIT :
switch ( state ) {
case CS_NEW :
case CS_INIT :
case CS_EXCHANGE_MEDIA :
case CS_SOFT_EXECUTE :
case CS_ROUTING :
case CS_EXECUTE :
case CS_HANGUP :
2009-04-10 17:43:18 +00:00
case CS_DESTROY :
2008-05-27 04:30:03 +00:00
default :
break ;
}
break ;
*/
2006-01-20 15:05:05 +00:00
2008-05-27 04:30:03 +00:00
switch ( last_state ) {
2006-01-20 02:02:03 +00:00
case CS_NEW :
2008-05-27 04:30:03 +00:00
case CS_RESET :
switch ( state ) {
default :
ok + + ;
break ;
}
break ;
2006-01-20 02:02:03 +00:00
case CS_INIT :
2008-05-27 04:30:03 +00:00
switch ( state ) {
case CS_EXCHANGE_MEDIA :
case CS_SOFT_EXECUTE :
case CS_ROUTING :
case CS_EXECUTE :
case CS_PARK :
case CS_CONSUME_MEDIA :
case CS_HIBERNATE :
case CS_RESET :
ok + + ;
default :
break ;
}
break ;
2008-05-05 15:30:55 +00:00
case CS_EXCHANGE_MEDIA :
2008-05-27 04:30:03 +00:00
switch ( state ) {
case CS_SOFT_EXECUTE :
case CS_ROUTING :
case CS_EXECUTE :
case CS_PARK :
case CS_CONSUME_MEDIA :
case CS_HIBERNATE :
case CS_RESET :
ok + + ;
default :
break ;
}
break ;
2008-05-05 15:30:55 +00:00
case CS_SOFT_EXECUTE :
2008-05-27 04:30:03 +00:00
switch ( state ) {
case CS_EXCHANGE_MEDIA :
case CS_ROUTING :
case CS_EXECUTE :
case CS_PARK :
case CS_CONSUME_MEDIA :
case CS_HIBERNATE :
case CS_RESET :
ok + + ;
default :
break ;
}
break ;
case CS_PARK :
switch ( state ) {
case CS_EXCHANGE_MEDIA :
case CS_ROUTING :
case CS_EXECUTE :
case CS_SOFT_EXECUTE :
case CS_HIBERNATE :
case CS_RESET :
case CS_CONSUME_MEDIA :
ok + + ;
default :
break ;
}
break ;
case CS_CONSUME_MEDIA :
switch ( state ) {
case CS_EXCHANGE_MEDIA :
case CS_ROUTING :
case CS_EXECUTE :
case CS_SOFT_EXECUTE :
case CS_HIBERNATE :
case CS_RESET :
case CS_PARK :
ok + + ;
default :
break ;
}
break ;
case CS_HIBERNATE :
switch ( state ) {
case CS_EXCHANGE_MEDIA :
case CS_INIT :
case CS_ROUTING :
case CS_EXECUTE :
case CS_SOFT_EXECUTE :
case CS_PARK :
case CS_CONSUME_MEDIA :
case CS_RESET :
ok + + ;
default :
break ;
}
break ;
2008-05-05 15:30:55 +00:00
case CS_ROUTING :
2008-05-27 04:30:03 +00:00
switch ( state ) {
case CS_EXCHANGE_MEDIA :
case CS_EXECUTE :
case CS_SOFT_EXECUTE :
case CS_PARK :
case CS_CONSUME_MEDIA :
case CS_HIBERNATE :
case CS_RESET :
ok + + ;
default :
break ;
}
break ;
2005-11-19 20:07:43 +00:00
case CS_EXECUTE :
2008-05-27 04:30:03 +00:00
switch ( state ) {
case CS_EXCHANGE_MEDIA :
case CS_SOFT_EXECUTE :
case CS_ROUTING :
case CS_PARK :
case CS_CONSUME_MEDIA :
case CS_HIBERNATE :
case CS_RESET :
ok + + ;
default :
break ;
}
break ;
2005-11-19 20:07:43 +00:00
case CS_HANGUP :
2009-03-04 04:19:33 +00:00
switch ( state ) {
case CS_REPORTING :
2009-04-10 17:43:18 +00:00
case CS_DESTROY :
2009-03-04 04:19:33 +00:00
ok + + ;
default :
break ;
}
break ;
case CS_REPORTING :
2008-05-27 04:30:03 +00:00
switch ( state ) {
2009-04-10 17:43:18 +00:00
case CS_DESTROY :
2008-05-27 04:30:03 +00:00
ok + + ;
default :
break ;
}
break ;
2005-11-19 20:07:43 +00:00
default :
2008-05-27 04:30:03 +00:00
break ;
2005-11-19 20:07:43 +00:00
}
if ( ok ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_DEBUG , " (%s) State Change %s -> %s \n " ,
2008-05-27 04:30:03 +00:00
channel - > name , state_names [ last_state ] , state_names [ state ] ) ;
2009-03-20 01:50:50 +00:00
2012-11-15 19:16:50 +00:00
careful_set ( channel , & channel - > state , state ) ;
2006-04-22 18:12:17 +00:00
2007-01-26 20:39:45 +00:00
if ( state = = CS_HANGUP & & ! channel - > hangup_cause ) {
2006-04-22 18:12:17 +00:00
channel - > hangup_cause = SWITCH_CAUSE_NORMAL_CLEARING ;
}
2007-03-29 22:31:56 +00:00
2009-08-26 21:53:43 +00:00
if ( state < = CS_DESTROY ) {
2006-03-22 17:05:16 +00:00
switch_core_session_signal_state_change ( channel - > session ) ;
}
2005-11-19 20:07:43 +00:00
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_WARNING ,
2008-10-10 03:22:34 +00:00
" (%s) Invalid State Change %s -> %s \n " , channel - > name , state_names [ last_state ] , state_names [ state ] ) ;
2007-03-04 01:46:08 +00:00
/* we won't tolerate an invalid state change so we can make sure we are as robust as a nice cup of dark coffee! */
2008-03-08 21:07:15 +00:00
/* not cool lets crash this bad boy and figure out wtf is going on */
switch_assert ( channel - > state > = CS_HANGUP ) ;
2005-11-19 20:07:43 +00:00
}
2008-05-27 04:30:03 +00:00
done :
2007-03-29 22:31:56 +00:00
2009-02-20 18:31:08 +00:00
switch_mutex_unlock ( channel - > state_mutex ) ;
2005-11-19 20:07:43 +00:00
return channel - > state ;
}
2012-11-15 19:16:50 +00:00
SWITCH_DECLARE ( void ) switch_channel_state_thread_lock ( switch_channel_t * channel )
{
switch_mutex_lock ( channel - > thread_mutex ) ;
}
2013-02-22 23:46:54 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_state_thread_trylock ( switch_channel_t * channel )
{
return switch_mutex_trylock ( channel - > thread_mutex ) ;
}
2012-11-15 19:16:50 +00:00
SWITCH_DECLARE ( void ) switch_channel_state_thread_unlock ( switch_channel_t * channel )
{
switch_mutex_unlock ( channel - > thread_mutex ) ;
}
2009-01-05 20:43:53 +00:00
SWITCH_DECLARE ( void ) switch_channel_event_set_basic_data ( switch_channel_t * channel , switch_event_t * event )
2005-12-21 22:25:22 +00:00
{
2006-12-01 15:26:37 +00:00
switch_caller_profile_t * caller_profile , * originator_caller_profile = NULL , * originatee_caller_profile = NULL ;
2010-02-06 03:38:24 +00:00
switch_codec_implementation_t impl = { 0 } ;
2006-04-04 21:26:21 +00:00
char state_num [ 25 ] ;
2009-11-17 00:12:54 +00:00
const char * v ;
2010-02-06 03:38:24 +00:00
2007-06-24 04:06:05 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2009-12-08 01:20:22 +00:00
if ( ( caller_profile = channel - > caller_profile ) ) {
2007-03-29 22:31:56 +00:00
originator_caller_profile = caller_profile - > originator_caller_profile ;
originatee_caller_profile = caller_profile - > originatee_caller_profile ;
}
2006-01-03 01:17:59 +00:00
2012-11-08 20:13:05 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-State " , switch_channel_state_name ( channel - > running_state ) ) ;
2010-06-05 00:03:36 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-Call-State " , switch_channel_callstate2str ( channel - > callstate ) ) ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( state_num , sizeof ( state_num ) , " %d " , channel - > state ) ;
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-State-Number " , state_num ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-Name " , switch_channel_get_name ( channel ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Unique-ID " , switch_core_session_get_uuid ( channel - > session ) ) ;
2020-06-23 21:50:18 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Session-External-ID " , switch_core_session_get_external_id ( channel - > session ) ) ;
2010-02-06 03:38:24 +00:00
2009-02-24 00:05:19 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Call-Direction " ,
channel - > direction = = SWITCH_CALL_DIRECTION_OUTBOUND ? " outbound " : " inbound " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Presence-Call-Direction " ,
channel - > direction = = SWITCH_CALL_DIRECTION_OUTBOUND ? " outbound " : " inbound " ) ;
2017-01-06 07:10:15 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-HIT-Dialplan " ,
2011-08-05 03:32:06 +00:00
switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND | |
switch_channel_test_flag ( channel , CF_DIALPLAN ) ? " true " : " false " ) ;
2015-09-23 16:58:57 +00:00
if ( ( v = switch_channel_get_variable_dup ( channel , " presence_id " , SWITCH_FALSE , - 1 ) ) ) {
2009-11-17 00:12:54 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-Presence-ID " , v ) ;
}
2015-09-23 16:58:57 +00:00
if ( ( v = switch_channel_get_variable_dup ( channel , " presence_data " , SWITCH_FALSE , - 1 ) ) ) {
2009-11-17 00:12:54 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-Presence-Data " , v ) ;
}
2010-07-13 05:47:41 +00:00
2015-09-23 16:58:57 +00:00
if ( ( v = switch_channel_get_variable_dup ( channel , " presence_data_cols " , SWITCH_FALSE , - 1 ) ) ) {
2010-07-13 05:47:41 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Presence-Data-Cols " , v ) ;
2012-05-10 17:15:25 +00:00
switch_event_add_presence_data_cols ( channel , event , " PD- " ) ;
2010-07-13 05:47:41 +00:00
}
2015-09-23 16:58:57 +00:00
if ( ( v = switch_channel_get_variable_dup ( channel , " call_uuid " , SWITCH_FALSE , - 1 ) ) ) {
2010-06-25 18:19:53 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-Call-UUID " , v ) ;
2011-08-04 06:04:21 +00:00
} else {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-Call-UUID " , switch_core_session_get_uuid ( channel - > session ) ) ;
2010-06-25 18:19:53 +00:00
}
2007-03-29 22:31:56 +00:00
2011-09-02 21:59:59 +00:00
if ( switch_channel_down_nosig ( channel ) ) {
2010-08-19 17:09:21 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Answer-State " , " hangup " ) ;
} else if ( switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Answer-State " , " answered " ) ;
2007-12-15 00:39:53 +00:00
} else if ( switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) ) {
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Answer-State " , " early " ) ;
2007-12-15 00:39:53 +00:00
} else {
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Answer-State " , " ringing " ) ;
2007-12-15 00:39:53 +00:00
}
2013-04-15 15:43:28 +00:00
if ( channel - > hangup_cause ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Hangup-Cause " , switch_channel_cause2str ( channel - > hangup_cause ) ) ;
}
2009-03-20 01:50:50 +00:00
switch_core_session_get_read_impl ( channel - > session , & impl ) ;
if ( impl . iananame ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-Read-Codec-Name " , impl . iananame ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Channel-Read-Codec-Rate " , " %u " , impl . actual_samples_per_second ) ;
2010-09-29 21:52:34 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Channel-Read-Codec-Bit-Rate " , " %d " , impl . bits_per_second ) ;
2006-07-20 03:55:07 +00:00
}
2007-03-29 22:31:56 +00:00
2009-03-20 01:50:50 +00:00
switch_core_session_get_write_impl ( channel - > session , & impl ) ;
if ( impl . iananame ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Channel-Write-Codec-Name " , impl . iananame ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Channel-Write-Codec-Rate " , " %u " , impl . actual_samples_per_second ) ;
2010-09-29 21:52:34 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Channel-Write-Codec-Bit-Rate " , " %d " , impl . bits_per_second ) ;
2006-07-20 03:55:07 +00:00
}
2009-01-05 20:43:53 +00:00
2008-10-08 14:22:55 +00:00
/* Index Caller's Profile */
if ( caller_profile ) {
switch_caller_profile_event_set_data ( caller_profile , " Caller " , event ) ;
}
2010-02-06 03:38:24 +00:00
2011-08-04 22:20:02 +00:00
/* Index Originator/ee's Profile */
if ( originator_caller_profile & & channel - > last_profile_type = = LP_ORIGINATOR ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Other-Type " , " originator " ) ;
switch_caller_profile_event_set_data ( originator_caller_profile , " Other-Leg " , event ) ;
} else if ( originatee_caller_profile & & channel - > last_profile_type = = LP_ORIGINATEE ) { /* Index Originatee's Profile */
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Other-Type " , " originatee " ) ;
switch_caller_profile_event_set_data ( originatee_caller_profile , " Other-Leg " , event ) ;
2008-10-08 14:22:55 +00:00
}
2011-08-04 22:20:02 +00:00
2009-01-05 20:51:45 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2009-01-05 20:43:53 +00:00
}
2005-12-21 22:25:22 +00:00
2009-01-05 20:43:53 +00:00
SWITCH_DECLARE ( void ) switch_channel_event_set_extended_data ( switch_channel_t * channel , switch_event_t * event )
{
switch_event_header_t * hi ;
2010-11-17 18:17:27 +00:00
int global_verbose_events = - 1 ;
2009-01-05 20:43:53 +00:00
2009-01-05 20:51:45 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2010-02-06 03:38:24 +00:00
2010-07-13 05:47:41 +00:00
switch_core_session_ctl ( SCSC_VERBOSE_EVENTS , & global_verbose_events ) ;
2010-04-27 21:52:29 +00:00
2017-01-06 07:10:15 +00:00
if ( global_verbose_events | |
2010-07-13 05:47:41 +00:00
switch_channel_test_flag ( channel , CF_VERBOSE_EVENTS ) | |
switch_event_get_header ( event , " presence-data-cols " ) | |
2010-03-03 03:20:27 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_CREATE | |
2008-10-02 15:38:45 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_ORIGINATE | |
2008-11-04 16:46:33 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_UUID | |
2008-10-02 15:38:45 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_ANSWER | |
2009-01-08 16:41:32 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_PARK | |
event - > event_id = = SWITCH_EVENT_CHANNEL_UNPARK | |
2009-01-08 16:43:07 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_BRIDGE | |
event - > event_id = = SWITCH_EVENT_CHANNEL_UNBRIDGE | |
2008-10-02 15:38:45 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_PROGRESS | |
event - > event_id = = SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA | |
2008-10-02 17:10:05 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_HANGUP | |
2009-06-01 12:45:56 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE | |
2008-10-02 17:10:05 +00:00
event - > event_id = = SWITCH_EVENT_REQUEST_PARAMS | |
2008-10-02 20:52:42 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_DATA | |
2011-11-09 19:53:07 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_EXECUTE | |
2008-12-08 17:17:29 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE | |
2011-02-25 16:55:33 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_DESTROY | |
2008-10-08 14:22:55 +00:00
event - > event_id = = SWITCH_EVENT_SESSION_HEARTBEAT | |
2009-04-21 14:57:43 +00:00
event - > event_id = = SWITCH_EVENT_API | |
2009-08-21 22:29:44 +00:00
event - > event_id = = SWITCH_EVENT_RECORD_START | |
2017-01-06 07:10:15 +00:00
event - > event_id = = SWITCH_EVENT_RECORD_STOP | |
2011-02-25 16:55:33 +00:00
event - > event_id = = SWITCH_EVENT_PLAYBACK_START | |
event - > event_id = = SWITCH_EVENT_PLAYBACK_STOP | |
2010-03-02 01:11:15 +00:00
event - > event_id = = SWITCH_EVENT_CALL_UPDATE | |
event - > event_id = = SWITCH_EVENT_MEDIA_BUG_START | |
event - > event_id = = SWITCH_EVENT_MEDIA_BUG_STOP | |
2016-11-17 01:30:50 +00:00
event - > event_id = = SWITCH_EVENT_CHANNEL_HOLD | |
event - > event_id = = SWITCH_EVENT_CHANNEL_UNHOLD | |
2017-02-06 22:37:59 +00:00
event - > event_id = = SWITCH_EVENT_TEXT | |
2010-03-02 01:11:15 +00:00
event - > event_id = = SWITCH_EVENT_CUSTOM ) {
2008-10-02 15:38:45 +00:00
/* Index Variables */
2011-06-15 18:03:39 +00:00
if ( channel - > scope_variables ) {
2011-06-16 14:43:32 +00:00
switch_event_t * ep ;
for ( ep = channel - > scope_variables ; ep ; ep = ep - > next ) {
for ( hi = ep - > headers ; hi ; hi = hi - > next ) {
char buf [ 1024 ] ;
char * vvar = NULL , * vval = NULL ;
2017-01-06 07:10:15 +00:00
2011-06-16 14:43:32 +00:00
vvar = ( char * ) hi - > name ;
vval = ( char * ) hi - > value ;
2017-01-06 07:10:15 +00:00
2011-06-16 14:43:32 +00:00
switch_assert ( vvar & & vval ) ;
switch_snprintf ( buf , sizeof ( buf ) , " scope_variable_%s " , vvar ) ;
2017-01-06 07:10:15 +00:00
2011-06-16 14:43:32 +00:00
if ( ! switch_event_get_header ( event , buf ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , buf , vval ) ;
}
}
2011-06-15 18:03:39 +00:00
}
}
2008-10-02 15:38:45 +00:00
if ( channel - > variables ) {
for ( hi = channel - > variables - > headers ; hi ; hi = hi - > next ) {
char buf [ 1024 ] ;
char * vvar = NULL , * vval = NULL ;
2010-02-06 03:38:24 +00:00
2008-10-02 15:38:45 +00:00
vvar = ( char * ) hi - > name ;
vval = ( char * ) hi - > value ;
2017-01-06 07:10:15 +00:00
2008-10-02 15:38:45 +00:00
switch_assert ( vvar & & vval ) ;
switch_snprintf ( buf , sizeof ( buf ) , " variable_%s " , vvar ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , buf , vval ) ;
}
2008-03-11 03:45:16 +00:00
}
2005-12-21 22:25:22 +00:00
}
2008-10-02 15:38:45 +00:00
2007-06-24 04:06:05 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2005-12-21 22:25:22 +00:00
}
2009-01-05 20:43:53 +00:00
SWITCH_DECLARE ( void ) switch_channel_event_set_data ( switch_channel_t * channel , switch_event_t * event )
{
2009-01-05 20:51:45 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2009-01-05 20:43:53 +00:00
switch_channel_event_set_basic_data ( channel , event ) ;
switch_channel_event_set_extended_data ( channel , event ) ;
2009-01-05 20:51:45 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2009-01-05 20:43:53 +00:00
}
2013-03-29 03:17:28 +00:00
SWITCH_DECLARE ( void ) switch_channel_step_caller_profile ( switch_channel_t * channel )
{
switch_caller_profile_t * cp ;
2009-01-05 20:43:53 +00:00
2013-03-29 03:17:28 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
cp = switch_caller_profile_clone ( channel - > session , channel - > caller_profile ) ;
switch_mutex_unlock ( channel - > profile_mutex ) ;
2017-01-06 07:10:15 +00:00
2013-03-29 03:17:28 +00:00
switch_channel_set_caller_profile ( channel , cp ) ;
}
2009-01-05 20:43:53 +00:00
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_caller_profile ( switch_channel_t * channel , switch_caller_profile_t * caller_profile )
2005-11-19 20:07:43 +00:00
{
2007-09-12 22:36:26 +00:00
char * uuid = NULL ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
switch_assert ( channel - > session ! = NULL ) ;
2006-04-28 19:46:57 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2007-12-11 19:23:57 +00:00
switch_assert ( caller_profile ! = NULL ) ;
2008-01-28 07:26:10 +00:00
2010-08-17 22:26:36 +00:00
caller_profile - > direction = channel - > direction ;
2013-10-31 20:28:24 +00:00
caller_profile - > logical_direction = channel - > logical_direction ;
2007-09-12 22:36:26 +00:00
uuid = switch_core_session_get_uuid ( channel - > session ) ;
2008-01-28 07:26:10 +00:00
2007-09-12 22:36:26 +00:00
if ( ! caller_profile - > uuid | | strcasecmp ( caller_profile - > uuid , uuid ) ) {
caller_profile - > uuid = switch_core_session_strdup ( channel - > session , uuid ) ;
2006-02-22 02:50:33 +00:00
}
2007-09-12 22:36:26 +00:00
if ( ! caller_profile - > chan_name | | strcasecmp ( caller_profile - > chan_name , channel - > name ) ) {
2006-02-22 02:50:33 +00:00
caller_profile - > chan_name = switch_core_session_strdup ( channel - > session , channel - > name ) ;
}
2006-05-10 03:23:05 +00:00
if ( ! caller_profile - > context ) {
2007-09-12 22:36:26 +00:00
caller_profile - > context = switch_core_session_strdup ( channel - > session , " default " ) ;
2006-05-10 03:23:05 +00:00
}
2010-02-06 03:38:24 +00:00
if ( ! caller_profile - > times ) {
caller_profile - > times = ( switch_channel_timetable_t * ) switch_core_session_alloc ( channel - > session , sizeof ( * caller_profile - > times ) ) ;
caller_profile - > times - > profile_created = switch_micro_time_now ( ) ;
}
2006-12-01 15:26:37 +00:00
2007-03-29 22:31:56 +00:00
if ( channel - > caller_profile & & channel - > caller_profile - > times ) {
2007-12-20 17:27:11 +00:00
channel - > caller_profile - > times - > transferred = caller_profile - > times - > profile_created ;
2007-03-29 22:31:56 +00:00
caller_profile - > times - > answered = channel - > caller_profile - > times - > answered ;
2008-05-24 01:43:12 +00:00
caller_profile - > times - > progress = channel - > caller_profile - > times - > progress ;
caller_profile - > times - > progress_media = channel - > caller_profile - > times - > progress_media ;
2007-12-20 17:27:11 +00:00
caller_profile - > times - > created = channel - > caller_profile - > times - > created ;
caller_profile - > times - > hungup = channel - > caller_profile - > times - > hungup ;
2008-08-13 21:46:06 +00:00
if ( channel - > caller_profile - > caller_extension ) {
switch_caller_extension_clone ( & caller_profile - > caller_extension , channel - > caller_profile - > caller_extension , caller_profile - > pool ) ;
}
2007-12-20 18:04:07 +00:00
} else {
2009-01-25 21:23:07 +00:00
caller_profile - > times - > created = switch_micro_time_now ( ) ;
2007-03-29 22:31:56 +00:00
}
2006-04-04 21:26:21 +00:00
2010-08-17 22:26:36 +00:00
2006-04-28 19:46:57 +00:00
caller_profile - > next = channel - > caller_profile ;
2005-11-19 20:07:43 +00:00
channel - > caller_profile = caller_profile ;
2008-02-26 23:29:58 +00:00
caller_profile - > profile_index = switch_core_sprintf ( caller_profile - > pool , " %d " , + + channel - > profile_index ) ;
2008-05-27 04:30:03 +00:00
2006-04-28 19:46:57 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2005-11-19 20:07:43 +00:00
}
2006-04-29 06:05:03 +00:00
SWITCH_DECLARE ( switch_caller_profile_t * ) switch_channel_get_caller_profile ( switch_channel_t * channel )
2005-11-19 20:07:43 +00:00
{
2006-04-29 06:05:03 +00:00
switch_caller_profile_t * profile ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-04-28 19:46:57 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2009-06-05 01:46:09 +00:00
if ( ( profile = channel - > caller_profile ) & & profile - > hunt_caller_profile ) {
profile = profile - > hunt_caller_profile ;
}
2006-04-28 19:46:57 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
return profile ;
2005-11-19 20:07:43 +00:00
}
2013-03-30 03:12:54 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_originator_caller_profile ( switch_channel_t * channel , switch_caller_profile_t * caller_profile )
2005-11-19 20:07:43 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-12-11 19:54:04 +00:00
switch_assert ( channel - > caller_profile ! = NULL ) ;
2007-09-29 01:06:08 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2008-10-22 18:32:54 +00:00
if ( ! caller_profile - > times ) {
caller_profile - > times = ( switch_channel_timetable_t * ) switch_core_alloc ( caller_profile - > pool , sizeof ( * caller_profile - > times ) ) ;
}
2007-03-29 22:31:56 +00:00
if ( channel - > caller_profile ) {
caller_profile - > next = channel - > caller_profile - > originator_caller_profile ;
channel - > caller_profile - > originator_caller_profile = caller_profile ;
2011-08-04 22:20:02 +00:00
channel - > last_profile_type = LP_ORIGINATOR ;
2007-03-29 22:31:56 +00:00
}
2007-12-11 19:23:57 +00:00
switch_assert ( channel - > caller_profile - > originator_caller_profile - > next ! = channel - > caller_profile - > originator_caller_profile ) ;
2007-09-29 01:06:08 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2005-11-19 20:07:43 +00:00
}
2009-06-05 01:05:11 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_hunt_caller_profile ( switch_channel_t * channel , switch_caller_profile_t * caller_profile )
{
switch_assert ( channel ! = NULL ) ;
switch_assert ( channel - > caller_profile ! = NULL ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
2010-08-18 00:26:19 +00:00
2009-06-05 01:05:11 +00:00
channel - > caller_profile - > hunt_caller_profile = NULL ;
if ( channel - > caller_profile & & caller_profile ) {
2010-08-18 00:26:19 +00:00
caller_profile - > direction = channel - > direction ;
2013-10-31 20:28:24 +00:00
caller_profile - > logical_direction = channel - > logical_direction ;
2009-06-05 01:05:11 +00:00
channel - > caller_profile - > hunt_caller_profile = caller_profile ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
}
2010-09-08 18:19:56 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_origination_caller_profile ( switch_channel_t * channel , switch_caller_profile_t * caller_profile )
{
switch_assert ( channel ! = NULL ) ;
switch_assert ( channel - > caller_profile ! = NULL ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > caller_profile ) {
caller_profile - > next = channel - > caller_profile - > origination_caller_profile ;
channel - > caller_profile - > origination_caller_profile = caller_profile ;
}
switch_assert ( channel - > caller_profile - > origination_caller_profile - > next ! = channel - > caller_profile - > origination_caller_profile ) ;
switch_mutex_unlock ( channel - > profile_mutex ) ;
}
SWITCH_DECLARE ( switch_caller_profile_t * ) switch_channel_get_origination_caller_profile ( switch_channel_t * channel )
{
switch_caller_profile_t * profile = NULL ;
switch_assert ( channel ! = NULL ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > caller_profile ) {
profile = channel - > caller_profile - > origination_caller_profile ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
return profile ;
}
2013-03-30 03:12:54 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_originatee_caller_profile ( switch_channel_t * channel , switch_caller_profile_t * caller_profile )
2005-12-26 19:09:59 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-12-11 19:54:04 +00:00
switch_assert ( channel - > caller_profile ! = NULL ) ;
2007-09-29 01:06:08 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2010-08-17 22:26:36 +00:00
2007-03-29 22:31:56 +00:00
if ( channel - > caller_profile ) {
caller_profile - > next = channel - > caller_profile - > originatee_caller_profile ;
channel - > caller_profile - > originatee_caller_profile = caller_profile ;
2011-08-04 22:20:02 +00:00
channel - > last_profile_type = LP_ORIGINATEE ;
2007-03-29 22:31:56 +00:00
}
2007-12-11 19:23:57 +00:00
switch_assert ( channel - > caller_profile - > originatee_caller_profile - > next ! = channel - > caller_profile - > originatee_caller_profile ) ;
2008-05-27 04:30:03 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2005-12-26 19:09:59 +00:00
}
2006-04-29 06:05:03 +00:00
SWITCH_DECLARE ( switch_caller_profile_t * ) switch_channel_get_originator_caller_profile ( switch_channel_t * channel )
2005-11-19 20:07:43 +00:00
{
2006-12-01 15:26:37 +00:00
switch_caller_profile_t * profile = NULL ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-04-28 19:46:57 +00:00
2007-09-29 01:06:08 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2017-01-06 07:10:15 +00:00
2007-03-29 22:31:56 +00:00
if ( channel - > caller_profile ) {
profile = channel - > caller_profile - > originator_caller_profile ;
}
2007-09-29 01:06:08 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2008-01-28 07:26:10 +00:00
2006-04-28 19:46:57 +00:00
return profile ;
2005-11-19 20:07:43 +00:00
}
2006-04-29 06:05:03 +00:00
SWITCH_DECLARE ( switch_caller_profile_t * ) switch_channel_get_originatee_caller_profile ( switch_channel_t * channel )
2005-12-26 19:09:59 +00:00
{
2006-12-01 15:26:37 +00:00
switch_caller_profile_t * profile = NULL ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-04-28 19:46:57 +00:00
2007-09-29 01:06:08 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2007-03-29 22:31:56 +00:00
if ( channel - > caller_profile ) {
profile = channel - > caller_profile - > originatee_caller_profile ;
}
2007-09-29 01:06:08 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2008-01-28 07:26:10 +00:00
2006-04-28 19:46:57 +00:00
return profile ;
2005-12-26 19:09:59 +00:00
}
2006-12-01 15:26:37 +00:00
SWITCH_DECLARE ( char * ) switch_channel_get_uuid ( switch_channel_t * channel )
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
switch_assert ( channel - > session ! = NULL ) ;
2006-12-01 15:26:37 +00:00
return switch_core_session_get_uuid ( channel - > session ) ;
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( int ) switch_channel_add_state_handler ( switch_channel_t * channel , const switch_state_handler_table_t * state_handler )
2005-11-19 20:07:43 +00:00
{
2006-08-15 21:38:24 +00:00
int x , index ;
2006-02-07 22:58:56 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2009-02-20 18:31:08 +00:00
switch_mutex_lock ( channel - > state_mutex ) ;
2006-08-15 21:38:24 +00:00
for ( x = 0 ; x < SWITCH_MAX_STATE_HANDLERS ; x + + ) {
if ( channel - > state_handlers [ x ] = = state_handler ) {
2006-10-04 23:11:11 +00:00
index = x ;
goto end ;
2006-08-15 21:38:24 +00:00
}
}
2006-02-07 22:58:56 +00:00
index = channel - > state_handler_index + + ;
2006-02-07 20:47:15 +00:00
if ( channel - > state_handler_index > = SWITCH_MAX_STATE_HANDLERS ) {
2006-10-04 23:11:11 +00:00
index = - 1 ;
goto end ;
2006-02-07 20:47:15 +00:00
}
2007-03-29 22:31:56 +00:00
2006-02-07 20:47:15 +00:00
channel - > state_handlers [ index ] = state_handler ;
2006-10-04 23:11:11 +00:00
2008-05-27 04:30:03 +00:00
end :
2009-02-20 18:31:08 +00:00
switch_mutex_unlock ( channel - > state_mutex ) ;
2006-02-07 20:47:15 +00:00
return index ;
2005-11-19 20:07:43 +00:00
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( const switch_state_handler_table_t * ) switch_channel_get_state_handler ( switch_channel_t * channel , int index )
2005-11-19 20:07:43 +00:00
{
2006-10-04 23:11:11 +00:00
const switch_state_handler_table_t * h = NULL ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-02-07 20:47:15 +00:00
2024-11-13 19:56:15 +00:00
switch_mutex_lock ( channel - > state_mutex ) ;
if ( index < SWITCH_MAX_STATE_HANDLERS & & index < = channel - > state_handler_index ) {
h = channel - > state_handlers [ index ] ;
2006-02-07 20:47:15 +00:00
}
2009-02-20 18:31:08 +00:00
switch_mutex_unlock ( channel - > state_mutex ) ;
2006-10-04 23:11:11 +00:00
return h ;
2005-11-19 20:07:43 +00:00
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( void ) switch_channel_clear_state_handler ( switch_channel_t * channel , const switch_state_handler_table_t * state_handler )
2006-04-25 18:02:12 +00:00
{
2024-11-13 19:56:15 +00:00
int index , i ;
2007-03-29 22:31:56 +00:00
const switch_state_handler_table_t * new_handlers [ SWITCH_MAX_STATE_HANDLERS ] = { 0 } ;
2006-04-25 18:02:12 +00:00
2008-05-15 21:08:42 +00:00
switch_assert ( channel ! = NULL ) ;
2006-10-04 23:11:11 +00:00
2009-02-20 18:31:08 +00:00
switch_mutex_lock ( channel - > state_mutex ) ;
2024-11-13 19:56:15 +00:00
i = channel - > state_handler_index ;
2006-10-04 23:11:11 +00:00
channel - > state_handler_index = 0 ;
2006-04-25 18:02:12 +00:00
2006-08-17 00:53:09 +00:00
if ( state_handler ) {
2006-10-04 23:11:11 +00:00
for ( index = 0 ; index < i ; index + + ) {
2006-08-17 00:53:09 +00:00
if ( channel - > state_handlers [ index ] ! = state_handler ) {
2006-10-04 23:11:11 +00:00
new_handlers [ channel - > state_handler_index + + ] = channel - > state_handlers [ index ] ;
2006-08-17 00:53:09 +00:00
}
2006-04-25 18:02:12 +00:00
}
2009-11-04 21:07:18 +00:00
} else {
for ( index = 0 ; index < i ; index + + ) {
2009-12-07 19:07:53 +00:00
if ( channel - > state_handlers [ index ] & & switch_test_flag ( channel - > state_handlers [ index ] , SSH_FLAG_STICKY ) ) {
2009-11-04 21:07:18 +00:00
new_handlers [ channel - > state_handler_index + + ] = channel - > state_handlers [ index ] ;
}
}
2006-04-25 18:02:12 +00:00
}
2009-11-04 21:07:18 +00:00
2006-04-26 18:37:03 +00:00
for ( index = 0 ; index < SWITCH_MAX_STATE_HANDLERS ; index + + ) {
channel - > state_handlers [ index ] = NULL ;
}
2006-09-19 15:33:02 +00:00
2009-11-04 22:55:33 +00:00
if ( channel - > state_handler_index > 0 ) {
2006-10-04 23:11:11 +00:00
for ( index = 0 ; index < channel - > state_handler_index ; index + + ) {
channel - > state_handlers [ index ] = new_handlers [ index ] ;
2006-08-17 00:53:09 +00:00
}
2006-04-25 18:02:12 +00:00
}
2009-02-20 18:31:08 +00:00
switch_mutex_unlock ( channel - > state_mutex ) ;
2006-04-25 18:02:12 +00:00
}
2009-10-09 22:28:31 +00:00
SWITCH_DECLARE ( void ) switch_channel_restart ( switch_channel_t * channel )
{
switch_channel_set_state ( channel , CS_RESET ) ;
switch_channel_wait_for_state_timeout ( channel , CS_RESET , 5000 ) ;
switch_channel_set_state ( channel , CS_EXECUTE ) ;
}
2017-01-06 07:10:15 +00:00
/* XXX This is a somewhat simple operation. Were essentially taking the extension that one channel
was executing and generating a new extension for another channel that starts out where the
original one left off with an optional forward offset . Since all we are really doing is
copying a few basic pool - allocated structures from one channel to another there really is
not much to worry about here in terms of threading since we use read - write locks .
While the features are nice , they only really are needed in one specific crazy attended
2009-10-09 22:28:31 +00:00
transfer scenario where one channel was in the middle of calling a particular extension
when it was rudely cut off by a transfer key press . XXX */
2009-10-09 20:48:24 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_caller_extension_masquerade ( switch_channel_t * orig_channel , switch_channel_t * new_channel , uint32_t offset )
{
switch_caller_profile_t * caller_profile ;
switch_caller_extension_t * extension = NULL , * orig_extension = NULL ;
switch_caller_application_t * ap ;
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_event_header_t * hi = NULL ;
const char * no_copy = switch_channel_get_variable ( orig_channel , " attended_transfer_no_copy " ) ;
char * dup ;
int i , argc = 0 ;
char * argv [ 128 ] ;
if ( no_copy ) {
dup = switch_core_session_strdup ( new_channel - > session , no_copy ) ;
argc = switch_separate_string ( dup , ' , ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
}
switch_mutex_lock ( orig_channel - > profile_mutex ) ;
switch_mutex_lock ( new_channel - > profile_mutex ) ;
2010-02-06 03:38:24 +00:00
2009-10-09 20:48:24 +00:00
caller_profile = switch_caller_profile_clone ( new_channel - > session , new_channel - > caller_profile ) ;
switch_assert ( caller_profile ) ;
extension = switch_caller_extension_new ( new_channel - > session , caller_profile - > destination_number , caller_profile - > destination_number ) ;
orig_extension = switch_channel_get_caller_extension ( orig_channel ) ;
2010-02-06 03:38:24 +00:00
2009-10-09 20:48:24 +00:00
if ( extension & & orig_extension ) {
2010-02-06 03:38:24 +00:00
for ( ap = orig_extension - > current_application ; ap & & offset > 0 ; offset - - ) {
2009-10-09 20:48:24 +00:00
ap = ap - > next ;
}
2010-02-06 03:38:24 +00:00
2009-10-09 20:48:24 +00:00
for ( ; ap ; ap = ap - > next ) {
switch_caller_extension_add_application ( new_channel - > session , extension , ap - > application_name , ap - > application_data ) ;
}
2010-02-06 03:38:24 +00:00
2009-10-09 20:48:24 +00:00
caller_profile - > destination_number = switch_core_strdup ( caller_profile - > pool , orig_channel - > caller_profile - > destination_number ) ;
switch_channel_set_caller_profile ( new_channel , caller_profile ) ;
switch_channel_set_caller_extension ( new_channel , extension ) ;
for ( hi = orig_channel - > variables - > headers ; hi ; hi = hi - > next ) {
int ok = 1 ;
for ( i = 0 ; i < argc ; i + + ) {
if ( ! strcasecmp ( argv [ i ] , hi - > name ) ) {
ok = 0 ;
break ;
}
}
2010-02-06 03:38:24 +00:00
if ( ! ok )
continue ;
2009-10-09 20:48:24 +00:00
switch_channel_set_variable ( new_channel , hi - > name , hi - > value ) ;
}
status = SWITCH_STATUS_SUCCESS ;
}
switch_mutex_unlock ( new_channel - > profile_mutex ) ;
switch_mutex_unlock ( orig_channel - > profile_mutex ) ;
return status ;
}
2013-04-05 20:29:14 +00:00
SWITCH_DECLARE ( void ) switch_channel_invert_cid ( switch_channel_t * channel )
{
const char * tname , * tnum ;
switch_caller_profile_t * cp ;
cp = switch_channel_get_caller_profile ( channel ) ;
tname = cp - > caller_id_name ;
tnum = cp - > caller_id_number ;
# ifdef DEEP_DEBUG_CID
2013-04-22 21:30:06 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " SWAP [%s][%s] [%s][%s] \n " , cp - > caller_id_name , cp - > caller_id_number , cp - > callee_id_name , cp - > callee_id_number ) ;
2013-04-05 20:29:14 +00:00
# endif
cp - > caller_id_name = cp - > callee_id_name ;
cp - > caller_id_number = cp - > callee_id_number ;
2017-01-06 07:10:15 +00:00
2013-04-05 20:29:14 +00:00
cp - > callee_id_name = tname ;
cp - > callee_id_number = tnum ;
if ( zstr ( cp - > caller_id_name ) ) {
cp - > caller_id_name = " Unknown " ;
}
if ( zstr ( cp - > caller_id_number ) ) {
cp - > caller_id_number = " Unknown " ;
}
}
2011-03-11 19:00:16 +00:00
SWITCH_DECLARE ( void ) switch_channel_flip_cid ( switch_channel_t * channel )
{
2011-08-01 03:14:06 +00:00
switch_event_t * event ;
2013-10-15 21:24:32 +00:00
const char * tmp = NULL ;
2011-08-01 03:14:06 +00:00
2011-03-11 19:00:16 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2021-06-22 21:06:37 +00:00
if ( switch_channel_test_flag ( channel , CF_RECOVERING ) & & switch_true ( switch_channel_get_variable ( channel , " channel_cid_flipped " ) ) ) {
switch_mutex_unlock ( channel - > profile_mutex ) ;
return ;
}
2011-03-11 19:00:16 +00:00
if ( channel - > caller_profile - > callee_id_name ) {
2013-10-15 21:24:32 +00:00
tmp = channel - > caller_profile - > caller_id_name ;
2011-03-11 19:00:16 +00:00
switch_channel_set_variable ( channel , " pre_transfer_caller_id_name " , channel - > caller_profile - > caller_id_name ) ;
channel - > caller_profile - > caller_id_name = switch_core_strdup ( channel - > caller_profile - > pool , channel - > caller_profile - > callee_id_name ) ;
}
2013-10-15 21:24:32 +00:00
if ( switch_channel_test_flag ( channel , CF_BRIDGED ) ) {
channel - > caller_profile - > callee_id_name = SWITCH_BLANK_STRING ;
} else if ( tmp ) {
channel - > caller_profile - > callee_id_name = tmp ;
}
2017-01-06 07:10:15 +00:00
2011-03-11 19:00:16 +00:00
if ( channel - > caller_profile - > callee_id_number ) {
2013-10-15 21:24:32 +00:00
tmp = channel - > caller_profile - > caller_id_number ;
2011-03-11 19:00:16 +00:00
switch_channel_set_variable ( channel , " pre_transfer_caller_id_number " , channel - > caller_profile - > caller_id_number ) ;
channel - > caller_profile - > caller_id_number = switch_core_strdup ( channel - > caller_profile - > pool , channel - > caller_profile - > callee_id_number ) ;
}
2013-10-15 21:24:32 +00:00
if ( switch_channel_test_flag ( channel , CF_BRIDGED ) ) {
channel - > caller_profile - > callee_id_number = SWITCH_BLANK_STRING ;
} else if ( tmp ) {
channel - > caller_profile - > callee_id_number = tmp ;
}
2021-06-22 21:06:37 +00:00
switch_channel_set_variable ( channel , " channel_cid_flipped " , " yes " ) ;
2011-03-11 19:00:16 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2011-08-01 03:14:06 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CALL_UPDATE ) = = SWITCH_STATUS_SUCCESS ) {
2012-05-29 18:10:15 +00:00
const char * uuid = switch_channel_get_partner_uuid ( channel ) ;
2011-08-01 03:14:06 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Direction " , " RECV " ) ;
if ( uuid ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridged-To " , uuid ) ;
}
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2017-01-06 07:10:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( channel - > session ) , SWITCH_LOG_INFO , " %s Flipping CID from \" %s \" <%s> to \" %s \" <%s> \n " ,
2011-03-11 19:00:16 +00:00
switch_channel_get_name ( channel ) ,
2011-03-30 20:10:40 +00:00
switch_str_nil ( switch_channel_get_variable ( channel , " pre_transfer_caller_id_name " ) ) ,
switch_str_nil ( switch_channel_get_variable ( channel , " pre_transfer_caller_id_number " ) ) ,
2011-03-11 19:00:16 +00:00
channel - > caller_profile - > caller_id_name ,
channel - > caller_profile - > caller_id_number
) ;
}
2013-04-05 13:28:49 +00:00
SWITCH_DECLARE ( void ) switch_channel_sort_cid ( switch_channel_t * channel )
2010-12-17 20:35:53 +00:00
{
2013-04-05 13:28:49 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND & & switch_channel_test_flag ( channel , CF_BLEG ) ) {
switch_channel_flip_cid ( channel ) ;
switch_channel_clear_flag ( channel , CF_BLEG ) ;
} else if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND & & ! switch_channel_test_flag ( channel , CF_DIALPLAN ) ) {
switch_channel_set_flag ( channel , CF_DIALPLAN ) ;
switch_channel_flip_cid ( channel ) ;
2010-12-17 20:35:53 +00:00
}
}
2011-08-31 20:33:53 +00:00
SWITCH_DECLARE ( switch_caller_extension_t * ) switch_channel_get_queued_extension ( switch_channel_t * channel )
{
switch_caller_extension_t * caller_extension ;
switch_mutex_lock ( channel - > profile_mutex ) ;
caller_extension = channel - > queued_extension ;
channel - > queued_extension = NULL ;
switch_mutex_unlock ( channel - > profile_mutex ) ;
return caller_extension ;
}
SWITCH_DECLARE ( void ) switch_channel_transfer_to_extension ( switch_channel_t * channel , switch_caller_extension_t * caller_extension )
{
switch_mutex_lock ( channel - > profile_mutex ) ;
channel - > queued_extension = caller_extension ;
switch_mutex_unlock ( channel - > profile_mutex ) ;
switch_channel_set_flag ( channel , CF_TRANSFER ) ;
2017-01-06 07:10:15 +00:00
switch_channel_set_state ( channel , CS_ROUTING ) ;
2011-08-31 20:33:53 +00:00
}
2010-12-17 20:35:53 +00:00
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_caller_extension ( switch_channel_t * channel , switch_caller_extension_t * caller_extension )
2005-11-19 20:07:43 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-06-03 17:06:06 +00:00
2013-04-05 13:28:49 +00:00
switch_channel_sort_cid ( channel ) ;
2017-01-06 07:10:15 +00:00
2006-06-03 17:06:06 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2007-02-07 17:19:06 +00:00
caller_extension - > next = channel - > caller_profile - > caller_extension ;
channel - > caller_profile - > caller_extension = caller_extension ;
2006-06-03 17:06:06 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2005-11-19 20:07:43 +00:00
}
2006-04-29 06:05:03 +00:00
SWITCH_DECLARE ( switch_caller_extension_t * ) switch_channel_get_caller_extension ( switch_channel_t * channel )
2005-11-19 20:07:43 +00:00
{
2007-03-29 22:31:56 +00:00
switch_caller_extension_t * extension = NULL ;
2005-11-19 20:07:43 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-02-07 17:19:06 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2007-03-28 12:30:20 +00:00
if ( channel - > caller_profile ) {
extension = channel - > caller_profile - > caller_extension ;
}
2007-03-29 22:31:56 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
return extension ;
2005-11-19 20:07:43 +00:00
}
2011-04-28 18:46:39 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_bridge_time ( switch_channel_t * channel )
{
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > caller_profile & & channel - > caller_profile - > times ) {
channel - > caller_profile - > times - > bridged = switch_micro_time_now ( ) ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
}
2009-03-25 20:07:40 +00:00
SWITCH_DECLARE ( void ) switch_channel_set_hangup_time ( switch_channel_t * channel )
{
2011-05-02 15:37:05 +00:00
if ( channel - > caller_profile & & channel - > caller_profile - > times & & ! channel - > caller_profile - > times - > hungup ) {
2009-03-25 20:07:40 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2011-04-29 17:37:30 +00:00
channel - > caller_profile - > times - > hungup = switch_micro_time_now ( ) ;
2009-03-25 20:07:40 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
}
}
2007-03-29 22:31:56 +00:00
SWITCH_DECLARE ( switch_channel_state_t ) switch_channel_perform_hangup ( switch_channel_t * channel ,
2007-03-30 00:13:31 +00:00
const char * file , const char * func , int line , switch_call_cause_t hangup_cause )
2005-11-19 20:07:43 +00:00
{
2010-05-03 17:29:56 +00:00
int ok = 0 ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2009-03-04 04:19:33 +00:00
2010-05-03 17:29:56 +00:00
/* one per customer */
switch_mutex_lock ( channel - > state_mutex ) ;
if ( ! ( channel - > opaque_flags & OCF_HANGUP ) ) {
channel - > opaque_flags | = OCF_HANGUP ;
ok = 1 ;
}
switch_mutex_unlock ( channel - > state_mutex ) ;
2014-02-21 19:25:59 +00:00
if ( switch_channel_test_flag ( channel , CF_LEG_HOLDING ) ) {
switch_channel_mark_hold ( channel , SWITCH_FALSE ) ;
2014-02-26 22:24:25 +00:00
switch_channel_set_flag ( channel , CF_HANGUP_HELD ) ;
2014-02-21 19:25:59 +00:00
}
2010-05-03 17:29:56 +00:00
if ( ! ok ) {
return channel - > state ;
}
2009-03-04 04:19:33 +00:00
switch_channel_clear_flag ( channel , CF_BLOCK_STATE ) ;
2010-02-06 03:38:24 +00:00
2006-04-03 14:53:34 +00:00
if ( channel - > state < CS_HANGUP ) {
2009-10-07 04:30:19 +00:00
switch_channel_state_t last_state ;
2009-05-29 17:18:03 +00:00
switch_event_t * event ;
2011-11-09 19:52:43 +00:00
const char * var ;
2008-01-28 07:26:10 +00:00
2016-03-09 06:02:52 +00:00
2012-09-07 23:17:57 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > hold_record & & ! channel - > hold_record - > off ) {
channel - > hold_record - > off = switch_time_now ( ) ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
2009-03-20 01:50:50 +00:00
switch_mutex_lock ( channel - > state_mutex ) ;
2009-10-07 04:30:19 +00:00
last_state = channel - > state ;
2005-11-19 20:07:43 +00:00
channel - > state = CS_HANGUP ;
2009-03-20 01:50:50 +00:00
switch_mutex_unlock ( channel - > state_mutex ) ;
2006-04-22 03:05:25 +00:00
channel - > hangup_cause = hangup_cause ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_NOTICE , " Hangup %s [%s] [%s] \n " ,
2008-05-27 04:30:03 +00:00
channel - > name , state_names [ last_state ] , switch_channel_cause2str ( channel - > hangup_cause ) ) ;
2006-10-21 04:58:15 +00:00
2010-04-23 17:14:37 +00:00
2011-11-09 19:52:43 +00:00
switch_channel_set_variable_partner ( channel , " last_bridge_hangup_cause " , switch_channel_cause2str ( hangup_cause ) ) ;
if ( ( var = switch_channel_get_variable ( channel , SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE ) ) ) {
switch_channel_set_variable_partner ( channel , " last_bridge_ " SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE , var ) ;
}
2013-04-02 04:02:29 +00:00
if ( switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
switch_channel_set_variable ( channel , " last_bridge_role " , " originator " ) ;
} else if ( switch_channel_test_flag ( channel , CF_BRIDGED ) ) {
switch_channel_set_variable ( channel , " last_bridge_role " , " originatee " ) ;
}
2011-11-09 19:52:43 +00:00
2010-05-03 17:29:56 +00:00
if ( ! switch_core_session_running ( channel - > session ) & & ! switch_core_session_started ( channel - > session ) ) {
2010-04-23 17:14:37 +00:00
switch_core_session_thread_launch ( channel - > session ) ;
}
2009-05-29 17:18:03 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_HANGUP ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2006-03-22 17:05:16 +00:00
switch_core_session_kill_channel ( channel - > session , SWITCH_SIG_KILL ) ;
2006-09-16 00:43:58 +00:00
switch_core_session_signal_state_change ( channel - > session ) ;
2009-12-11 00:28:54 +00:00
switch_core_session_hangup_state ( channel - > session , SWITCH_FALSE ) ;
2005-11-19 20:07:43 +00:00
}
2006-09-16 00:43:58 +00:00
2005-11-19 20:07:43 +00:00
return channel - > state ;
}
2013-09-11 17:58:00 +00:00
static switch_status_t send_ind ( switch_channel_t * channel , switch_core_session_message_types_t msg_id , const char * file , const char * func , int line )
{
switch_core_session_message_t msg = { 0 } ;
msg . message_id = msg_id ;
msg . from = channel - > name ;
return switch_core_session_perform_receive_message ( channel - > session , & msg , file , func , line ) ;
}
2016-06-27 05:55:07 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_perform_acknowledge_call ( switch_channel_t * channel ,
const char * file , const char * func , int line )
{
send_ind ( channel , SWITCH_MESSAGE_INDICATE_ACKNOWLEDGE_CALL , file , func , line ) ;
return SWITCH_STATUS_SUCCESS ;
}
2013-09-11 17:58:00 +00:00
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_perform_mark_ring_ready_value ( switch_channel_t * channel ,
2010-06-15 20:48:12 +00:00
switch_ring_ready_t rv ,
const char * file , const char * func , int line )
2007-02-13 02:32:10 +00:00
{
2008-10-02 15:38:45 +00:00
switch_event_t * event ;
2008-06-05 20:45:03 +00:00
2012-08-17 19:07:20 +00:00
if ( ! switch_channel_test_flag ( channel , CF_RING_READY ) & & ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_NOTICE , " Ring-Ready %s! \n " , channel - > name ) ;
2010-06-15 20:48:12 +00:00
switch_channel_set_flag_value ( channel , CF_RING_READY , rv ) ;
2013-04-15 15:43:28 +00:00
2017-06-05 19:20:21 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > caller_profile & & channel - > caller_profile - > times & & ! channel - > caller_profile - > times - > progress ) {
2009-01-25 21:23:07 +00:00
channel - > caller_profile - > times - > progress = switch_micro_time_now ( ) ;
2008-10-22 18:32:54 +00:00
if ( channel - > caller_profile - > originator_caller_profile ) {
switch_core_session_t * other_session ;
if ( ( other_session = switch_core_session_locate ( channel - > caller_profile - > originator_caller_profile - > uuid ) ) ) {
switch_channel_t * other_channel ;
other_channel = switch_core_session_get_channel ( other_session ) ;
2017-06-06 14:08:09 +00:00
switch_mutex_lock ( other_channel - > profile_mutex ) ;
if ( other_channel - > caller_profile & & ! other_channel - > caller_profile - > times - > progress ) {
2008-10-22 18:32:54 +00:00
other_channel - > caller_profile - > times - > progress = channel - > caller_profile - > times - > progress ;
}
2017-06-06 14:08:09 +00:00
switch_mutex_unlock ( other_channel - > profile_mutex ) ;
2008-10-22 18:32:54 +00:00
switch_core_session_rwunlock ( other_session ) ;
}
channel - > caller_profile - > originator_caller_profile - > times - > progress = channel - > caller_profile - > times - > progress ;
}
2008-05-24 02:03:16 +00:00
}
2017-06-05 19:20:21 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2008-06-05 20:45:03 +00:00
2008-10-02 15:38:45 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_PROGRESS ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2011-04-01 22:39:20 +00:00
switch_channel_execute_on ( channel , SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE ) ;
2011-08-18 14:11:45 +00:00
switch_channel_api_on ( channel , SWITCH_CHANNEL_API_ON_RING_VARIABLE ) ;
2008-06-05 20:45:03 +00:00
2013-04-15 15:43:28 +00:00
switch_channel_set_callstate ( channel , CCS_RINGING ) ;
2013-09-11 17:58:00 +00:00
send_ind ( channel , SWITCH_MESSAGE_RING_EVENT , file , func , line ) ;
2007-02-13 02:32:10 +00:00
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_FALSE ;
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_perform_mark_pre_answered ( switch_channel_t * channel , const char * file , const char * func , int line )
2007-02-09 01:34:01 +00:00
{
2007-03-29 22:31:56 +00:00
switch_event_t * event ;
2007-02-09 01:34:01 +00:00
2010-01-22 21:04:50 +00:00
if ( ! switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) & & ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
2007-11-01 11:28:26 +00:00
const char * uuid ;
2007-03-29 22:31:56 +00:00
switch_core_session_t * other_session ;
2015-06-05 01:37:15 +00:00
switch_core_media_check_dtls ( channel - > session , SWITCH_MEDIA_TYPE_AUDIO ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_NOTICE , " Pre-Answer %s! \n " , channel - > name ) ;
2007-03-29 22:31:56 +00:00
switch_channel_set_flag ( channel , CF_EARLY_MEDIA ) ;
2017-01-06 07:10:15 +00:00
2008-10-21 19:18:40 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " EARLY MEDIA " ) ;
2010-02-06 03:38:24 +00:00
2015-04-03 23:39:43 +00:00
if ( switch_true ( switch_channel_get_variable ( channel , " video_mirror_input " ) ) ) {
switch_channel_set_flag ( channel , CF_VIDEO_MIRROR_INPUT ) ;
}
2017-01-06 07:10:15 +00:00
2008-05-24 01:43:12 +00:00
if ( channel - > caller_profile & & channel - > caller_profile - > times ) {
switch_mutex_lock ( channel - > profile_mutex ) ;
2009-01-25 21:23:07 +00:00
channel - > caller_profile - > times - > progress_media = switch_micro_time_now ( ) ;
2008-10-22 18:32:54 +00:00
if ( channel - > caller_profile - > originator_caller_profile ) {
2008-10-23 01:39:04 +00:00
switch_core_session_t * osession ;
if ( ( osession = switch_core_session_locate ( channel - > caller_profile - > originator_caller_profile - > uuid ) ) ) {
2008-10-22 18:32:54 +00:00
switch_channel_t * other_channel ;
2008-10-23 01:39:04 +00:00
other_channel = switch_core_session_get_channel ( osession ) ;
2008-10-22 18:32:54 +00:00
if ( other_channel - > caller_profile ) {
other_channel - > caller_profile - > times - > progress_media = channel - > caller_profile - > times - > progress_media ;
}
2008-10-23 01:39:04 +00:00
switch_core_session_rwunlock ( osession ) ;
2008-10-22 18:32:54 +00:00
}
channel - > caller_profile - > originator_caller_profile - > times - > progress_media = channel - > caller_profile - > times - > progress_media ;
}
2008-05-24 01:43:12 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
}
2011-08-10 12:59:03 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2011-04-04 21:51:30 +00:00
switch_channel_execute_on ( channel , SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE ) ;
switch_channel_execute_on ( channel , SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE ) ;
2011-08-18 14:11:45 +00:00
switch_channel_api_on ( channel , SWITCH_CHANNEL_API_ON_PRE_ANSWER_VARIABLE ) ;
switch_channel_api_on ( channel , SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE ) ;
2009-10-29 05:47:17 +00:00
2014-04-28 20:17:56 +00:00
if ( switch_true ( switch_channel_get_variable ( channel , SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE ) ) ) {
2010-10-05 14:59:13 +00:00
switch_channel_set_flag ( channel , CF_PASSTHRU_PTIME_MISMATCH ) ;
}
2011-08-19 21:25:26 +00:00
2017-01-06 07:10:15 +00:00
/* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
2008-05-27 04:30:03 +00:00
a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
*/
2007-03-29 22:31:56 +00:00
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_ORIGINATOR_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
2008-05-27 04:30:03 +00:00
switch_core_session_kill_channel ( other_session , SWITCH_SIG_BREAK ) ;
switch_core_session_rwunlock ( other_session ) ;
2007-03-29 22:31:56 +00:00
}
2010-08-23 22:02:06 +00:00
2013-04-15 15:43:28 +00:00
switch_channel_set_callstate ( channel , CCS_EARLY ) ;
2013-09-11 17:58:00 +00:00
send_ind ( channel , SWITCH_MESSAGE_PROGRESS_EVENT , file , func , line ) ;
2015-03-26 22:48:39 +00:00
switch_core_media_check_autoadj ( channel - > session ) ;
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_FALSE ;
2007-02-09 01:34:01 +00:00
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_perform_pre_answer ( switch_channel_t * channel , const char * file , const char * func , int line )
2006-03-03 16:57:21 +00:00
{
2009-10-12 22:23:55 +00:00
switch_core_session_message_t msg = { 0 } ;
2009-01-20 18:36:02 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2007-03-29 22:31:56 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-03-21 00:20:24 +00:00
2007-03-12 20:17:34 +00:00
if ( channel - > hangup_cause | | channel - > state > = CS_HANGUP ) {
2006-03-21 00:20:24 +00:00
return SWITCH_STATUS_FALSE ;
}
2006-07-10 19:51:19 +00:00
if ( switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2006-10-08 15:51:10 +00:00
if ( switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2010-12-16 02:59:23 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
2009-01-20 18:36:02 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_PROGRESS ;
msg . from = channel - > name ;
status = switch_core_session_perform_receive_message ( channel - > session , & msg , file , func , line ) ;
2009-01-19 16:25:49 +00:00
}
2006-03-03 17:49:22 +00:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
2008-02-20 03:57:01 +00:00
switch_channel_perform_mark_pre_answered ( channel , file , func , line ) ;
2013-04-04 18:46:46 +00:00
switch_channel_audio_sync ( channel ) ;
2008-02-20 03:57:01 +00:00
} else {
switch_channel_hangup ( channel , SWITCH_CAUSE_INCOMPATIBLE_DESTINATION ) ;
2006-03-03 17:49:22 +00:00
}
2006-03-03 16:57:21 +00:00
return status ;
}
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_perform_ring_ready_value ( switch_channel_t * channel , switch_ring_ready_t rv ,
2010-06-15 20:48:12 +00:00
const char * file , const char * func , int line )
2006-10-25 04:28:49 +00:00
{
2009-10-12 22:23:55 +00:00
switch_core_session_message_t msg = { 0 } ;
2009-01-20 18:36:02 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2007-03-29 22:31:56 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-10-25 04:28:49 +00:00
2007-03-12 20:17:34 +00:00
if ( channel - > hangup_cause | | channel - > state > = CS_HANGUP ) {
2006-10-25 04:28:49 +00:00
return SWITCH_STATUS_FALSE ;
}
if ( switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
return SWITCH_STATUS_SUCCESS ;
}
if ( switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2010-12-16 02:59:23 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
2009-01-20 18:36:02 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_RINGING ;
msg . from = channel - > name ;
2010-06-15 20:48:12 +00:00
msg . numeric_arg = rv ;
2009-01-20 18:36:02 +00:00
status = switch_core_session_perform_receive_message ( channel - > session , & msg , file , func , line ) ;
2009-01-19 16:25:49 +00:00
}
2010-02-06 03:38:24 +00:00
2006-10-25 04:28:49 +00:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_NOTICE , " Ring Ready %s! \n " , channel - > name ) ;
2010-06-15 20:48:12 +00:00
switch_channel_perform_mark_ring_ready_value ( channel , rv , file , func , line ) ;
2008-02-20 03:57:01 +00:00
} else {
switch_channel_hangup ( channel , SWITCH_CAUSE_INCOMPATIBLE_DESTINATION ) ;
2006-10-25 04:28:49 +00:00
}
return status ;
}
2011-08-18 14:11:45 +00:00
static void do_api_on ( switch_channel_t * channel , const char * variable )
2011-04-01 22:39:20 +00:00
{
2011-08-18 14:11:45 +00:00
char * app ;
2017-01-06 07:10:15 +00:00
char * arg = NULL ;
2020-04-19 22:59:42 +00:00
char * expanded = NULL ;
2011-08-18 14:11:45 +00:00
switch_stream_handle_t stream = { 0 } ;
app = switch_core_session_strdup ( channel - > session , variable ) ;
2017-01-06 07:10:15 +00:00
2011-08-18 14:11:45 +00:00
if ( ( arg = strchr ( app , ' ' ) ) ) {
* arg + + = ' \0 ' ;
}
2017-01-06 07:10:15 +00:00
2020-04-19 22:59:42 +00:00
if ( zstr ( arg ) ) {
expanded = arg ;
} else {
expanded = switch_channel_expand_variables ( channel , arg ) ;
}
2011-08-18 14:11:45 +00:00
SWITCH_STANDARD_STREAM ( stream ) ;
2020-04-19 22:59:42 +00:00
switch_api_execute ( app , expanded , NULL , & stream ) ;
2011-08-18 14:11:45 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_DEBUG , " %s process %s: %s(%s) \n %s \n " ,
2020-04-19 22:59:42 +00:00
channel - > name , variable , app , switch_str_nil ( expanded ) , ( char * ) stream . data ) ;
if ( expanded & & expanded ! = arg ) {
free ( expanded ) ;
}
2011-08-18 14:11:45 +00:00
free ( stream . data ) ;
}
SWITCH_DECLARE ( switch_status_t ) switch_channel_api_on ( switch_channel_t * channel , const char * variable_prefix )
{
switch_event_header_t * hp ;
2011-04-02 00:46:48 +00:00
switch_event_t * event ;
2011-04-01 22:39:20 +00:00
int x = 0 ;
2011-04-02 00:46:48 +00:00
2017-01-06 07:10:15 +00:00
2011-04-02 00:46:48 +00:00
switch_channel_get_variables ( channel , & event ) ;
2017-01-06 07:10:15 +00:00
2011-08-18 14:11:45 +00:00
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
char * var = hp - > name ;
char * val = hp - > value ;
2011-04-01 22:39:20 +00:00
2011-08-18 14:11:45 +00:00
if ( ! strncasecmp ( var , variable_prefix , strlen ( variable_prefix ) ) ) {
if ( hp - > idx ) {
int i ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
x + + ;
2017-01-06 07:10:15 +00:00
do_api_on ( channel , hp - > array [ i ] ) ;
2011-04-04 22:43:05 +00:00
}
2011-08-18 14:11:45 +00:00
} else {
x + + ;
do_api_on ( channel , val ) ;
2011-04-04 22:43:05 +00:00
}
2011-08-18 14:11:45 +00:00
}
}
2017-01-06 07:10:15 +00:00
2011-08-18 14:11:45 +00:00
switch_event_destroy ( & event ) ;
2011-04-04 22:43:05 +00:00
2011-08-18 14:11:45 +00:00
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
}
2020-12-22 20:32:48 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_execute_on_value ( switch_channel_t * channel , const char * variable_value )
2011-08-18 14:11:45 +00:00
{
2020-12-22 20:32:48 +00:00
switch_status_t status ;
2011-08-18 14:11:45 +00:00
char * arg = NULL ;
char * p ;
int bg = 0 ;
char * app ;
2020-04-19 22:59:42 +00:00
char * expanded = NULL ;
2020-12-22 20:32:48 +00:00
app = switch_core_session_strdup ( channel - > session , variable_value ) ;
2013-03-28 03:19:58 +00:00
2011-08-18 14:11:45 +00:00
for ( p = app ; p & & * p ; p + + ) {
2012-09-20 14:57:58 +00:00
if ( * p = = ' ' | | ( * p = = ' : ' & & ( * ( p + 1 ) ! = ' : ' ) ) ) {
2011-08-18 14:11:45 +00:00
* p + + = ' \0 ' ;
arg = p ;
break ;
} else if ( * p = = ' : ' & & ( * ( p + 1 ) = = ' : ' ) ) {
bg + + ;
break ;
}
}
2017-01-06 07:10:15 +00:00
2019-05-03 00:58:51 +00:00
switch_assert ( app ! = NULL ) ;
2014-04-28 16:16:52 +00:00
if ( ! strncasecmp ( app , " perl " , 4 ) ) {
bg + + ;
}
2017-01-06 07:10:15 +00:00
2020-04-19 22:59:42 +00:00
if ( zstr ( arg ) ) {
expanded = arg ;
} else {
expanded = switch_channel_expand_variables ( channel , arg ) ;
}
2011-08-18 14:11:45 +00:00
if ( bg ) {
2020-12-22 20:32:48 +00:00
status = switch_core_session_execute_application_async ( channel - > session , app , arg ) ;
2011-08-18 14:11:45 +00:00
} else {
2020-12-22 20:32:48 +00:00
status = switch_core_session_execute_application ( channel - > session , app , arg ) ;
2011-08-18 14:11:45 +00:00
}
2020-04-19 22:59:42 +00:00
if ( expanded & & expanded ! = arg ) {
free ( expanded ) ;
}
2020-12-22 20:32:48 +00:00
return status ;
2011-08-18 14:11:45 +00:00
}
SWITCH_DECLARE ( switch_status_t ) switch_channel_execute_on ( switch_channel_t * channel , const char * variable_prefix )
{
switch_event_header_t * hp ;
2013-03-27 19:54:01 +00:00
switch_event_t * event , * cevent ;
2011-08-18 14:11:45 +00:00
int x = 0 ;
2013-03-27 19:54:01 +00:00
switch_core_get_variables ( & event ) ;
switch_channel_get_variables ( channel , & cevent ) ;
switch_event_merge ( event , cevent ) ;
2017-01-06 07:10:15 +00:00
2011-08-18 14:11:45 +00:00
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
char * var = hp - > name ;
char * val = hp - > value ;
if ( ! strncasecmp ( var , variable_prefix , strlen ( variable_prefix ) ) ) {
if ( hp - > idx ) {
int i ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
x + + ;
2020-12-22 20:32:48 +00:00
switch_channel_execute_on_value ( channel , hp - > array [ i ] ) ;
2011-08-18 14:11:45 +00:00
}
2011-04-02 00:46:48 +00:00
} else {
2011-08-18 14:11:45 +00:00
x + + ;
2020-12-22 20:32:48 +00:00
switch_channel_execute_on_value ( channel , val ) ;
2011-04-01 22:39:20 +00:00
}
}
}
2017-01-06 07:10:15 +00:00
2011-04-02 00:46:48 +00:00
switch_event_destroy ( & event ) ;
2013-03-27 19:54:01 +00:00
switch_event_destroy ( & cevent ) ;
2011-04-01 22:39:20 +00:00
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_perform_mark_answered ( switch_channel_t * channel , const char * file , const char * func , int line )
2006-12-05 23:08:14 +00:00
{
2007-03-29 22:31:56 +00:00
switch_event_t * event ;
2007-11-01 11:28:26 +00:00
const char * uuid ;
2007-03-29 22:31:56 +00:00
switch_core_session_t * other_session ;
2008-06-05 19:36:33 +00:00
const char * var ;
2006-12-05 23:08:14 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2006-12-05 23:08:14 +00:00
2007-03-12 20:17:34 +00:00
if ( channel - > hangup_cause | | channel - > state > = CS_HANGUP ) {
2006-12-05 23:08:14 +00:00
return SWITCH_STATUS_FALSE ;
}
if ( switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2015-06-05 01:37:15 +00:00
switch_core_media_check_dtls ( channel - > session , SWITCH_MEDIA_TYPE_AUDIO ) ;
2007-03-29 22:31:56 +00:00
if ( channel - > caller_profile & & channel - > caller_profile - > times ) {
switch_mutex_lock ( channel - > profile_mutex ) ;
2009-01-25 21:23:07 +00:00
channel - > caller_profile - > times - > answered = switch_micro_time_now ( ) ;
2007-03-29 22:31:56 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
}
switch_channel_set_flag ( channel , CF_ANSWERED ) ;
2013-04-15 15:43:28 +00:00
2015-04-03 23:39:43 +00:00
if ( switch_true ( switch_channel_get_variable ( channel , " video_mirror_input " ) ) ) {
switch_channel_set_flag ( channel , CF_VIDEO_MIRROR_INPUT ) ;
//switch_channel_set_flag(channel, CF_VIDEO_DECODED_READ);
}
2017-01-06 07:10:15 +00:00
2007-03-29 22:31:56 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_ANSWER ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2017-01-06 07:10:15 +00:00
/* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
2008-05-27 04:30:03 +00:00
a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
*/
2007-03-29 22:31:56 +00:00
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_ORIGINATOR_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
2008-05-27 04:30:03 +00:00
switch_core_session_kill_channel ( other_session , SWITCH_SIG_BREAK ) ;
switch_core_session_rwunlock ( other_session ) ;
2007-03-29 22:31:56 +00:00
}
2014-04-28 20:17:56 +00:00
if ( switch_true ( switch_channel_get_variable ( channel , SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE ) ) ) {
2010-10-05 14:59:13 +00:00
switch_channel_set_flag ( channel , CF_PASSTHRU_PTIME_MISMATCH ) ;
}
2008-10-07 21:03:37 +00:00
if ( ( var = switch_channel_get_variable ( channel , SWITCH_ENABLE_HEARTBEAT_EVENTS_VARIABLE ) ) ) {
uint32_t seconds = 60 ;
int tmp ;
if ( switch_is_number ( var ) ) {
tmp = atoi ( var ) ;
2008-10-07 21:42:31 +00:00
if ( tmp > 0 ) {
2008-10-07 21:03:37 +00:00
seconds = tmp ;
}
} else if ( ! switch_true ( var ) ) {
seconds = 0 ;
}
if ( seconds ) {
switch_core_session_enable_heartbeat ( channel - > session , seconds ) ;
}
}
2008-10-21 19:18:40 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ANSWER " ) ;
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_channel_get_uuid ( channel ) , SWITCH_LOG_NOTICE , " Channel [%s] has been answered \n " ,
channel - > name ) ;
2009-10-29 05:47:17 +00:00
2010-02-06 03:38:24 +00:00
2014-04-28 20:17:56 +00:00
if ( switch_channel_get_variable ( channel , " absolute_codec_string " ) ) {
2017-01-06 07:10:15 +00:00
/* inherit_codec == true will implicitly clear the absolute_codec_string
2014-02-17 18:48:59 +00:00
variable if used since it was the reason it was set in the first place and is no longer needed */
if ( switch_true ( switch_channel_get_variable ( channel , " inherit_codec " ) ) ) {
switch_channel_set_variable ( channel , " absolute_codec_string " , NULL ) ;
}
}
2011-04-04 21:51:30 +00:00
switch_channel_execute_on ( channel , SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE ) ;
if ( ! switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) ) {
switch_channel_execute_on ( channel , SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE ) ;
2011-08-18 14:11:45 +00:00
switch_channel_api_on ( channel , SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE ) ;
2008-06-05 19:36:33 +00:00
}
2008-11-27 02:41:08 +00:00
2011-08-18 14:11:45 +00:00
switch_channel_api_on ( channel , SWITCH_CHANNEL_API_ON_ANSWER_VARIABLE ) ;
2009-10-23 15:01:34 +00:00
2009-12-24 05:44:23 +00:00
switch_channel_presence ( channel , " unknown " , " answered " , NULL ) ;
2012-11-29 05:12:35 +00:00
//switch_channel_audio_sync(channel);
2020-04-19 04:03:41 +00:00
if ( ! switch_channel_test_flag ( channel , CF_NO_RECOVER ) ) {
switch_core_recovery_track ( channel - > session ) ;
}
2013-04-15 15:43:28 +00:00
switch_channel_set_callstate ( channel , CCS_ACTIVE ) ;
2013-09-11 17:58:00 +00:00
send_ind ( channel , SWITCH_MESSAGE_ANSWER_EVENT , file , func , line ) ;
2017-01-06 07:10:15 +00:00
2015-03-26 22:48:39 +00:00
switch_core_media_check_autoadj ( channel - > session ) ;
2013-09-11 17:58:00 +00:00
2016-10-12 23:00:13 +00:00
if ( switch_channel_test_flag ( channel , CF_RTT ) ) {
switch_channel_set_flag_partner ( channel , CF_RTT ) ;
}
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_SUCCESS ;
2006-12-05 23:08:14 +00:00
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_perform_answer ( switch_channel_t * channel , const char * file , const char * func , int line )
2005-11-19 20:07:43 +00:00
{
2009-10-12 22:23:55 +00:00
switch_core_session_message_t msg = { 0 } ;
2009-01-20 18:36:02 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2007-04-16 16:53:30 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2005-11-19 20:07:43 +00:00
2010-12-16 02:59:23 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2010-03-11 20:41:46 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-03-12 20:17:34 +00:00
if ( channel - > hangup_cause | | channel - > state > = CS_HANGUP ) {
2006-03-21 00:20:24 +00:00
return SWITCH_STATUS_FALSE ;
2009-01-19 16:00:11 +00:00
}
2009-01-19 16:25:49 +00:00
if ( switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
return SWITCH_STATUS_SUCCESS ;
2006-03-21 00:20:24 +00:00
}
2013-04-03 01:05:46 +00:00
2010-03-11 20:41:46 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_ANSWER ;
msg . from = channel - > name ;
status = switch_core_session_perform_receive_message ( channel - > session , & msg , file , func , line ) ;
2010-02-06 03:38:24 +00:00
2006-06-06 23:49:02 +00:00
2007-04-16 16:53:30 +00:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
2008-02-20 03:57:01 +00:00
switch_channel_perform_mark_answered ( channel , file , func , line ) ;
2013-04-04 18:46:46 +00:00
if ( ! switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) ) {
switch_channel_audio_sync ( channel ) ;
}
2008-02-20 03:57:01 +00:00
} else {
switch_channel_hangup ( channel , SWITCH_CAUSE_INCOMPATIBLE_DESTINATION ) ;
2005-11-19 20:07:43 +00:00
}
2013-06-21 02:29:31 +00:00
2017-01-06 07:10:15 +00:00
if ( switch_core_session_in_thread ( channel - > session ) & & ! switch_channel_test_flag ( channel , CF_PROXY_MODE ) & &
2016-10-12 23:00:13 +00:00
! switch_channel_test_flag ( channel , CF_HAS_TEXT ) ) {
2013-06-21 02:29:31 +00:00
const char * delay ;
if ( ( delay = switch_channel_get_variable ( channel , " answer_delay " ) ) ) {
2014-08-03 02:41:44 +00:00
uint32_t msec = atoi ( delay ) ;
2017-01-06 07:10:15 +00:00
2013-06-21 02:29:31 +00:00
if ( msec ) {
2015-06-24 21:43:30 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( channel - > session ) , SWITCH_LOG_DEBUG , " Answer delay for %u msec \n " , msec ) ;
2013-06-21 02:29:31 +00:00
switch_ivr_sleep ( channel - > session , msec , SWITCH_TRUE , NULL ) ;
}
}
}
2008-02-20 03:57:01 +00:00
return status ;
2005-11-19 20:07:43 +00:00
}
2006-10-07 19:54:04 +00:00
2006-12-07 00:36:00 +00:00
# define resize(l) {\
2008-01-28 07:26:10 +00:00
char * dp ; \
olen + = ( len + l + block ) ; \
cpos = c - data ; \
if ( ( dp = realloc ( data , olen ) ) ) { \
data = dp ; \
c = data + cpos ; \
memset ( c , 0 , olen - cpos ) ; \
} } \
2006-12-07 00:36:00 +00:00
2012-04-12 12:23:08 +00:00
SWITCH_DECLARE ( char * ) switch_channel_expand_variables_check ( switch_channel_t * channel , const char * in , switch_event_t * var_list , switch_event_t * api_list , uint32_t recur )
2006-10-07 19:54:04 +00:00
{
2007-12-05 20:23:50 +00:00
char * p , * c = NULL ;
2008-08-11 15:37:50 +00:00
char * data , * indup , * endof_indup ;
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
size_t sp = 0 , len = 0 , olen = 0 , vtype = 0 , br = 0 , cpos , block = 128 ;
2012-04-11 20:30:37 +00:00
char * cloned_sub_val = NULL , * sub_val = NULL , * expanded_sub_val = NULL ;
2011-03-30 00:55:28 +00:00
char * func_val = NULL , * sb = NULL ;
2007-04-21 14:17:43 +00:00
int nv = 0 ;
2006-10-07 19:54:04 +00:00
2012-04-12 12:23:08 +00:00
if ( recur > 100 ) {
return ( char * ) in ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( in ) ) {
2008-05-27 04:30:03 +00:00
return ( char * ) in ;
2008-03-11 23:49:06 +00:00
}
2009-04-14 15:24:30 +00:00
nv = switch_string_var_check_const ( in ) | | switch_string_has_escaped_data ( in ) ;
2008-01-28 07:26:10 +00:00
2007-10-23 01:29:37 +00:00
if ( ! nv ) {
2008-05-27 04:30:03 +00:00
return ( char * ) in ;
2006-10-07 19:54:04 +00:00
}
2008-05-27 04:30:03 +00:00
2007-10-23 01:29:37 +00:00
nv = 0 ;
olen = strlen ( in ) + 1 ;
2006-10-07 19:54:04 +00:00
indup = strdup ( in ) ;
2008-08-11 20:43:19 +00:00
endof_indup = end_of_p ( indup ) + 1 ;
2006-10-07 19:54:04 +00:00
if ( ( data = malloc ( olen ) ) ) {
memset ( data , 0 , olen ) ;
c = data ;
2008-08-11 15:37:50 +00:00
for ( p = indup ; p & & p < endof_indup & & * p ; p + + ) {
2012-05-24 18:07:26 +00:00
int global = 0 ;
2006-10-07 19:54:04 +00:00
vtype = 0 ;
2008-01-28 07:26:10 +00:00
2007-04-21 14:17:43 +00:00
if ( * p = = ' \\ ' ) {
if ( * ( p + 1 ) = = ' $ ' ) {
nv = 1 ;
2009-05-21 20:10:24 +00:00
p + + ;
2012-05-24 18:07:26 +00:00
if ( * ( p + 1 ) = = ' $ ' ) {
p + + ;
}
2010-03-03 18:31:19 +00:00
} else if ( * ( p + 1 ) = = ' \' ' ) {
p + + ;
continue ;
2007-04-21 14:23:12 +00:00
} else if ( * ( p + 1 ) = = ' \\ ' ) {
2016-01-19 13:50:38 +00:00
if ( len + 1 > = olen ) {
resize ( 1 ) ;
}
2007-04-21 14:23:12 +00:00
* c + + = * p + + ;
len + + ;
continue ;
2007-04-21 14:17:43 +00:00
}
}
if ( * p = = ' $ ' & & ! nv ) {
2012-05-24 18:07:26 +00:00
if ( * ( p + 1 ) = = ' $ ' ) {
p + + ;
global + + ;
}
2008-05-27 04:30:03 +00:00
if ( * ( p + 1 ) ) {
if ( * ( p + 1 ) = = ' { ' ) {
2012-05-24 18:07:26 +00:00
vtype = global ? 3 : 1 ;
2007-10-18 21:36:57 +00:00
} else {
nv = 1 ;
2007-10-17 18:26:08 +00:00
}
} else {
nv = 1 ;
2007-03-29 22:31:56 +00:00
}
2006-10-07 19:54:04 +00:00
}
2006-12-07 00:36:00 +00:00
2007-04-21 14:17:43 +00:00
if ( nv ) {
2016-01-19 13:50:38 +00:00
if ( len + 1 > = olen ) {
resize ( 1 ) ;
}
2007-04-21 14:17:43 +00:00
* c + + = * p ;
len + + ;
nv = 0 ;
continue ;
}
2006-10-07 19:54:04 +00:00
if ( vtype ) {
char * s = p , * e , * vname , * vval = NULL ;
2006-10-08 04:37:03 +00:00
size_t nlen ;
2006-12-07 00:36:00 +00:00
2006-10-07 19:54:04 +00:00
s + + ;
2006-12-07 00:36:00 +00:00
2012-05-24 18:07:26 +00:00
if ( ( vtype = = 1 | | vtype = = 3 ) & & * s = = ' { ' ) {
2006-10-07 19:54:04 +00:00
br = 1 ;
s + + ;
}
e = s ;
vname = s ;
while ( * e ) {
if ( br = = 1 & & * e = = ' } ' ) {
br = 0 ;
* e + + = ' \0 ' ;
break ;
}
2007-11-07 02:14:57 +00:00
if ( br > 0 ) {
if ( e ! = s & & * e = = ' { ' ) {
br + + ;
} else if ( br > 1 & & * e = = ' } ' ) {
br - - ;
}
}
2008-01-28 07:26:10 +00:00
2006-10-07 19:54:04 +00:00
e + + ;
}
2008-08-11 15:37:50 +00:00
p = e > endof_indup ? endof_indup : e ;
2008-01-28 07:26:10 +00:00
2011-03-30 00:55:28 +00:00
vval = NULL ;
for ( sb = vname ; sb & & * sb ; sb + + ) {
if ( * sb = = ' ' ) {
vval = sb ;
break ;
} else if ( * sb = = ' ( ' ) {
vval = sb ;
br = 1 ;
break ;
}
}
if ( vval ) {
2007-10-18 21:36:57 +00:00
e = vval - 1 ;
* vval + + = ' \0 ' ;
2008-05-27 04:30:03 +00:00
while ( * e = = ' ' ) {
2007-10-18 21:36:57 +00:00
* e - - = ' \0 ' ;
}
2007-11-08 23:46:26 +00:00
e = vval ;
2010-10-08 20:59:22 +00:00
2008-05-27 04:30:03 +00:00
while ( e & & * e ) {
2007-11-08 23:46:26 +00:00
if ( * e = = ' ( ' ) {
br + + ;
} else if ( br > 1 & & * e = = ' ) ' ) {
br - - ;
} else if ( br = = 1 & & * e = = ' ) ' ) {
* e = ' \0 ' ;
break ;
}
e + + ;
2007-10-18 21:36:57 +00:00
}
2007-11-08 23:46:26 +00:00
2007-10-18 21:36:57 +00:00
vtype = 2 ;
}
2007-03-29 22:31:56 +00:00
2012-05-24 18:07:26 +00:00
if ( vtype = = 1 | | vtype = = 3 ) {
2007-11-07 18:28:33 +00:00
char * expanded = NULL ;
2007-11-09 19:25:46 +00:00
int offset = 0 ;
int ooffset = 0 ;
2007-12-17 22:52:32 +00:00
char * ptr ;
2011-05-25 20:42:36 +00:00
int idx = - 1 ;
2017-01-06 07:10:15 +00:00
2012-04-12 12:23:08 +00:00
if ( ( expanded = switch_channel_expand_variables_check ( channel , ( char * ) vname , var_list , api_list , recur + 1 ) ) = = vname ) {
2007-11-07 18:28:33 +00:00
expanded = NULL ;
} else {
vname = expanded ;
}
2011-05-25 20:42:36 +00:00
2007-12-17 22:52:32 +00:00
if ( ( ptr = strchr ( vname , ' : ' ) ) ) {
* ptr + + = ' \0 ' ;
offset = atoi ( ptr ) ;
if ( ( ptr = strchr ( ptr , ' : ' ) ) ) {
ptr + + ;
ooffset = atoi ( ptr ) ;
2007-11-09 19:25:46 +00:00
}
}
2008-01-28 07:26:10 +00:00
2011-05-25 20:42:36 +00:00
if ( ( ptr = strchr ( vname , ' [ ' ) ) & & strchr ( ptr , ' ] ' ) ) {
* ptr + + = ' \0 ' ;
idx = atoi ( ptr ) ;
}
2017-01-06 07:10:15 +00:00
2012-07-11 03:44:11 +00:00
if ( ( sub_val = ( char * ) switch_channel_get_variable_dup ( channel , vname , SWITCH_TRUE , idx ) ) ) {
2012-01-09 18:47:47 +00:00
if ( var_list & & ! switch_event_check_permission_list ( var_list , vname ) ) {
2012-07-27 23:53:04 +00:00
sub_val = " <Variable Expansion Permission Denied> " ;
2012-01-09 18:47:47 +00:00
}
2012-04-12 12:23:08 +00:00
if ( ( expanded_sub_val = switch_channel_expand_variables_check ( channel , sub_val , var_list , api_list , recur + 1 ) ) = = sub_val ) {
2012-04-11 20:30:37 +00:00
expanded_sub_val = NULL ;
} else {
sub_val = expanded_sub_val ;
}
2017-01-06 07:10:15 +00:00
2008-03-12 15:17:18 +00:00
if ( offset | | ooffset ) {
cloned_sub_val = strdup ( sub_val ) ;
switch_assert ( cloned_sub_val ) ;
sub_val = cloned_sub_val ;
}
2007-11-09 19:25:46 +00:00
2008-03-12 15:17:18 +00:00
if ( offset > = 0 ) {
2010-02-06 03:38:24 +00:00
if ( ( size_t ) offset > strlen ( sub_val ) ) {
2008-06-06 13:43:41 +00:00
* sub_val = ' \0 ' ;
} else {
sub_val + = offset ;
}
2008-05-27 04:30:03 +00:00
} else if ( ( size_t ) abs ( offset ) < = strlen ( sub_val ) ) {
2008-03-12 15:17:18 +00:00
sub_val = cloned_sub_val + ( strlen ( cloned_sub_val ) + offset ) ;
}
2007-11-09 19:25:46 +00:00
2008-05-27 04:30:03 +00:00
if ( ooffset > 0 & & ( size_t ) ooffset < strlen ( sub_val ) ) {
if ( ( ptr = ( char * ) sub_val + ooffset ) ) {
2008-03-12 15:17:18 +00:00
* ptr = ' \0 ' ;
}
2007-11-09 19:25:46 +00:00
}
}
2007-11-07 18:28:33 +00:00
switch_safe_free ( expanded ) ;
2006-10-07 19:54:04 +00:00
} else {
2007-03-29 22:31:56 +00:00
switch_stream_handle_t stream = { 0 } ;
2007-11-07 18:28:33 +00:00
char * expanded = NULL ;
2006-10-07 19:54:04 +00:00
SWITCH_STANDARD_STREAM ( stream ) ;
2007-03-29 22:31:56 +00:00
2006-10-07 19:54:04 +00:00
if ( stream . data ) {
2007-11-07 18:34:56 +00:00
char * expanded_vname = NULL ;
2017-01-06 07:10:15 +00:00
2012-04-12 12:23:08 +00:00
if ( ( expanded_vname = switch_channel_expand_variables_check ( channel , ( char * ) vname , var_list , api_list , recur + 1 ) ) = = vname ) {
2007-11-07 18:34:56 +00:00
expanded_vname = NULL ;
} else {
vname = expanded_vname ;
}
2007-11-07 02:14:57 +00:00
2012-04-12 12:23:08 +00:00
if ( ( expanded = switch_channel_expand_variables_check ( channel , vval , var_list , api_list , recur + 1 ) ) = = vval ) {
2007-11-07 00:00:51 +00:00
expanded = NULL ;
} else {
vval = expanded ;
}
2012-07-27 23:53:04 +00:00
if ( ! switch_core_test_flag ( SCF_API_EXPANSION ) | | ( api_list & & ! switch_event_check_permission_list ( api_list , vname ) ) ) {
func_val = NULL ;
sub_val = " <API Execute Permission Denied> " ;
2021-01-28 00:13:13 +00:00
free ( stream . data ) ;
2007-11-07 01:33:31 +00:00
} else {
2012-01-09 18:47:47 +00:00
if ( switch_api_execute ( vname , vval , channel - > session , & stream ) = = SWITCH_STATUS_SUCCESS ) {
func_val = stream . data ;
sub_val = func_val ;
} else {
free ( stream . data ) ;
}
2006-10-07 19:54:04 +00:00
}
2008-01-28 07:26:10 +00:00
2007-11-07 00:00:51 +00:00
switch_safe_free ( expanded ) ;
2007-11-07 18:34:56 +00:00
switch_safe_free ( expanded_vname ) ;
2008-01-28 07:26:10 +00:00
2006-10-07 19:54:04 +00:00
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_CRIT , " Memory Error! \n " ) ;
2006-10-07 19:54:04 +00:00
free ( data ) ;
free ( indup ) ;
2008-05-27 04:30:03 +00:00
return ( char * ) in ;
2006-10-07 19:54:04 +00:00
}
}
2006-11-26 20:06:04 +00:00
if ( ( nlen = sub_val ? strlen ( sub_val ) : 0 ) ) {
if ( len + nlen > = olen ) {
2007-03-29 22:31:56 +00:00
resize ( nlen ) ;
2006-11-26 20:06:04 +00:00
}
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
len + = nlen ;
strcat ( c , sub_val ) ;
c + = nlen ;
2006-10-07 19:54:04 +00:00
}
2007-03-29 22:31:56 +00:00
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
switch_safe_free ( func_val ) ;
2007-11-09 19:25:46 +00:00
switch_safe_free ( cloned_sub_val ) ;
2012-04-11 20:30:37 +00:00
switch_safe_free ( expanded_sub_val ) ;
2007-03-29 22:31:56 +00:00
sub_val = NULL ;
vname = NULL ;
2007-11-09 19:25:46 +00:00
br = 0 ;
2007-03-29 22:31:56 +00:00
}
2006-12-07 00:36:00 +00:00
2006-10-07 19:54:04 +00:00
if ( sp ) {
2016-01-19 13:50:38 +00:00
if ( len + 1 > = olen ) {
resize ( 1 ) ;
}
2006-10-07 19:54:04 +00:00
* c + + = ' ' ;
sp = 0 ;
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
len + + ;
2006-10-07 19:54:04 +00:00
}
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
2006-12-06 17:19:07 +00:00
if ( * p = = ' $ ' ) {
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
p - - ;
} else {
2016-01-19 13:50:38 +00:00
if ( len + 1 > = olen ) {
resize ( 1 ) ;
}
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
* c + + = * p ;
len + + ;
2007-03-29 22:31:56 +00:00
}
2006-10-07 19:54:04 +00:00
}
}
free ( indup ) ;
2008-01-28 07:26:10 +00:00
2006-10-07 19:54:04 +00:00
return data ;
}
2006-11-27 22:30:48 +00:00
2007-11-17 00:26:28 +00:00
SWITCH_DECLARE ( char * ) switch_channel_build_param_string ( switch_channel_t * channel , switch_caller_profile_t * caller_profile , const char * prefix )
2007-11-16 19:11:16 +00:00
{
switch_stream_handle_t stream = { 0 } ;
switch_size_t encode_len = 1024 , new_len = 0 ;
char * encode_buf = NULL ;
2011-10-11 20:13:23 +00:00
const char * prof [ 13 ] = { 0 } , * prof_names [ 13 ] = {
2008-05-27 04:30:03 +00:00
0 } ;
2007-11-16 19:11:16 +00:00
char * e = NULL ;
switch_event_header_t * hi ;
uint32_t x = 0 ;
SWITCH_STANDARD_STREAM ( stream ) ;
2007-11-17 00:26:28 +00:00
if ( prefix ) {
stream . write_function ( & stream , " %s& " , prefix ) ;
}
2007-11-16 19:11:16 +00:00
encode_buf = malloc ( encode_len ) ;
2007-12-11 19:23:57 +00:00
switch_assert ( encode_buf ) ;
2007-11-16 19:11:16 +00:00
if ( ! caller_profile ) {
caller_profile = switch_channel_get_caller_profile ( channel ) ;
}
2007-12-11 19:23:57 +00:00
switch_assert ( caller_profile ! = NULL ) ;
2008-01-28 07:26:10 +00:00
2007-11-16 19:11:16 +00:00
prof [ 0 ] = caller_profile - > context ;
prof [ 1 ] = caller_profile - > destination_number ;
prof [ 2 ] = caller_profile - > caller_id_name ;
prof [ 3 ] = caller_profile - > caller_id_number ;
prof [ 4 ] = caller_profile - > network_addr ;
prof [ 5 ] = caller_profile - > ani ;
prof [ 6 ] = caller_profile - > aniii ;
prof [ 7 ] = caller_profile - > rdnis ;
prof [ 8 ] = caller_profile - > source ;
prof [ 9 ] = caller_profile - > chan_name ;
prof [ 10 ] = caller_profile - > uuid ;
2011-10-11 20:13:23 +00:00
prof [ 11 ] = caller_profile - > transfer_source ;
2017-01-06 07:10:15 +00:00
2007-11-16 19:11:16 +00:00
prof_names [ 0 ] = " context " ;
prof_names [ 1 ] = " destination_number " ;
prof_names [ 2 ] = " caller_id_name " ;
prof_names [ 3 ] = " caller_id_number " ;
prof_names [ 4 ] = " network_addr " ;
prof_names [ 5 ] = " ani " ;
prof_names [ 6 ] = " aniii " ;
prof_names [ 7 ] = " rdnis " ;
prof_names [ 8 ] = " source " ;
prof_names [ 9 ] = " chan_name " ;
prof_names [ 10 ] = " uuid " ;
2011-10-11 20:13:23 +00:00
prof_names [ 11 ] = " transfer_source " ;
2007-11-16 19:11:16 +00:00
for ( x = 0 ; prof [ x ] ; x + + ) {
2009-10-23 16:03:42 +00:00
if ( zstr ( prof [ x ] ) ) {
2007-11-16 19:11:16 +00:00
continue ;
}
new_len = ( strlen ( prof [ x ] ) * 3 ) + 1 ;
if ( encode_len < new_len ) {
char * tmp ;
2017-01-06 07:10:15 +00:00
2007-11-16 19:11:16 +00:00
encode_len = new_len ;
if ( ! ( tmp = realloc ( encode_buf , encode_len ) ) ) {
abort ( ) ;
}
encode_buf = tmp ;
}
2008-05-21 21:31:17 +00:00
switch_url_encode ( prof [ x ] , encode_buf , encode_len ) ;
2007-11-16 19:11:16 +00:00
stream . write_function ( & stream , " %s=%s& " , prof_names [ x ] , encode_buf ) ;
}
2011-10-11 20:13:23 +00:00
if ( channel - > caller_profile - > soft ) {
profile_node_t * pn ;
for ( pn = channel - > caller_profile - > soft ; pn ; pn = pn - > next ) {
char * var = pn - > var ;
char * val = pn - > val ;
new_len = ( strlen ( ( char * ) var ) * 3 ) + 1 ;
if ( encode_len < new_len ) {
char * tmp ;
encode_len = new_len ;
tmp = realloc ( encode_buf , encode_len ) ;
switch_assert ( tmp ) ;
encode_buf = tmp ;
}
switch_url_encode ( ( char * ) val , encode_buf , encode_len ) ;
stream . write_function ( & stream , " %s=%s& " , ( char * ) var , encode_buf ) ;
}
}
2007-11-16 19:11:16 +00:00
if ( ( hi = switch_channel_variable_first ( channel ) ) ) {
for ( ; hi ; hi = hi - > next ) {
char * var = hi - > name ;
char * val = hi - > value ;
2008-01-28 07:26:10 +00:00
2007-11-16 19:11:16 +00:00
new_len = ( strlen ( ( char * ) var ) * 3 ) + 1 ;
if ( encode_len < new_len ) {
char * tmp ;
2008-01-28 07:26:10 +00:00
2007-11-16 19:11:16 +00:00
encode_len = new_len ;
2008-01-28 07:26:10 +00:00
2007-11-16 19:11:16 +00:00
tmp = realloc ( encode_buf , encode_len ) ;
2007-12-11 19:23:57 +00:00
switch_assert ( tmp ) ;
2007-11-16 19:11:16 +00:00
encode_buf = tmp ;
}
2008-05-21 21:31:17 +00:00
switch_url_encode ( ( char * ) val , encode_buf , encode_len ) ;
2007-11-16 19:11:16 +00:00
stream . write_function ( & stream , " %s=%s& " , ( char * ) var , encode_buf ) ;
}
switch_channel_variable_last ( channel ) ;
}
e = ( char * ) stream . data + ( strlen ( ( char * ) stream . data ) - 1 ) ;
if ( e & & * e = = ' & ' ) {
* e = ' \0 ' ;
}
switch_safe_free ( encode_buf ) ;
return stream . data ;
}
2009-10-21 18:48:28 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_pass_callee_id ( switch_channel_t * channel , switch_channel_t * other_channel )
{
int x = 0 ;
switch_assert ( channel ) ;
switch_assert ( other_channel ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
switch_mutex_lock ( other_channel - > profile_mutex ) ;
2009-10-23 16:03:42 +00:00
if ( ! zstr ( channel - > caller_profile - > callee_id_name ) ) {
2010-05-13 02:23:09 +00:00
other_channel - > caller_profile - > callee_id_name = switch_core_strdup ( other_channel - > caller_profile - > pool , channel - > caller_profile - > callee_id_name ) ;
2009-10-21 18:48:28 +00:00
x + + ;
}
2009-10-23 16:03:42 +00:00
if ( ! zstr ( channel - > caller_profile - > callee_id_number ) ) {
2010-05-13 02:23:09 +00:00
other_channel - > caller_profile - > callee_id_number = switch_core_strdup ( other_channel - > caller_profile - > pool , channel - > caller_profile - > callee_id_number ) ;
2009-10-21 18:48:28 +00:00
x + + ;
}
switch_mutex_unlock ( other_channel - > profile_mutex ) ;
switch_mutex_unlock ( channel - > profile_mutex ) ;
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
}
2008-07-17 19:46:25 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_get_variables ( switch_channel_t * channel , switch_event_t * * event )
{
switch_status_t status ;
switch_mutex_lock ( channel - > profile_mutex ) ;
2014-09-24 15:40:22 +00:00
if ( channel - > variables ) {
status = switch_event_dup ( event , channel - > variables ) ;
} else {
status = switch_event_create ( event , SWITCH_EVENT_CHANNEL_DATA ) ;
}
2008-11-03 15:45:38 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2008-07-17 19:46:25 +00:00
return status ;
}
2020-04-25 01:35:59 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_get_variables_prefix ( switch_channel_t * channel , const char * prefix , switch_event_t * * event )
{
switch_status_t status = SWITCH_STATUS_SUCCESS ;
switch_event_t * vars ;
switch_event_create ( & vars , SWITCH_EVENT_CHANNEL_DATA ) ;
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( channel - > variables ) {
switch_event_header_t * hi ;
for ( hi = channel - > variables - > headers ; hi ; hi = hi - > next ) {
if ( ! strncmp ( hi - > name , prefix , strlen ( prefix ) ) ) {
switch_event_add_header_string ( vars , SWITCH_STACK_BOTTOM , hi - > name , hi - > value ) ;
}
}
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
* event = vars ;
return status ;
}
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( switch_core_session_t * ) switch_channel_get_session ( switch_channel_t * channel )
2010-01-20 19:19:48 +00:00
{
switch_assert ( channel ) ;
return channel - > session ;
}
2007-12-20 18:04:07 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_set_timestamps ( switch_channel_t * channel )
{
switch_status_t status = SWITCH_STATUS_SUCCESS ;
const char * cid_buf = NULL ;
2014-04-28 20:06:39 +00:00
switch_caller_profile_t * caller_profile ;
2007-12-20 18:04:07 +00:00
switch_app_log_t * app_log , * ap ;
char * last_app = NULL , * last_arg = NULL ;
2017-01-06 07:10:15 +00:00
char start [ 80 ] = " " , resurrect [ 80 ] = " " , answer [ 80 ] = " " , hold [ 80 ] ,
2011-06-27 18:27:52 +00:00
bridge [ 80 ] = " " , progress [ 80 ] = " " , progress_media [ 80 ] = " " , end [ 80 ] = " " , tmp [ 80 ] = " " ,
2010-07-20 20:22:19 +00:00
profile_start [ 80 ] = " " ;
2008-05-24 03:24:12 +00:00
int32_t duration = 0 , legbillsec = 0 , billsec = 0 , mduration = 0 , billmsec = 0 , legbillmsec = 0 , progressmsec = 0 , progress_mediamsec = 0 ;
2011-04-28 18:46:39 +00:00
int32_t answersec = 0 , answermsec = 0 , waitsec = 0 , waitmsec = 0 ;
2009-08-24 17:12:36 +00:00
switch_time_t answerusec = 0 ;
2011-04-28 18:46:39 +00:00
switch_time_t uduration = 0 , legbillusec = 0 , billusec = 0 , progresssec = 0 , progressusec = 0 , progress_mediasec = 0 , progress_mediausec = 0 , waitusec = 0 ;
2011-06-27 18:27:52 +00:00
time_t tt_created = 0 , tt_answered = 0 , tt_resurrected = 0 , tt_bridged , tt_last_hold , tt_hold_accum ,
2011-04-28 18:46:39 +00:00
tt_progress = 0 , tt_progress_media = 0 , tt_hungup = 0 , mtt_created = 0 , mtt_answered = 0 , mtt_bridged = 0 ,
2012-06-26 16:34:24 +00:00
mtt_hungup = 0 , tt_prof_created , mtt_progress = 0 , mtt_progress_media = 0 ;
2009-02-23 16:31:59 +00:00
void * pop ;
2010-02-06 03:38:24 +00:00
char dtstr [ SWITCH_DTMF_LOG_LEN + 1 ] = " " ;
2009-02-23 16:31:59 +00:00
int x = 0 ;
2007-12-20 18:04:07 +00:00
2009-12-08 01:20:22 +00:00
switch_mutex_lock ( channel - > profile_mutex ) ;
2009-05-12 14:54:34 +00:00
if ( switch_channel_test_flag ( channel , CF_TIMESTAMP_SET ) ) {
2010-03-04 23:03:51 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2009-05-12 14:54:34 +00:00
return SWITCH_STATUS_FALSE ;
}
2010-02-06 03:38:24 +00:00
2009-12-08 01:20:22 +00:00
if ( ! ( caller_profile = channel - > caller_profile ) | | ! channel - > variables ) {
2010-03-04 23:03:51 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2008-03-11 21:32:56 +00:00
return SWITCH_STATUS_FALSE ;
}
2007-12-20 18:04:07 +00:00
2010-03-04 23:03:51 +00:00
switch_channel_set_flag ( channel , CF_TIMESTAMP_SET ) ;
2008-03-14 20:08:58 +00:00
if ( ( app_log = switch_core_session_get_app_log ( channel - > session ) ) ) {
for ( ap = app_log ; ap & & ap - > next ; ap = ap - > next ) ;
last_app = ap - > app ;
last_arg = ap - > arg ;
}
2008-05-27 04:30:03 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( caller_profile - > caller_id_name ) ) {
2008-05-27 04:30:03 +00:00
cid_buf = switch_core_session_sprintf ( channel - > session , " \" %s \" <%s> " , caller_profile - > caller_id_name ,
2008-03-11 21:32:56 +00:00
switch_str_nil ( caller_profile - > caller_id_number ) ) ;
2007-12-20 18:04:07 +00:00
} else {
cid_buf = caller_profile - > caller_id_number ;
}
2009-02-23 16:31:59 +00:00
while ( x < SWITCH_DTMF_LOG_LEN & & switch_queue_trypop ( channel - > dtmf_log_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
switch_dtmf_t * dt = ( switch_dtmf_t * ) pop ;
if ( dt ) {
dtstr [ x + + ] = dt - > digit ;
free ( dt ) ;
dt = NULL ;
}
}
2010-02-06 03:38:24 +00:00
2009-02-23 16:31:59 +00:00
if ( x ) {
2014-10-23 17:47:27 +00:00
const char * var = switch_channel_get_variable ( channel , " digits_dialed_filter " ) ;
char * digit_string = dtstr ;
char * X = NULL ;
switch_regex_t * re = NULL ;
char * substituted = NULL ;
if ( ! zstr ( var ) ) {
int proceed = 0 ;
int ovector [ 30 ] ;
if ( ( proceed = switch_regex_perform ( dtstr , var , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ) ) {
int len = ( strlen ( dtstr ) + strlen ( var ) + 10 ) * proceed ;
int i = 0 ;
const char * replace = NULL ;
X = malloc ( len ) ;
2017-01-06 07:10:15 +00:00
2014-10-23 17:47:27 +00:00
for ( i = 0 ; i < proceed ; i + + ) {
2017-06-05 23:15:18 +00:00
if ( pcre_get_substring ( dtstr , ovector , proceed , i , & replace ) > = 0 ) {
if ( replace ) {
switch_size_t plen = strlen ( replace ) ;
memset ( X , ' X ' , plen ) ;
* ( X + plen ) = ' \0 ' ;
switch_safe_free ( substituted ) ;
substituted = switch_string_replace ( substituted ? substituted : dtstr , replace , X ) ;
pcre_free_substring ( replace ) ;
}
2014-10-23 17:47:27 +00:00
}
}
2017-01-06 07:10:15 +00:00
2014-10-23 17:47:27 +00:00
if ( ! zstr ( substituted ) ) {
digit_string = substituted ;
}
}
}
switch_channel_set_variable ( channel , " digits_dialed " , digit_string ) ;
switch_regex_safe_free ( re ) ;
switch_safe_free ( substituted ) ;
switch_safe_free ( X ) ;
2009-02-23 16:31:59 +00:00
} else {
switch_channel_set_variable ( channel , " digits_dialed " , " none " ) ;
}
2007-12-20 18:04:07 +00:00
if ( caller_profile - > times ) {
switch_time_exp_t tm ;
switch_size_t retsize ;
const char * fmt = " %Y-%m-%d %T " ;
switch_time_exp_lt ( & tm , caller_profile - > times - > created ) ;
2008-10-12 21:51:51 +00:00
switch_strftime_nocheck ( start , & retsize , sizeof ( start ) , fmt , & tm ) ;
2007-12-20 18:04:07 +00:00
switch_channel_set_variable ( channel , " start_stamp " , start ) ;
switch_time_exp_lt ( & tm , caller_profile - > times - > profile_created ) ;
2008-10-12 21:51:51 +00:00
switch_strftime_nocheck ( profile_start , & retsize , sizeof ( profile_start ) , fmt , & tm ) ;
2007-12-20 18:04:07 +00:00
switch_channel_set_variable ( channel , " profile_start_stamp " , profile_start ) ;
2008-02-26 21:55:59 +00:00
if ( caller_profile - > times - > answered ) {
switch_time_exp_lt ( & tm , caller_profile - > times - > answered ) ;
2008-10-12 21:51:51 +00:00
switch_strftime_nocheck ( answer , & retsize , sizeof ( answer ) , fmt , & tm ) ;
2008-02-26 21:55:59 +00:00
switch_channel_set_variable ( channel , " answer_stamp " , answer ) ;
}
2007-12-20 18:04:07 +00:00
2011-04-28 18:46:39 +00:00
if ( caller_profile - > times - > bridged ) {
switch_time_exp_lt ( & tm , caller_profile - > times - > bridged ) ;
switch_strftime_nocheck ( bridge , & retsize , sizeof ( bridge ) , fmt , & tm ) ;
switch_channel_set_variable ( channel , " bridge_stamp " , bridge ) ;
}
2011-06-27 18:27:52 +00:00
if ( caller_profile - > times - > last_hold ) {
switch_time_exp_lt ( & tm , caller_profile - > times - > last_hold ) ;
switch_strftime_nocheck ( hold , & retsize , sizeof ( hold ) , fmt , & tm ) ;
switch_channel_set_variable ( channel , " hold_stamp " , hold ) ;
}
2010-02-06 03:38:24 +00:00
if ( caller_profile - > times - > resurrected ) {
switch_time_exp_lt ( & tm , caller_profile - > times - > resurrected ) ;
2010-07-20 20:22:19 +00:00
switch_strftime_nocheck ( resurrect , & retsize , sizeof ( resurrect ) , fmt , & tm ) ;
2010-02-06 03:38:24 +00:00
switch_channel_set_variable ( channel , " resurrect_stamp " , resurrect ) ;
}
2008-05-24 01:43:12 +00:00
if ( caller_profile - > times - > progress ) {
switch_time_exp_lt ( & tm , caller_profile - > times - > progress ) ;
2008-10-12 21:51:51 +00:00
switch_strftime_nocheck ( progress , & retsize , sizeof ( progress ) , fmt , & tm ) ;
2008-05-24 01:43:12 +00:00
switch_channel_set_variable ( channel , " progress_stamp " , progress ) ;
}
if ( caller_profile - > times - > progress_media ) {
switch_time_exp_lt ( & tm , caller_profile - > times - > progress_media ) ;
2008-10-12 21:51:51 +00:00
switch_strftime_nocheck ( progress_media , & retsize , sizeof ( progress_media ) , fmt , & tm ) ;
2008-05-24 01:43:12 +00:00
switch_channel_set_variable ( channel , " progress_media_stamp " , progress_media ) ;
}
2012-09-12 21:36:17 +00:00
if ( channel - > hold_record ) {
switch_hold_record_t * hr ;
switch_stream_handle_t stream = { 0 } ;
SWITCH_STANDARD_STREAM ( stream ) ;
stream . write_function ( & stream , " { " , SWITCH_VA_NONE ) ;
for ( hr = channel - > hold_record ; hr ; hr = hr - > next ) {
stream . write_function ( & stream , " {% " SWITCH_TIME_T_FMT " ,% " SWITCH_TIME_T_FMT " }, " , hr - > on , hr - > off ) ;
}
end_of ( ( char * ) stream . data ) = ' } ' ;
switch_channel_set_variable ( channel , " hold_events " , ( char * ) stream . data ) ;
free ( stream . data ) ;
}
2007-12-20 18:04:07 +00:00
switch_time_exp_lt ( & tm , caller_profile - > times - > hungup ) ;
2008-10-12 21:51:51 +00:00
switch_strftime_nocheck ( end , & retsize , sizeof ( end ) , fmt , & tm ) ;
2007-12-20 18:04:07 +00:00
switch_channel_set_variable ( channel , " end_stamp " , end ) ;
tt_created = ( time_t ) ( caller_profile - > times - > created / 1000000 ) ;
mtt_created = ( time_t ) ( caller_profile - > times - > created / 1000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_created ) ;
switch_channel_set_variable ( channel , " start_epoch " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > created ) ;
switch_channel_set_variable ( channel , " start_uepoch " , tmp ) ;
2010-07-20 20:22:19 +00:00
tt_prof_created = ( time_t ) ( caller_profile - > times - > profile_created / 1000000 ) ;
2007-12-20 18:04:07 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_prof_created ) ;
switch_channel_set_variable ( channel , " profile_start_epoch " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > profile_created ) ;
switch_channel_set_variable ( channel , " profile_start_uepoch " , tmp ) ;
2008-01-28 07:26:10 +00:00
2007-12-20 18:04:07 +00:00
tt_answered = ( time_t ) ( caller_profile - > times - > answered / 1000000 ) ;
mtt_answered = ( time_t ) ( caller_profile - > times - > answered / 1000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_answered ) ;
switch_channel_set_variable ( channel , " answer_epoch " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > answered ) ;
2008-05-27 04:30:03 +00:00
switch_channel_set_variable ( channel , " answer_uepoch " , tmp ) ;
2007-12-20 18:04:07 +00:00
2011-04-28 18:46:39 +00:00
tt_bridged = ( time_t ) ( caller_profile - > times - > bridged / 1000000 ) ;
mtt_bridged = ( time_t ) ( caller_profile - > times - > bridged / 1000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_bridged ) ;
switch_channel_set_variable ( channel , " bridge_epoch " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > bridged ) ;
switch_channel_set_variable ( channel , " bridge_uepoch " , tmp ) ;
2011-06-27 18:27:52 +00:00
tt_last_hold = ( time_t ) ( caller_profile - > times - > last_hold / 1000000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_last_hold ) ;
switch_channel_set_variable ( channel , " last_hold_epoch " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > last_hold ) ;
switch_channel_set_variable ( channel , " last_hold_uepoch " , tmp ) ;
tt_hold_accum = ( time_t ) ( caller_profile - > times - > hold_accum / 1000000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_hold_accum ) ;
switch_channel_set_variable ( channel , " hold_accum_seconds " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > hold_accum ) ;
switch_channel_set_variable ( channel , " hold_accum_usec " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > hold_accum / 1000 ) ;
switch_channel_set_variable ( channel , " hold_accum_ms " , tmp ) ;
2010-02-06 03:38:24 +00:00
tt_resurrected = ( time_t ) ( caller_profile - > times - > resurrected / 1000000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_resurrected ) ;
switch_channel_set_variable ( channel , " resurrect_epoch " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > resurrected ) ;
switch_channel_set_variable ( channel , " resurrect_uepoch " , tmp ) ;
2008-05-24 01:43:12 +00:00
tt_progress = ( time_t ) ( caller_profile - > times - > progress / 1000000 ) ;
mtt_progress = ( time_t ) ( caller_profile - > times - > progress / 1000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_progress ) ;
2009-01-14 13:36:32 +00:00
switch_channel_set_variable ( channel , " progress_epoch " , tmp ) ;
2008-05-24 01:43:12 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > progress ) ;
2009-01-14 13:36:32 +00:00
switch_channel_set_variable ( channel , " progress_uepoch " , tmp ) ;
2008-05-24 01:43:12 +00:00
tt_progress_media = ( time_t ) ( caller_profile - > times - > progress_media / 1000000 ) ;
mtt_progress_media = ( time_t ) ( caller_profile - > times - > progress_media / 1000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_progress_media ) ;
2009-01-14 13:36:32 +00:00
switch_channel_set_variable ( channel , " progress_media_epoch " , tmp ) ;
2008-05-24 01:43:12 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > progress_media ) ;
2009-01-14 13:36:32 +00:00
switch_channel_set_variable ( channel , " progress_media_uepoch " , tmp ) ;
2008-05-24 01:43:12 +00:00
2007-12-20 18:04:07 +00:00
tt_hungup = ( time_t ) ( caller_profile - > times - > hungup / 1000000 ) ;
mtt_hungup = ( time_t ) ( caller_profile - > times - > hungup / 1000 ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " TIME_T_FMT , tt_hungup ) ;
switch_channel_set_variable ( channel , " end_epoch " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > hungup ) ;
switch_channel_set_variable ( channel , " end_uepoch " , tmp ) ;
2008-05-27 04:30:03 +00:00
duration = ( int32_t ) ( tt_hungup - tt_created ) ;
mduration = ( int32_t ) ( mtt_hungup - mtt_created ) ;
2010-07-20 20:22:19 +00:00
uduration = caller_profile - > times - > hungup - caller_profile - > times - > created ;
2008-01-28 07:26:10 +00:00
2011-04-28 18:46:39 +00:00
if ( caller_profile - > times - > bridged > caller_profile - > times - > created ) {
waitsec = ( int32_t ) ( tt_bridged - tt_created ) ;
waitmsec = ( int32_t ) ( mtt_bridged - mtt_created ) ;
waitusec = caller_profile - > times - > bridged - caller_profile - > times - > created ;
} else {
waitsec = 0 ;
waitmsec = 0 ;
waitusec = 0 ;
}
2007-12-20 18:04:07 +00:00
if ( caller_profile - > times - > answered ) {
2008-05-27 04:30:03 +00:00
billsec = ( int32_t ) ( tt_hungup - tt_answered ) ;
billmsec = ( int32_t ) ( mtt_hungup - mtt_answered ) ;
2007-12-20 18:04:07 +00:00
billusec = caller_profile - > times - > hungup - caller_profile - > times - > answered ;
2012-06-26 16:34:24 +00:00
legbillsec = ( int32_t ) ( tt_hungup - tt_created ) ;
legbillmsec = ( int32_t ) ( mtt_hungup - mtt_created ) ;
legbillusec = caller_profile - > times - > hungup - caller_profile - > times - > created ;
2009-08-24 17:12:36 +00:00
2012-06-26 16:34:24 +00:00
answersec = ( int32_t ) ( tt_answered - tt_created ) ;
answermsec = ( int32_t ) ( mtt_answered - mtt_created ) ;
answerusec = caller_profile - > times - > answered - caller_profile - > times - > created ;
2007-12-20 18:04:07 +00:00
}
2008-05-24 03:24:12 +00:00
if ( caller_profile - > times - > progress ) {
2008-05-27 04:30:03 +00:00
progresssec = ( int32_t ) ( tt_progress - tt_created ) ;
progressmsec = ( int32_t ) ( mtt_progress - mtt_created ) ;
2008-05-24 03:24:12 +00:00
progressusec = caller_profile - > times - > progress - caller_profile - > times - > created ;
}
if ( caller_profile - > times - > progress_media ) {
2009-02-12 20:10:51 +00:00
progress_mediasec = ( int32_t ) ( tt_progress_media - tt_created ) ;
progress_mediamsec = ( int32_t ) ( mtt_progress_media - mtt_created ) ;
progress_mediausec = caller_profile - > times - > progress_media - caller_profile - > times - > created ;
2008-05-24 03:24:12 +00:00
}
2007-12-20 18:04:07 +00:00
}
2008-01-27 17:36:53 +00:00
2007-12-20 18:04:07 +00:00
switch_channel_set_variable ( channel , " last_app " , last_app ) ;
switch_channel_set_variable ( channel , " last_arg " , last_arg ) ;
switch_channel_set_variable ( channel , " caller_id " , cid_buf ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , duration ) ;
switch_channel_set_variable ( channel , " duration " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , billsec ) ;
switch_channel_set_variable ( channel , " billsec " , tmp ) ;
2011-06-02 03:36:19 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , progresssec ) ;
2008-05-24 03:24:12 +00:00
switch_channel_set_variable ( channel , " progresssec " , tmp ) ;
2010-07-20 20:22:19 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , answersec ) ;
2009-08-24 17:12:36 +00:00
switch_channel_set_variable ( channel , " answersec " , tmp ) ;
2011-04-28 18:46:39 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , waitsec ) ;
switch_channel_set_variable ( channel , " waitsec " , tmp ) ;
2011-06-02 03:36:19 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , progress_mediasec ) ;
2008-05-24 03:24:12 +00:00
switch_channel_set_variable ( channel , " progress_mediasec " , tmp ) ;
2007-12-20 18:04:07 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , legbillsec ) ;
switch_channel_set_variable ( channel , " flow_billsec " , tmp ) ;
2008-01-28 07:26:10 +00:00
2007-12-20 18:04:07 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , mduration ) ;
switch_channel_set_variable ( channel , " mduration " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , billmsec ) ;
switch_channel_set_variable ( channel , " billmsec " , tmp ) ;
2008-05-24 03:24:12 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , progressmsec ) ;
switch_channel_set_variable ( channel , " progressmsec " , tmp ) ;
2009-08-24 17:12:36 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , answermsec ) ;
switch_channel_set_variable ( channel , " answermsec " , tmp ) ;
2011-04-28 18:46:39 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , waitmsec ) ;
switch_channel_set_variable ( channel , " waitmsec " , tmp ) ;
2010-07-20 20:22:19 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , progress_mediamsec ) ;
2008-05-24 03:24:12 +00:00
switch_channel_set_variable ( channel , " progress_mediamsec " , tmp ) ;
2007-12-20 18:04:07 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , legbillmsec ) ;
switch_channel_set_variable ( channel , " flow_billmsec " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , uduration ) ;
switch_channel_set_variable ( channel , " uduration " , tmp ) ;
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , billusec ) ;
switch_channel_set_variable ( channel , " billusec " , tmp ) ;
2008-05-24 03:24:12 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , progressusec ) ;
switch_channel_set_variable ( channel , " progressusec " , tmp ) ;
2009-08-24 17:12:36 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , answerusec ) ;
switch_channel_set_variable ( channel , " answerusec " , tmp ) ;
2011-04-28 18:46:39 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , waitusec ) ;
switch_channel_set_variable ( channel , " waitusec " , tmp ) ;
2008-05-24 03:24:12 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , progress_mediausec ) ;
switch_channel_set_variable ( channel , " progress_mediausec " , tmp ) ;
2007-12-20 18:04:07 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , legbillusec ) ;
switch_channel_set_variable ( channel , " flow_billusec " , tmp ) ;
2010-02-06 03:38:24 +00:00
2009-12-08 01:20:22 +00:00
switch_mutex_unlock ( channel - > profile_mutex ) ;
2007-12-20 18:04:07 +00:00
return status ;
}
2007-11-16 19:11:16 +00:00
2017-06-22 20:48:20 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_get_partner_uuid_copy ( switch_channel_t * channel , char * buf , switch_size_t blen )
{
const char * uuid = NULL ;
switch_mutex_lock ( channel - > profile_mutex ) ;
if ( ! ( uuid = switch_channel_get_variable_dup ( channel , SWITCH_SIGNAL_BOND_VARIABLE , SWITCH_TRUE , - 1 ) ) ) {
uuid = switch_channel_get_variable_dup ( channel , SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE , SWITCH_TRUE , - 1 ) ;
}
if ( uuid ) {
strncpy ( buf , uuid , blen ) ;
uuid = ( const char * ) buf ;
}
switch_mutex_unlock ( channel - > profile_mutex ) ;
return uuid ;
}
2012-05-29 18:10:15 +00:00
SWITCH_DECLARE ( const char * ) switch_channel_get_partner_uuid ( switch_channel_t * channel )
{
const char * uuid = NULL ;
if ( ! ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ) ) {
uuid = switch_channel_get_variable ( channel , SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE ) ;
}
return uuid ;
}
2013-05-22 16:01:39 +00:00
SWITCH_DECLARE ( void ) switch_channel_handle_cause ( switch_channel_t * channel , switch_call_cause_t cause )
{
switch_core_session_t * session = channel - > session ;
const char * transfer_on_fail = NULL ;
char * tof_data = NULL ;
char * tof_array [ 4 ] = { 0 } ;
//int tof_arrayc = 0;
if ( ! switch_channel_up_nosig ( channel ) ) {
return ;
}
transfer_on_fail = switch_channel_get_variable ( channel , " transfer_on_fail " ) ;
tof_data = switch_core_session_strdup ( session , transfer_on_fail ) ;
switch_split ( tof_data , ' ' , tof_array ) ;
transfer_on_fail = tof_array [ 0 ] ;
2017-01-06 07:10:15 +00:00
/*
2013-05-22 16:01:39 +00:00
if the variable continue_on_fail is set it can be :
' true ' to continue on all failures .
' false ' to not continue .
A list of codes either names or numbers eg " user_busy,normal_temporary_failure,603 "
2017-01-06 07:10:15 +00:00
failure_causes acts as the opposite version
2013-05-22 16:01:39 +00:00
EXCEPTION . . . ATTENDED_TRANSFER never is a reason to continue . . . . . . .
*/
if ( cause ! = SWITCH_CAUSE_ATTENDED_TRANSFER ) {
const char * continue_on_fail = NULL , * failure_causes = NULL ;
continue_on_fail = switch_channel_get_variable ( channel , " continue_on_fail " ) ;
failure_causes = switch_channel_get_variable ( channel , " failure_causes " ) ;
if ( continue_on_fail | | failure_causes ) {
const char * cause_str ;
char cause_num [ 35 ] = " " ;
cause_str = switch_channel_cause2str ( cause ) ;
switch_snprintf ( cause_num , sizeof ( cause_num ) , " %u " , cause ) ;
if ( failure_causes ) {
char * lbuf = switch_core_session_strdup ( session , failure_causes ) ;
char * argv [ 256 ] = { 0 } ;
int argc = switch_separate_string ( lbuf , ' , ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
int i , x = 0 ;
for ( i = 0 ; i < argc ; i + + ) {
if ( ! strcasecmp ( argv [ i ] , cause_str ) | | ! strcasecmp ( argv [ i ] , cause_num ) ) {
x + + ;
break ;
}
}
if ( ! x ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG ,
" Failure causes [%s]: Cause: %s \n " , failure_causes , cause_str ) ;
return ;
}
}
if ( continue_on_fail ) {
if ( switch_true ( continue_on_fail ) ) {
return ;
} else {
char * lbuf = switch_core_session_strdup ( session , continue_on_fail ) ;
char * argv [ 256 ] = { 0 } ;
int argc = switch_separate_string ( lbuf , ' , ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
int i ;
for ( i = 0 ; i < argc ; i + + ) {
if ( ! strcasecmp ( argv [ i ] , cause_str ) | | ! strcasecmp ( argv [ i ] , cause_num ) ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG ,
" Continue on fail [%s]: Cause: %s \n " , continue_on_fail , cause_str ) ;
return ;
}
}
}
}
} else {
/* no answer is *always* a reason to continue */
if ( cause = = SWITCH_CAUSE_NO_ANSWER | | cause = = SWITCH_CAUSE_NO_USER_RESPONSE | | cause = = SWITCH_CAUSE_ORIGINATOR_CANCEL ) {
return ;
}
}
2017-01-06 07:10:15 +00:00
2013-05-22 16:01:39 +00:00
if ( transfer_on_fail | | failure_causes ) {
const char * cause_str ;
char cause_num [ 35 ] = " " ;
cause_str = switch_channel_cause2str ( cause ) ;
switch_snprintf ( cause_num , sizeof ( cause_num ) , " %u " , cause ) ;
if ( ( tof_array [ 1 ] = = NULL ) | | ( ! strcasecmp ( tof_array [ 1 ] , " auto_cause " ) ) ) {
tof_array [ 1 ] = ( char * ) cause_str ;
}
if ( failure_causes ) {
char * lbuf = switch_core_session_strdup ( session , failure_causes ) ;
char * argv [ 256 ] = { 0 } ;
int argc = switch_separate_string ( lbuf , ' , ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
int i , x = 0 ;
for ( i = 0 ; i < argc ; i + + ) {
if ( ! strcasecmp ( argv [ i ] , cause_str ) | | ! strcasecmp ( argv [ i ] , cause_num ) ) {
x + + ;
break ;
}
}
if ( ! x ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG ,
" Failure causes [%s]: Cause: %s \n " , failure_causes , cause_str ) ;
2017-01-06 07:10:15 +00:00
2013-05-22 16:01:39 +00:00
switch_ivr_session_transfer ( session , tof_array [ 1 ] , tof_array [ 2 ] , tof_array [ 3 ] ) ;
}
}
if ( transfer_on_fail ) {
if ( switch_true ( transfer_on_fail ) ) {
return ;
} else {
char * lbuf = switch_core_session_strdup ( session , transfer_on_fail ) ;
char * argv [ 256 ] = { 0 } ;
int argc = switch_separate_string ( lbuf , ' , ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
int i ;
for ( i = 0 ; i < argc ; i + + ) {
if ( ! strcasecmp ( argv [ i ] , cause_str ) | | ! strcasecmp ( argv [ i ] , cause_num ) ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG ,
" Transfer on fail [%s]: Cause: %s \n " , transfer_on_fail , cause_str ) ;
switch_ivr_session_transfer ( session , tof_array [ 1 ] , tof_array [ 2 ] , tof_array [ 3 ] ) ;
}
}
}
}
2017-01-06 07:10:15 +00:00
}
2013-05-22 16:01:39 +00:00
}
2017-01-06 07:10:15 +00:00
if ( ! switch_channel_test_flag ( channel , CF_TRANSFER ) & & ! switch_channel_test_flag ( channel , CF_CONFIRM_BLIND_TRANSFER ) & &
2013-05-22 16:01:39 +00:00
switch_channel_get_state ( channel ) ! = CS_ROUTING ) {
switch_channel_hangup ( channel , cause ) ;
}
}
2013-06-05 16:19:44 +00:00
SWITCH_DECLARE ( void ) switch_channel_global_init ( switch_memory_pool_t * pool )
{
memset ( & globals , 0 , sizeof ( globals ) ) ;
globals . pool = pool ;
switch_mutex_init ( & globals . device_mutex , SWITCH_MUTEX_NESTED , pool ) ;
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & globals . device_hash ) ;
2013-06-05 16:19:44 +00:00
}
SWITCH_DECLARE ( void ) switch_channel_global_uninit ( void )
{
switch_core_hash_destroy ( & globals . device_hash ) ;
}
static void fetch_device_stats ( switch_device_record_t * drec )
{
switch_device_node_t * np ;
2013-10-24 01:45:29 +00:00
2013-06-05 16:19:44 +00:00
memset ( & drec - > stats , 0 , sizeof ( switch_device_stats_t ) ) ;
2017-01-06 07:10:15 +00:00
2013-06-05 16:19:44 +00:00
switch_mutex_lock ( drec - > mutex ) ;
for ( np = drec - > uuid_list ; np ; np = np - > next ) {
drec - > stats . total + + ;
2013-10-24 01:45:29 +00:00
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . total_in + + ;
} else {
drec - > stats . total_out + + ;
}
2017-01-06 07:10:15 +00:00
2013-06-05 16:19:44 +00:00
if ( ! np - > hup_profile ) {
drec - > stats . offhook + + ;
2013-10-24 01:45:29 +00:00
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . offhook_in + + ;
} else {
drec - > stats . offhook_out + + ;
}
2013-06-05 16:19:44 +00:00
if ( np - > callstate = = CCS_HELD ) {
drec - > stats . held + + ;
2013-10-24 01:45:29 +00:00
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . held_in + + ;
} else {
drec - > stats . held_out + + ;
}
2014-05-30 19:30:59 +00:00
} else if ( np - > callstate = = CCS_UNHELD ) {
drec - > stats . unheld + + ;
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . unheld_in + + ;
} else {
drec - > stats . unheld_out + + ;
}
2013-06-05 16:19:44 +00:00
} else {
2013-06-11 00:13:05 +00:00
if ( np - > callstate = = CCS_EARLY ) {
drec - > stats . early + + ;
2013-10-24 01:45:29 +00:00
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . early_in + + ;
} else {
drec - > stats . early_out + + ;
}
2013-06-11 00:13:05 +00:00
} else if ( np - > callstate = = CCS_RINGING ) {
drec - > stats . ringing + + ;
2013-10-24 01:45:29 +00:00
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . ringing_in + + ;
} else {
drec - > stats . ringing_out + + ;
}
2013-10-30 19:08:27 +00:00
} else if ( np - > callstate = = CCS_RING_WAIT ) {
drec - > stats . ring_wait + + ;
2013-10-24 04:09:14 +00:00
} else if ( np - > callstate = = CCS_HANGUP ) {
drec - > stats . hup + + ;
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . hup_in + + ;
} else {
drec - > stats . hup_out + + ;
}
2013-06-11 16:23:45 +00:00
} else if ( np - > callstate ! = CCS_DOWN ) {
2013-06-11 00:13:05 +00:00
drec - > stats . active + + ;
2013-10-24 01:45:29 +00:00
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . active_in + + ;
} else {
drec - > stats . active_out + + ;
}
2013-06-11 00:13:05 +00:00
}
2013-06-05 16:19:44 +00:00
}
} else {
drec - > stats . hup + + ;
2013-10-24 01:45:29 +00:00
if ( np - > direction = = SWITCH_CALL_DIRECTION_INBOUND ) {
drec - > stats . hup_in + + ;
} else {
drec - > stats . hup_out + + ;
}
2013-06-05 16:19:44 +00:00
}
}
switch_mutex_unlock ( drec - > mutex ) ;
}
SWITCH_DECLARE ( void ) switch_channel_clear_device_record ( switch_channel_t * channel )
{
switch_memory_pool_t * pool ;
int sanity = 100 ;
switch_device_node_t * np ;
switch_event_t * event ;
if ( ! channel - > device_node | | ! switch_channel_test_flag ( channel , CF_FINAL_DEVICE_LEG ) ) {
return ;
}
while ( - - sanity & & channel - > device_node - > parent - > refs ) {
switch_yield ( 100000 ) ;
}
2017-01-06 07:10:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_DEBUG , " Destroying device cdr %s on device [%s] \n " ,
2013-06-05 16:19:44 +00:00
channel - > device_node - > parent - > uuid ,
channel - > device_node - > parent - > device_id ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_CALL_DETAIL ) = = SWITCH_STATUS_SUCCESS ) {
int x = 0 ;
char prefix [ 80 ] = " " ;
2013-06-10 23:21:46 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Type " , " device " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Device-ID " , channel - > device_node - > parent - > device_id ) ;
2013-06-05 16:19:44 +00:00
switch_mutex_lock ( channel - > device_node - > parent - > mutex ) ;
for ( np = channel - > device_node - > parent - > uuid_list ; np ; np = np - > next ) {
switch_snprintf ( prefix , sizeof ( prefix ) , " Call-%d " , + + x ) ;
switch_caller_profile_event_set_data ( np - > hup_profile , prefix , event ) ;
}
switch_mutex_unlock ( channel - > device_node - > parent - > mutex ) ;
switch_event_fire ( & event ) ;
}
switch_mutex_lock ( channel - > device_node - > parent - > mutex ) ;
for ( np = channel - > device_node - > parent - > uuid_list ; np ; np = np - > next ) {
if ( np - > xml_cdr ) {
switch_xml_free ( np - > xml_cdr ) ;
}
if ( np - > event ) {
switch_event_destroy ( & np - > event ) ;
}
}
switch_mutex_unlock ( channel - > device_node - > parent - > mutex ) ;
pool = channel - > device_node - > parent - > pool ;
switch_mutex_lock ( globals . device_mutex ) ;
2017-01-06 07:10:15 +00:00
switch_core_destroy_memory_pool ( & pool ) ;
2013-06-05 16:19:44 +00:00
switch_mutex_unlock ( globals . device_mutex ) ;
2017-01-06 07:10:15 +00:00
2013-06-05 16:19:44 +00:00
}
2017-01-06 07:10:15 +00:00
SWITCH_DECLARE ( void ) switch_channel_process_device_hangup ( switch_channel_t * channel )
2014-02-23 00:17:01 +00:00
{
switch_channel_check_device_state ( channel , channel - > callstate ) ;
process_device_hup ( channel ) ;
}
2013-06-05 16:19:44 +00:00
static void process_device_hup ( switch_channel_t * channel )
{
switch_hold_record_t * hr , * newhr , * last = NULL ;
2013-06-28 19:20:58 +00:00
switch_device_record_t * drec = NULL ;
switch_device_node_t * node ;
2013-06-05 16:19:44 +00:00
if ( ! channel - > device_node ) {
return ;
}
2017-01-06 07:10:15 +00:00
2013-06-05 16:19:44 +00:00
switch_mutex_lock ( globals . device_mutex ) ;
2013-06-28 19:20:58 +00:00
node = channel - > device_node ;
drec = channel - > device_node - > parent ;
node - > hup_profile = switch_caller_profile_dup ( drec - > pool , channel - > caller_profile ) ;
fetch_device_stats ( drec ) ;
2013-06-05 16:19:44 +00:00
2013-06-28 19:20:58 +00:00
switch_ivr_generate_xml_cdr ( channel - > session , & node - > xml_cdr ) ;
if ( switch_event_create ( & node - > event , SWITCH_EVENT_CALL_DETAIL ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_extended_data ( channel , node - > event ) ;
2013-06-05 16:19:44 +00:00
}
for ( hr = channel - > hold_record ; hr ; hr = hr - > next ) {
2013-06-28 19:20:58 +00:00
newhr = switch_core_alloc ( drec - > pool , sizeof ( * newhr ) ) ;
2013-06-05 16:19:44 +00:00
newhr - > on = hr - > on ;
newhr - > off = hr - > off ;
if ( hr - > uuid ) {
2013-06-28 19:20:58 +00:00
newhr - > uuid = switch_core_strdup ( drec - > pool , hr - > uuid ) ;
2013-06-05 16:19:44 +00:00
}
2013-06-28 19:20:58 +00:00
if ( ! node - > hold_record ) {
node - > hold_record = newhr ;
2014-04-28 20:30:19 +00:00
} else if ( last ) {
2013-06-05 16:19:44 +00:00
last - > next = newhr ;
}
last = newhr ;
2017-01-06 07:10:15 +00:00
}
2013-06-05 16:19:44 +00:00
2013-06-28 19:20:58 +00:00
if ( ! drec - > stats . offhook ) { /* this is final call */
2013-06-05 16:19:44 +00:00
2013-06-28 19:20:58 +00:00
switch_core_hash_delete ( globals . device_hash , drec - > device_id ) ;
2017-01-06 07:10:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_DEBUG , " Processing last call from device [%s] \n " ,
2013-06-28 19:20:58 +00:00
drec - > device_id ) ;
2013-06-05 16:19:44 +00:00
switch_channel_set_flag ( channel , CF_FINAL_DEVICE_LEG ) ;
2013-06-28 19:20:58 +00:00
} else {
channel - > device_node = NULL ;
2013-06-05 16:19:44 +00:00
}
2013-06-28 19:20:58 +00:00
drec - > refs - - ;
2013-06-05 16:19:44 +00:00
switch_mutex_unlock ( globals . device_mutex ) ;
2017-01-06 07:10:15 +00:00
2013-06-05 16:19:44 +00:00
}
static void switch_channel_check_device_state ( switch_channel_t * channel , switch_channel_callstate_t callstate )
{
switch_device_record_t * drec = NULL ;
switch_device_state_binding_t * ptr = NULL ;
switch_event_t * event = NULL ;
if ( ! channel - > device_node ) {
return ;
}
drec = channel - > device_node - > parent ;
switch_mutex_lock ( globals . device_mutex ) ;
switch_mutex_lock ( drec - > mutex ) ;
fetch_device_stats ( drec ) ;
2014-05-30 19:30:59 +00:00
if ( drec - > state ! = SDS_HANGUP ) {
if ( drec - > stats . offhook = = 0 | | drec - > stats . hup = = drec - > stats . total ) {
drec - > state = SDS_HANGUP ;
} else {
if ( drec - > stats . active = = 0 ) {
if ( ( drec - > stats . ringing_out + drec - > stats . early_out ) > 0 | | drec - > stats . ring_wait > 0 ) {
drec - > state = SDS_RINGING ;
2013-06-11 00:13:05 +00:00
} else {
2014-05-30 19:30:59 +00:00
if ( drec - > stats . held > 0 ) {
drec - > state = SDS_HELD ;
} else if ( drec - > stats . unheld > 0 ) {
drec - > state = SDS_UNHELD ;
} else {
drec - > state = SDS_DOWN ;
}
2013-06-11 00:13:05 +00:00
}
2014-05-30 19:30:59 +00:00
} else if ( drec - > stats . active = = 1 ) {
drec - > state = SDS_ACTIVE ;
} else {
drec - > state = SDS_ACTIVE_MULTI ;
2013-06-11 00:13:05 +00:00
}
2013-06-05 16:19:44 +00:00
}
}
2013-06-17 15:43:59 +00:00
if ( ( drec - > state = = SDS_DOWN & & drec - > last_state = = SDS_DOWN ) | | ( drec - > state = = SDS_HANGUP & & drec - > last_state = = SDS_HANGUP ) ) {
2013-06-11 16:23:45 +00:00
switch_mutex_unlock ( drec - > mutex ) ;
switch_mutex_unlock ( globals . device_mutex ) ;
return ;
}
2013-10-24 01:45:29 +00:00
if ( ! drec - > call_start ) {
drec - > call_start = switch_micro_time_now ( ) ;
}
2013-06-05 16:19:44 +00:00
switch ( drec - > state ) {
2013-10-24 01:45:29 +00:00
case SDS_RINGING :
2013-10-30 19:08:27 +00:00
if ( ! drec - > ring_start ) {
drec - > ring_start = switch_micro_time_now ( ) ;
drec - > ring_stop = 0 ;
}
2013-10-24 01:45:29 +00:00
break ;
2013-06-05 16:19:44 +00:00
case SDS_ACTIVE :
case SDS_ACTIVE_MULTI :
2013-10-30 19:08:27 +00:00
if ( ! drec - > active_start ) {
2013-06-05 16:19:44 +00:00
drec - > active_start = switch_micro_time_now ( ) ;
2013-10-30 19:08:27 +00:00
drec - > active_stop = 0 ;
2013-06-05 16:19:44 +00:00
}
break ;
2013-10-24 01:45:29 +00:00
case SDS_HELD :
2013-10-30 19:08:27 +00:00
if ( ! drec - > hold_start ) {
drec - > hold_start = switch_micro_time_now ( ) ;
drec - > hold_stop = 0 ;
2013-06-05 16:19:44 +00:00
}
break ;
2013-10-30 19:08:27 +00:00
default :
break ;
}
2014-05-30 19:30:59 +00:00
if ( callstate ! = CCS_UNHELD & & drec - > active_start & & drec - > state ! = SDS_ACTIVE & & drec - > state ! = SDS_ACTIVE_MULTI ) {
2013-10-30 19:08:27 +00:00
drec - > active_stop = switch_micro_time_now ( ) ;
2013-06-05 16:19:44 +00:00
}
2013-10-24 01:45:29 +00:00
if ( drec - > ring_start & & ! drec - > ring_stop & & drec - > state ! = SDS_RINGING ) {
drec - > ring_stop = switch_micro_time_now ( ) ;
}
if ( drec - > hold_start & & ! drec - > hold_stop & & drec - > state ! = SDS_HELD ) {
drec - > hold_stop = switch_micro_time_now ( ) ;
}
2013-06-05 16:19:44 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_DEVICE_STATE ) = = SWITCH_STATUS_SUCCESS ) {
2013-07-19 04:39:12 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Device-ID " , drec - > device_id ) ;
2013-06-05 16:19:44 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Last-Device-State " , switch_channel_device_state2str ( drec - > last_state ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Device-State " , switch_channel_device_state2str ( drec - > state ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Device-Call-State " , switch_channel_callstate2str ( callstate ) ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Total-Legs " , " %u " , drec - > stats . total ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Legs-Offhook " , " %u " , drec - > stats . offhook ) ;
2013-06-12 01:09:02 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Legs-Ringing " , " %u " , drec - > stats . ringing ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Legs-Early " , " %u " , drec - > stats . early ) ;
2013-06-05 16:19:44 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Legs-Active " , " %u " , drec - > stats . active ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Legs-Held " , " %u " , drec - > stats . held ) ;
2014-05-30 19:30:59 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Legs-UnHeld " , " %u " , drec - > stats . unheld ) ;
2013-06-05 16:19:44 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Legs-Hup " , " %u " , drec - > stats . hup ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Talk-Time-Start-Uepoch " , " % " SWITCH_TIME_T_FMT , drec - > active_start ) ;
if ( drec - > active_stop ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Talk-Time-Stop-Uepoch " , " % " SWITCH_TIME_T_FMT , drec - > active_stop ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Device-Talk-Time-Milliseconds " , " %u " , ( uint32_t ) ( drec - > active_stop - drec - > active_start ) / 1000 ) ;
}
}
2017-01-06 07:10:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_DEBUG1 ,
2013-10-24 01:45:29 +00:00
" %s device: %s \n State: %s Dev State: %s/%s Total:%u Offhook:%u "
2017-01-06 07:10:15 +00:00
" Ringing:%u Early:%u Active:%u Held:%u Unheld:%u Hungup:%u Dur: %u Ringtime: %u Holdtime: %u %s \n " ,
2013-06-05 16:19:44 +00:00
switch_channel_get_name ( channel ) ,
drec - > device_id ,
switch_channel_callstate2str ( callstate ) ,
switch_channel_device_state2str ( drec - > last_state ) ,
switch_channel_device_state2str ( drec - > state ) ,
drec - > stats . total ,
drec - > stats . offhook ,
2013-06-11 00:13:05 +00:00
drec - > stats . ringing ,
drec - > stats . early ,
2013-06-05 16:19:44 +00:00
drec - > stats . active ,
drec - > stats . held ,
2014-05-30 19:30:59 +00:00
drec - > stats . unheld ,
2013-06-05 16:19:44 +00:00
drec - > stats . hup ,
drec - > active_stop ? ( uint32_t ) ( drec - > active_stop - drec - > active_start ) / 1000 : 0 ,
2013-10-24 01:45:29 +00:00
drec - > ring_stop ? ( uint32_t ) ( drec - > ring_stop - drec - > ring_start ) / 1000 : 0 ,
drec - > hold_stop ? ( uint32_t ) ( drec - > hold_stop - drec - > hold_start ) / 1000 : 0 ,
2013-06-05 16:19:44 +00:00
switch_channel_test_flag ( channel , CF_FINAL_DEVICE_LEG ) ? " FINAL LEG " : " " ) ;
for ( ptr = globals . device_bindings ; ptr ; ptr = ptr - > next ) {
ptr - > function ( channel - > session , callstate , drec ) ;
}
2013-10-24 01:45:29 +00:00
drec - > last_stats = drec - > stats ;
2013-06-05 16:19:44 +00:00
if ( drec - > active_stop ) {
drec - > active_start = drec - > active_stop = 0 ;
if ( drec - > state = = SDS_ACTIVE | | drec - > state = = SDS_ACTIVE_MULTI ) {
drec - > active_start = switch_micro_time_now ( ) ;
}
}
2013-10-24 01:45:29 +00:00
if ( drec - > hold_stop ) {
drec - > hold_start = drec - > hold_stop = 0 ;
if ( drec - > state = = SDS_HELD ) {
drec - > hold_start = switch_micro_time_now ( ) ;
}
}
if ( drec - > ring_stop ) {
drec - > ring_start = drec - > ring_stop = 0 ;
if ( drec - > state = = SDS_RINGING ) {
drec - > ring_start = switch_micro_time_now ( ) ;
}
}
2013-06-06 18:08:59 +00:00
drec - > last_call_time = switch_micro_time_now ( ) ;
2013-06-05 16:19:44 +00:00
drec - > last_state = drec - > state ;
switch_mutex_unlock ( drec - > mutex ) ;
switch_mutex_unlock ( globals . device_mutex ) ;
2017-01-06 07:10:15 +00:00
2013-06-05 16:19:44 +00:00
if ( event ) {
switch_event_fire ( & event ) ;
}
}
/* assumed to be called under a lock */
static void add_uuid ( switch_device_record_t * drec , switch_channel_t * channel )
{
switch_device_node_t * node ;
switch_assert ( drec ) ;
switch_channel_set_flag ( channel , CF_DEVICE_LEG ) ;
node = switch_core_alloc ( drec - > pool , sizeof ( * node ) ) ;
node - > uuid = switch_core_strdup ( drec - > pool , switch_core_session_get_uuid ( channel - > session ) ) ;
node - > parent = drec ;
2013-06-11 00:13:05 +00:00
node - > callstate = channel - > callstate ;
2013-10-31 20:28:24 +00:00
node - > direction = channel - > logical_direction = = SWITCH_CALL_DIRECTION_INBOUND ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND ;
2013-10-24 01:45:29 +00:00
2013-06-05 16:19:44 +00:00
channel - > device_node = node ;
if ( ! drec - > uuid_list ) {
drec - > uuid_list = node ;
drec - > uuid = node - > uuid ;
} else {
drec - > uuid_tail - > next = node ;
}
drec - > uuid_tail = node ;
drec - > refs + + ;
}
static switch_status_t create_device_record ( switch_device_record_t * * drecp , const char * device_id )
{
switch_device_record_t * drec ;
switch_memory_pool_t * pool ;
switch_assert ( drecp ) ;
switch_core_new_memory_pool ( & pool ) ;
drec = switch_core_alloc ( pool , sizeof ( * drec ) ) ;
drec - > pool = pool ;
drec - > device_id = switch_core_strdup ( drec - > pool , device_id ) ;
switch_mutex_init ( & drec - > mutex , SWITCH_MUTEX_NESTED , drec - > pool ) ;
* drecp = drec ;
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( const char * ) switch_channel_set_device_id ( switch_channel_t * channel , const char * device_id )
{
switch_device_record_t * drec ;
if ( channel - > device_node ) {
return NULL ;
}
channel - > device_id = switch_core_session_strdup ( channel - > session , device_id ) ;
switch_mutex_lock ( globals . device_mutex ) ;
if ( ! ( drec = switch_core_hash_find ( globals . device_hash , channel - > device_id ) ) ) {
create_device_record ( & drec , channel - > device_id ) ;
switch_core_hash_insert ( globals . device_hash , drec - > device_id , drec ) ;
}
add_uuid ( drec , channel ) ;
2017-01-06 07:10:15 +00:00
2013-06-05 16:19:44 +00:00
switch_mutex_unlock ( globals . device_mutex ) ;
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( channel ) , SWITCH_LOG_DEBUG , " Setting DEVICE ID to [%s] \n " , device_id ) ;
2017-01-06 07:10:15 +00:00
2013-06-11 00:13:05 +00:00
switch_channel_check_device_state ( channel , channel - > callstate ) ;
2017-01-06 07:10:15 +00:00
2013-06-05 16:19:44 +00:00
return device_id ;
}
SWITCH_DECLARE ( switch_device_record_t * ) switch_channel_get_device_record ( switch_channel_t * channel )
{
if ( channel - > device_node ) {
switch_mutex_lock ( channel - > device_node - > parent - > mutex ) ;
return channel - > device_node - > parent ;
}
return NULL ;
}
SWITCH_DECLARE ( void ) switch_channel_release_device_record ( switch_device_record_t * * drecp )
{
if ( drecp & & * drecp ) {
switch_mutex_unlock ( ( * drecp ) - > mutex ) ;
* drecp = NULL ;
}
}
SWITCH_DECLARE ( switch_status_t ) switch_channel_bind_device_state_handler ( switch_device_state_function_t function , void * user_data )
{
switch_device_state_binding_t * binding = NULL , * ptr = NULL ;
assert ( function ! = NULL ) ;
if ( ! ( binding = ( switch_device_state_binding_t * ) switch_core_alloc ( globals . pool , sizeof ( * binding ) ) ) ) {
return SWITCH_STATUS_MEMERR ;
}
binding - > function = function ;
binding - > user_data = user_data ;
switch_mutex_lock ( globals . device_mutex ) ;
for ( ptr = globals . device_bindings ; ptr & & ptr - > next ; ptr = ptr - > next ) ;
if ( ptr ) {
ptr - > next = binding ;
} else {
globals . device_bindings = binding ;
}
switch_mutex_unlock ( globals . device_mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( switch_status_t ) switch_channel_unbind_device_state_handler ( switch_device_state_function_t function )
{
switch_device_state_binding_t * ptr , * last = NULL ;
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_mutex_lock ( globals . device_mutex ) ;
for ( ptr = globals . device_bindings ; ptr ; ptr = ptr - > next ) {
if ( ptr - > function = = function ) {
status = SWITCH_STATUS_SUCCESS ;
if ( last ) {
last - > next = ptr - > next ;
} else {
globals . device_bindings = ptr - > next ;
last = NULL ;
continue ;
}
}
last = ptr ;
}
switch_mutex_unlock ( globals . device_mutex ) ;
return status ;
}
2014-09-30 20:28:10 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_channel_pass_sdp ( switch_channel_t * from_channel , switch_channel_t * to_channel , const char * sdp )
{
2014-10-01 18:03:50 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2014-09-30 20:28:10 +00:00
char * use_sdp = ( char * ) sdp ;
char * patched_sdp = NULL ;
if ( ! switch_channel_get_variable ( to_channel , SWITCH_B_SDP_VARIABLE ) ) {
const char * var ;
if ( ( var = switch_channel_get_variable ( from_channel , " bypass_media_sdp_filter " ) ) ) {
2014-10-01 18:03:50 +00:00
if ( ( patched_sdp = switch_core_media_process_sdp_filter ( use_sdp , var , from_channel - > session ) ) ) {
use_sdp = patched_sdp ;
2014-09-30 20:28:10 +00:00
}
2014-10-01 18:03:50 +00:00
}
2014-10-03 15:17:41 +00:00
switch_channel_set_variable ( to_channel , SWITCH_B_SDP_VARIABLE , use_sdp ) ;
2014-09-30 20:28:10 +00:00
}
switch_safe_free ( patched_sdp ) ;
return status ;
}
2013-05-22 16:01:39 +00:00
2006-11-27 22:30:48 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2006-11-27 22:30:48 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2013-06-25 16:50:17 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 noet :
2006-11-27 22:30:48 +00:00
*/