@ -587,6 +587,43 @@ static void send_conf_stasis(struct confbridge_conference *conference, struct as
}
}
static void send_conf_stasis_snapshots ( struct confbridge_conference * conference ,
struct ast_channel_snapshot * chan_snapshot , struct stasis_message_type * type ,
struct ast_json * extras )
{
RAII_VAR ( struct stasis_message * , msg , NULL , ao2_cleanup ) ;
RAII_VAR ( struct ast_json * , json_object , NULL , ast_json_unref ) ;
RAII_VAR ( struct ast_bridge_snapshot * , bridge_snapshot , NULL , ao2_cleanup ) ;
json_object = ast_json_pack ( " {s: s} " ,
" conference " , conference - > name ) ;
if ( ! json_object ) {
return ;
}
if ( extras ) {
ast_json_object_update ( json_object , extras ) ;
}
ast_bridge_lock ( conference - > bridge ) ;
bridge_snapshot = ast_bridge_snapshot_create ( conference - > bridge ) ;
ast_bridge_unlock ( conference - > bridge ) ;
if ( ! bridge_snapshot ) {
return ;
}
msg = ast_bridge_blob_create_from_snapshots ( type ,
bridge_snapshot ,
chan_snapshot ,
json_object ) ;
if ( ! msg ) {
return ;
}
stasis_publish ( ast_bridge_topic ( conference - > bridge ) , msg ) ;
}
static void send_conf_start_event ( struct confbridge_conference * conference )
{
send_conf_stasis ( conference , NULL , confbridge_start_type ( ) , NULL , 0 ) ;
@ -1479,6 +1516,126 @@ static int push_announcer(struct confbridge_conference *conference)
return 0 ;
}
static void confbridge_unlock_and_unref ( void * obj )
{
struct confbridge_conference * conference = obj ;
if ( ! obj ) {
return ;
}
ao2_unlock ( conference ) ;
ao2_ref ( conference , - 1 ) ;
}
void confbridge_handle_atxfer ( struct ast_attended_transfer_message * msg )
{
struct ast_channel_snapshot * old_snapshot ;
struct ast_channel_snapshot * new_snapshot ;
char * confbr_name = NULL ;
char * comma ;
RAII_VAR ( struct confbridge_conference * , conference , NULL , confbridge_unlock_and_unref ) ;
struct confbridge_user * user = NULL ;
int found_user = 0 ;
struct ast_json * json_object ;
if ( msg - > to_transferee . channel_snapshot
& & strcmp ( msg - > to_transferee . channel_snapshot - > dialplan - > appl , " ConfBridge " ) = = 0
& & msg - > target ) {
/* We're transferring a bridge to an extension */
old_snapshot = msg - > to_transferee . channel_snapshot ;
new_snapshot = msg - > target ;
} else if ( msg - > to_transfer_target . channel_snapshot
& & strcmp ( msg - > to_transfer_target . channel_snapshot - > dialplan - > appl , " ConfBridge " ) = = 0
& & msg - > transferee ) {
/* We're transferring a call to a bridge */
old_snapshot = msg - > to_transfer_target . channel_snapshot ;
new_snapshot = msg - > transferee ;
} else {
ast_log ( LOG_ERROR , " Could not determine proper channels \n " ) ;
return ;
}
/*
* old_snapshot - > data should have the original parameters passed to
* the ConfBridge app :
* conference [ , bridge_profile [ , user_profile [ , menu ] ] ]
* We ' ll use " conference " to look up the bridge .
*
* We _could_ use old_snapshot - > bridgeid to get the bridge but
* that would involve locking the conference_bridges container
* and iterating over it looking for a matching bridge .
*/
if ( ast_strlen_zero ( old_snapshot - > dialplan - > data ) ) {
ast_log ( LOG_ERROR , " Channel '%s' didn't have app data set \n " , old_snapshot - > base - > name ) ;
return ;
}
confbr_name = ast_strdupa ( old_snapshot - > dialplan - > data ) ;
comma = strchr ( confbr_name , ' , ' ) ;
if ( comma ) {
* comma = ' \0 ' ;
}
ast_debug ( 1 , " Confbr: %s Leaving: %s Joining: %s \n " , confbr_name , old_snapshot - > base - > name , new_snapshot - > base - > name ) ;
conference = ao2_find ( conference_bridges , confbr_name , OBJ_SEARCH_KEY ) ;
if ( ! conference ) {
ast_log ( LOG_ERROR , " Conference bridge '%s' not found \n " , confbr_name ) ;
return ;
}
ao2_lock ( conference ) ;
/*
* We need to grab the user profile for the departing user in order to
* properly format the join / leave messages .
*/
AST_LIST_TRAVERSE ( & conference - > active_list , user , list ) {
if ( strcasecmp ( ast_channel_name ( user - > chan ) , old_snapshot - > base - > name ) = = 0 ) {
found_user = 1 ;
break ;
}
}
/*
* If we didn ' t find the user in the active list , try the waiting list .
*/
if ( ! found_user & & conference - > waitingusers ) {
AST_LIST_TRAVERSE ( & conference - > waiting_list , user , list ) {
if ( strcasecmp ( ast_channel_name ( user - > chan ) , old_snapshot - > base - > name ) = = 0 ) {
found_user = 1 ;
break ;
}
}
}
if ( ! found_user ) {
ast_log ( LOG_ERROR , " Unable to find user profile for channel '%s' in bridge '%s' \n " ,
old_snapshot - > base - > name , confbr_name ) ;
return ;
}
/*
* We ' re going to use the existing user profile to create the messages .
*/
json_object = ast_json_pack ( " {s: b} " ,
" admin " , ast_test_flag ( & user - > u_profile , USER_OPT_ADMIN )
) ;
if ( ! json_object ) {
return ;
}
send_conf_stasis_snapshots ( conference , old_snapshot , confbridge_leave_type ( ) , json_object ) ;
ast_json_unref ( json_object ) ;
json_object = ast_json_pack ( " {s: b, s: b} " ,
" admin " , ast_test_flag ( & user - > u_profile , USER_OPT_ADMIN ) ,
" muted " , user - > muted ) ;
if ( ! json_object ) {
return ;
}
send_conf_stasis_snapshots ( conference , new_snapshot , confbridge_join_type ( ) , json_object ) ;
ast_json_unref ( json_object ) ;
}
/*!
* \ brief Join a conference bridge
*