diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 1c6b4648e2c3e25fd05795f740a1d4ecba1091c7..a4e5c67a8d145709cfb68d6bbd388c67a422adca 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -576,6 +576,10 @@ static void send_conf_stasis(struct confbridge_conference *conference, struct as return; } + if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_ENABLE_EVENTS)) { + conf_send_event_to_participants(conference, chan, msg); + } + if (channel_topic) { stasis_publish(ast_channel_topic(chan), msg); } else { @@ -2311,6 +2315,25 @@ static int join_callback(struct ast_bridge_channel *bridge_channel, void *ignore return 0; } +struct confbridge_hook_data { + struct confbridge_conference *conference; + struct confbridge_user *user; + enum ast_bridge_hook_type hook_type; +}; + +static int send_event_hook_callback(struct ast_bridge_channel *bridge_channel, void *data) +{ + struct confbridge_hook_data *hook_data = data; + + if (hook_data->hook_type == AST_BRIDGE_HOOK_TYPE_JOIN) { + send_join_event(hook_data->user, hook_data->conference); + } else { + send_leave_event(hook_data->user, hook_data->conference); + } + + return 0; +} + /*! \brief The ConfBridge application */ static int confbridge_exec(struct ast_channel *chan, const char *data) { @@ -2328,6 +2351,9 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD, .tech_args.drop_silence = 0, }; + struct confbridge_hook_data *join_hook_data; + struct confbridge_hook_data *leave_hook_data; + AST_DECLARE_APP_ARGS(args, AST_APP_ARG(conf_name); AST_APP_ARG(b_profile_name); @@ -2510,8 +2536,39 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) conf_moh_unsuspend(&user); - /* Join our conference bridge for real */ - send_join_event(&user, conference); + join_hook_data = ast_malloc(sizeof(*join_hook_data)); + if (!join_hook_data) { + res = -1; + goto confbridge_cleanup; + } + join_hook_data->user = &user; + join_hook_data->conference = conference; + join_hook_data->hook_type = AST_BRIDGE_HOOK_TYPE_JOIN; + res = ast_bridge_join_hook(&user.features, send_event_hook_callback, + join_hook_data, ast_free_ptr, 0); + if (res) { + ast_free(join_hook_data); + ast_log(LOG_ERROR, "Couldn't add bridge join hook for channel '%s'\n", ast_channel_name(chan)); + goto confbridge_cleanup; + } + + leave_hook_data = ast_malloc(sizeof(*leave_hook_data)); + if (!leave_hook_data) { + /* join_hook_data is cleaned up by ast_bridge_features_cleanup via the goto */ + res = -1; + goto confbridge_cleanup; + } + leave_hook_data->user = &user; + leave_hook_data->conference = conference; + leave_hook_data->hook_type = AST_BRIDGE_HOOK_TYPE_LEAVE; + res = ast_bridge_leave_hook(&user.features, send_event_hook_callback, + leave_hook_data, ast_free_ptr, 0); + if (res) { + /* join_hook_data is cleaned up by ast_bridge_features_cleanup via the goto */ + ast_free(leave_hook_data); + ast_log(LOG_ERROR, "Couldn't add bridge leave hook for channel '%s'\n", ast_channel_name(chan)); + goto confbridge_cleanup; + } if (ast_bridge_join_hook(&user.features, join_callback, NULL, NULL, 0)) { async_play_sound_ready(user.chan); @@ -2533,8 +2590,6 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP"); } - send_leave_event(&user, conference); - /* if we're shutting down, don't attempt to do further processing */ if (ast_shutting_down()) { /* diff --git a/apps/confbridge/confbridge_manager.c b/apps/confbridge/confbridge_manager.c index 51112ba7854bde2895d7ed5c18c8d540389e1180..a7f2fce0146cee88e399c6f18a85b5f584325b74 100644 --- a/apps/confbridge/confbridge_manager.c +++ b/apps/confbridge/confbridge_manager.c @@ -395,6 +395,9 @@ static void set_media_labels(struct confbridge_conference *conference, struct ast_stream *stream; struct ast_channel *chan = dir == LABEL_DIRECTION_SRC ? dest_chan : src_chan; + if (!chan) { + return; + } topology = ast_channel_get_stream_topology(chan); stream = get_stream(topology, AST_MEDIA_TYPE_VIDEO); if (stream) { @@ -458,8 +461,8 @@ static void send_message(const char *msg_name, char *conf_name, struct ast_json ast_json_free(json); } -static void send_event_to_participants(struct confbridge_conference *conference, - struct ast_channel *chan, struct stasis_message * msg) +void conf_send_event_to_participants(struct confbridge_conference *conference, + struct ast_channel *chan, struct stasis_message *msg) { struct ast_bridge_blob *obj = stasis_message_data(msg); struct ast_json *extras = obj->blob; @@ -597,13 +600,6 @@ static void confbridge_publish_manager_event( struct confbridge_conference *conference = conf_find_bridge(conference_name); channel_text = ast_manager_build_channel_state_string(blob->channel); - - if (conference && ast_test_flag(&conference->b_profile, BRIDGE_OPT_ENABLE_EVENTS)) { - struct ast_channel *chan = ast_channel_get_by_name(blob->channel->name); - - send_event_to_participants(conference, chan, message); - ast_channel_cleanup(chan); - } ao2_cleanup(conference); } diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h index 51ff9a498d7b132ddafefae0ecbc903ffcaa896c..ac403d890ff1357cefdcb84fdf6c259b4cd76ebb 100644 --- a/apps/confbridge/include/confbridge.h +++ b/apps/confbridge/include/confbridge.h @@ -701,6 +701,16 @@ int conf_announce_channel_push(struct ast_channel *ast); */ struct confbridge_conference *conf_find_bridge(const char *conference_name); - +/*! + * \brief Send events to bridge participants. + * \since 15.7 + * \since 16.1 + * + * \param conference The conference bridge + * \param chan The channel triggering the action + * \param msg The stasis message describing the event + */ +void conf_send_event_to_participants(struct confbridge_conference *conference, + struct ast_channel *chan, struct stasis_message *msg); #endif