@ -5389,11 +5389,47 @@ static void handle_cause(int cause, int *outstate)
}
}
/*!
* \ internal
* \ brief Helper function to inherit info from parent channel .
*
* \ param new_chan Channel inheriting information .
* \ param parent Channel new_chan inherits information .
* \ param orig Channel being replaced by the call forward channel .
*
* \ return Nothing
*/
static void call_forward_inherit ( struct ast_channel * new_chan , struct ast_channel * parent , struct ast_channel * orig )
{
if ( ! ast_test_flag ( parent , AST_FLAG_ZOMBIE ) & & ! ast_check_hangup ( parent ) ) {
struct ast_party_redirecting redirecting ;
/*
* The parent is not a ZOMBIE or hungup so update it with the
* original channel ' s redirecting information .
*/
ast_party_redirecting_init ( & redirecting ) ;
ast_channel_lock ( orig ) ;
ast_party_redirecting_copy ( & redirecting , & orig - > redirecting ) ;
ast_channel_unlock ( orig ) ;
if ( ast_channel_redirecting_macro ( orig , parent , & redirecting , 1 , 0 ) ) {
ast_channel_update_redirecting ( parent , & redirecting , NULL ) ;
}
ast_party_redirecting_free ( & redirecting ) ;
}
/* Safely inherit variables and datastores from the parent channel. */
ast_channel_lock_both ( parent , new_chan ) ;
ast_channel_inherit_variables ( parent , new_chan ) ;
ast_channel_datastore_inherit ( parent , new_chan ) ;
ast_channel_unlock ( new_chan ) ;
ast_channel_unlock ( parent ) ;
}
struct ast_channel * ast_call_forward ( struct ast_channel * caller , struct ast_channel * orig , int * timeout , struct ast_format_cap * cap , struct outgoing_helper * oh , int * outstate )
{
char tmpchan [ 256 ] ;
struct ast_channel * new = NULL ;
struct ast_party_redirecting * apr = & orig - > redirecting ;
struct ast_channel * new_chan = NULL ;
char * data , * type ;
int cause = 0 ;
int res ;
@ -5412,64 +5448,52 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
data = tmpchan ;
type = " Local " ;
}
if ( ! ( new = ast_request ( type , cap , orig , data , & cause ) ) ) {
if ( ! ( new _chan = ast_request ( type , cap , orig , data , & cause ) ) ) {
ast_log ( LOG_NOTICE , " Unable to create channel for call forward to '%s/%s' (cause = %d) \n " , type , data , cause ) ;
handle_cause ( cause , outstate ) ;
ast_hangup ( orig ) ;
return NULL ;
}
ast_channel_set_redirecting ( new , apr , NULL ) ;
/* Copy/inherit important information into new channel */
if ( oh ) {
if ( oh - > vars ) {
ast_set_variables ( new , oh - > vars ) ;
}
if ( ! ast_strlen_zero ( oh - > cid_num ) & & ! ast_strlen_zero ( oh - > cid_name ) ) {
ast_set_callerid ( new , oh - > cid_num , oh - > cid_name , oh - > cid_num ) ;
ast_set_variables ( new_chan , oh - > vars ) ;
}
if ( oh - > parent_channel ) {
ast_channel_update_redirecting ( oh - > parent_channel , apr , NULL ) ;
ast_channel_inherit_variables ( oh - > parent_channel , new ) ;
ast_channel_datastore_inherit ( oh - > parent_channel , new ) ;
call_forward_inherit ( new_chan , oh - > parent_channel , orig ) ;
}
if ( oh - > account ) {
ast_channel_lock ( new ) ;
ast_cdr_setaccount ( new , oh - > account ) ;
ast_channel_unlock ( new ) ;
ast_channel_lock ( new _chan ) ;
ast_cdr_setaccount ( new _chan , oh - > account ) ;
ast_channel_unlock ( new _chan ) ;
}
} else if ( caller ) { /* no outgoing helper so use caller if avaliable */
ast_channel_update_redirecting ( caller , apr , NULL ) ;
ast_channel_inherit_variables ( caller , new ) ;
ast_channel_datastore_inherit ( caller , new ) ;
call_forward_inherit ( new_chan , caller , orig ) ;
}
ast_channel_lock ( orig ) ;
while ( ast_channel_trylock ( new ) ) {
CHANNEL_DEADLOCK_AVOIDANCE ( orig ) ;
}
ast_copy_flags ( new - > cdr , orig - > cdr , AST_CDR_FLAG_ORIGINATED ) ;
ast_string_field_set ( new , accountcode , orig - > accountcode ) ;
ast_party_caller_copy ( & new - > caller , & orig - > caller ) ;
ast_party_connected_line_copy ( & new - > connected , & orig - > connected ) ;
ast_channel_unlock ( new ) ;
ast_channel_lock_both ( orig , new_chan ) ;
ast_copy_flags ( new_chan - > cdr , orig - > cdr , AST_CDR_FLAG_ORIGINATED ) ;
ast_string_field_set ( new_chan , accountcode , orig - > accountcode ) ;
ast_party_connected_line_copy ( & new_chan - > connected , & orig - > connected ) ;
ast_party_redirecting_copy ( & new_chan - > redirecting , & orig - > redirecting ) ;
ast_channel_unlock ( new_chan ) ;
ast_channel_unlock ( orig ) ;
/* call new channel */
res = ast_call ( new , data , 0 ) ;
res = ast_call ( new _chan , data , 0 ) ;
if ( timeout ) {
* timeout = res ;
}
if ( res ) {
ast_log ( LOG_NOTICE , " Unable to call forward to channel %s/%s \n " , type , ( char * ) data ) ;
ast_hangup ( orig ) ;
ast_hangup ( new ) ;
ast_hangup ( new _chan ) ;
return NULL ;
}
ast_hangup ( orig ) ;
return new ;
return new _chan ;
}
struct ast_channel * __ast_request_and_dial ( const char * type , struct ast_format_cap * cap , const struct ast_channel * requestor , void * data , int timeout , int * outstate , const char * cid_num , const char * cid_name , struct outgoing_helper * oh )
@ -5494,14 +5518,24 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
}
if ( oh ) {
if ( oh - > vars )
if ( oh - > vars ) {
ast_set_variables ( chan , oh - > vars ) ;
/* XXX why is this necessary, for the parent_channel perhaps ? */
if ( ! ast_strlen_zero ( oh - > cid_num ) & & ! ast_strlen_zero ( oh - > cid_name ) )
ast_set_callerid ( chan , oh - > cid_num , oh - > cid_name , oh - > cid_num ) ;
}
if ( ! ast_strlen_zero ( oh - > cid_num ) & & ! ast_strlen_zero ( oh - > cid_name ) ) {
/*
* Use the oh values instead of the function parameters for the
* outgoing CallerID .
*/
cid_num = oh - > cid_num ;
cid_name = oh - > cid_name ;
}
if ( oh - > parent_channel ) {
/* Safely inherit variables and datastores from the parent channel. */
ast_channel_lock_both ( oh - > parent_channel , chan ) ;
ast_channel_inherit_variables ( oh - > parent_channel , chan ) ;
ast_channel_datastore_inherit ( oh - > parent_channel , chan ) ;
ast_channel_unlock ( oh - > parent_channel ) ;
ast_channel_unlock ( chan ) ;
}
if ( oh - > account ) {
ast_channel_lock ( chan ) ;
@ -5510,7 +5544,6 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
}
}
ast_set_callerid ( chan , cid_num , cid_name , cid_num ) ;
ast_set_flag ( chan - > cdr , AST_CDR_FLAG_ORIGINATED ) ;
ast_party_connected_line_set_init ( & connected , & chan - > connected ) ;
if ( cid_num ) {