@ -3491,13 +3491,17 @@ static int action_bridge(struct mansession *s, const struct message *m)
struct ast_bridge_thread_obj * tobj = NULL ;
struct ast_bridge_thread_obj * tobj = NULL ;
/* make sure valid channels were specified */
/* make sure valid channels were specified */
if ( ! ast_strlen_zero ( channela ) & & ! ast_strlen_zero ( channelb ) ) {
if ( ast_strlen_zero ( channela ) | | ast_strlen_zero ( channelb ) ) {
astman_send_error ( s , m , " Missing channel parameter in request " ) ;
return 0 ;
}
/* The same code must be executed for chana and chanb. To avoid a
* theoretical deadlock , this code is separated so both chana and chanb will
* not hold locks at the same time . */
/* Start with chana */
chana = ast_get_channel_by_name_prefix_locked ( channela , strlen ( channela ) ) ;
chana = ast_get_channel_by_name_prefix_locked ( channela , strlen ( channela ) ) ;
chanb = ast_get_channel_by_name_prefix_locked ( channelb , strlen ( channelb ) ) ;
if ( chana )
ast_channel_unlock ( chana ) ;
if ( chanb )
ast_channel_unlock ( chanb ) ;
/* send errors if any of the channels could not be found/locked */
/* send errors if any of the channels could not be found/locked */
if ( ! chana ) {
if ( ! chana ) {
@ -3506,39 +3510,49 @@ static int action_bridge(struct mansession *s, const struct message *m)
astman_send_error ( s , m , buf ) ;
astman_send_error ( s , m , buf ) ;
return 0 ;
return 0 ;
}
}
if ( ! chanb ) {
char buf [ 256 ] ;
snprintf ( buf , sizeof ( buf ) , " Channel2 does not exists: %s " , channelb ) ;
astman_send_error ( s , m , buf ) ;
return 0 ;
}
} else {
astman_send_error ( s , m , " Missing channel parameter in request " ) ;
return 0 ;
}
/* Answer the channels if needed */
/* Answer the channels if needed */
if ( chana - > _state ! = AST_STATE_UP )
if ( chana - > _state ! = AST_STATE_UP )
ast_answer ( chana ) ;
ast_answer ( chana ) ;
if ( chanb - > _state ! = AST_STATE_UP )
ast_answer ( chanb ) ;
/* create the placeholder channels and grab the other channels */
/* create the placeholder channels and grab the other channels */
if ( ! ( tmpchana = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL ,
if ( ! ( tmpchana = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL ,
NULL , NULL , 0 , " Bridge/%s " , chana - > name ) ) ) {
NULL , NULL , 0 , " Bridge/%s " , chana - > name ) ) ) {
astman_send_error ( s , m , " Unable to create temporary channel! " ) ;
astman_send_error ( s , m , " Unable to create temporary channel! " ) ;
ast_channel_unlock ( chana ) ;
return 1 ;
return 1 ;
}
}
do_bridge_masquerade ( chana , tmpchana ) ;
ast_channel_unlock ( chana ) ;
chana = NULL ;
/* now do chanb */
chanb = ast_get_channel_by_name_prefix_locked ( channelb , strlen ( channelb ) ) ;
/* send errors if any of the channels could not be found/locked */
if ( ! chanb ) {
char buf [ 256 ] ;
snprintf ( buf , sizeof ( buf ) , " Channel2 does not exists: %s " , channelb ) ;
ast_hangup ( tmpchana ) ;
astman_send_error ( s , m , buf ) ;
return 0 ;
}
/* Answer the channels if needed */
if ( chanb - > _state ! = AST_STATE_UP )
ast_answer ( chanb ) ;
/* create the placeholder channels and grab the other channels */
if ( ! ( tmpchanb = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL ,
if ( ! ( tmpchanb = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL ,
NULL , NULL , 0 , " Bridge/%s " , chanb - > name ) ) ) {
NULL , NULL , 0 , " Bridge/%s " , chanb - > name ) ) ) {
astman_send_error ( s , m , " Unable to create temporary channels! " ) ;
astman_send_error ( s , m , " Unable to create temporary channels! " ) ;
ast_channel_free ( tmpchana ) ;
ast_hangup ( tmpchana ) ;
ast_channel_unlock ( chanb ) ;
return 1 ;
return 1 ;
}
}
do_bridge_masquerade ( chana , tmpchana ) ;
do_bridge_masquerade ( chanb , tmpchanb ) ;
do_bridge_masquerade ( chanb , tmpchanb ) ;
ast_channel_unlock ( chanb ) ;
chanb = NULL ;
/* make the channels compatible, send error if we fail doing so */
/* make the channels compatible, send error if we fail doing so */
if ( ast_channel_make_compatible ( tmpchana , tmpchanb ) ) {
if ( ast_channel_make_compatible ( tmpchana , tmpchanb ) ) {
@ -3877,7 +3891,6 @@ static int bridge_exec(struct ast_channel *chan, void *data)
pbx_builtin_setvar_helper ( chan , " BRIDGERESULT " , " NONEXISTENT " ) ;
pbx_builtin_setvar_helper ( chan , " BRIDGERESULT " , " NONEXISTENT " ) ;
return 0 ;
return 0 ;
}
}
ast_channel_unlock ( current_dest_chan ) ;
/* answer the channel if needed */
/* answer the channel if needed */
if ( current_dest_chan - > _state ! = AST_STATE_UP )
if ( current_dest_chan - > _state ! = AST_STATE_UP )
@ -3895,6 +3908,8 @@ static int bridge_exec(struct ast_channel *chan, void *data)
}
}
do_bridge_masquerade ( current_dest_chan , final_dest_chan ) ;
do_bridge_masquerade ( current_dest_chan , final_dest_chan ) ;
ast_channel_unlock ( current_dest_chan ) ;
/* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
/* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
/* try to make compatible, send error if we fail */
/* try to make compatible, send error if we fail */
if ( ast_channel_make_compatible ( chan , final_dest_chan ) < 0 ) {
if ( ast_channel_make_compatible ( chan , final_dest_chan ) < 0 ) {