<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/10311">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_confbridge:  Use bridge join hook to send join and leave events<br><br>The first attempt at publishing confbridge events to participants<br>involved publishing them at the same time stasis events were<br>created.  This caused issues with bridge and channel locks.  The<br>second attempt involved publishing them when the stasis events<br>were received by the code that published the confbridge AMI events.<br>This caused timing issues because, depending on resources available,<br>the event could be received before channels actually joined the<br>bridge and would therefore fail to send messages to the participant.<br><br>This attempt reverts to the original mechanism with one exception.<br>The join and leave events are published via bridge join and leave<br>hooks.  This guarantees the states of the channels and bridge and<br>provides deterministic timing for event publishing.<br><br>Change-Id: I2660074f8a30a5224cb953d5e047ee84484a9036<br>---<br>M apps/app_confbridge.c<br>M apps/confbridge/confbridge_manager.c<br>M apps/confbridge/include/confbridge.h<br>3 files changed, 75 insertions(+), 14 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/11/10311/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c</span><br><span>index 1c6b464..02ce391 100644</span><br><span>--- a/apps/app_confbridge.c</span><br><span>+++ b/apps/app_confbridge.c</span><br><span>@@ -576,6 +576,10 @@</span><br><span>          return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_ENABLE_EVENTS)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         conf_send_event_to_participants(conference, chan, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (channel_topic) {</span><br><span>                 stasis_publish(ast_channel_topic(chan), msg);</span><br><span>        } else {</span><br><span>@@ -2311,6 +2315,25 @@</span><br><span>    return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct confbridge_hook_data {</span><br><span style="color: hsl(120, 100%, 40%);">+     struct confbridge_conference *conference;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct confbridge_user *user;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_bridge_hook_type hook_type;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int send_event_hook_callback(struct ast_bridge_channel *bridge_channel, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct confbridge_hook_data *hook_data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (hook_data->hook_type == AST_BRIDGE_HOOK_TYPE_JOIN) {</span><br><span style="color: hsl(120, 100%, 40%);">+           send_join_event(hook_data->user, hook_data->conference);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              send_leave_event(hook_data->user, hook_data->conference);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief The ConfBridge application */</span><br><span> static int confbridge_exec(struct ast_channel *chan, const char *data)</span><br><span> {</span><br><span>@@ -2328,6 +2351,9 @@</span><br><span>            .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,</span><br><span>            .tech_args.drop_silence = 0,</span><br><span>         };</span><br><span style="color: hsl(120, 100%, 40%);">+    struct confbridge_hook_data *join_hook_data;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct confbridge_hook_data *leave_hook_data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      AST_DECLARE_APP_ARGS(args,</span><br><span>           AST_APP_ARG(conf_name);</span><br><span>              AST_APP_ARG(b_profile_name);</span><br><span>@@ -2510,8 +2536,39 @@</span><br><span> </span><br><span>    conf_moh_unsuspend(&user);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      /* Join our conference bridge for real */</span><br><span style="color: hsl(0, 100%, 40%);">-       send_join_event(&user, conference);</span><br><span style="color: hsl(120, 100%, 40%);">+       join_hook_data = ast_malloc(sizeof(*join_hook_data));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!join_hook_data) {</span><br><span style="color: hsl(120, 100%, 40%);">+                res = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+             goto confbridge_cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     join_hook_data->user = &user;</span><br><span style="color: hsl(120, 100%, 40%);">+  join_hook_data->conference = conference;</span><br><span style="color: hsl(120, 100%, 40%);">+   join_hook_data->hook_type = AST_BRIDGE_HOOK_TYPE_JOIN;</span><br><span style="color: hsl(120, 100%, 40%);">+     res = ast_bridge_join_hook(&user.features, send_event_hook_callback,</span><br><span style="color: hsl(120, 100%, 40%);">+              join_hook_data, ast_free_ptr, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_free(join_hook_data);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_ERROR, "Couldn't add bridge join hook for channel '%s'\n", ast_channel_name(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+         goto confbridge_cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   leave_hook_data = ast_malloc(sizeof(*leave_hook_data));</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!leave_hook_data) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* join_hook_data is cleaned up by ast_bridge_features_cleanup via the goto */</span><br><span style="color: hsl(120, 100%, 40%);">+                res = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+             goto confbridge_cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     leave_hook_data->user = &user;</span><br><span style="color: hsl(120, 100%, 40%);">+ leave_hook_data->conference = conference;</span><br><span style="color: hsl(120, 100%, 40%);">+  leave_hook_data->hook_type = AST_BRIDGE_HOOK_TYPE_LEAVE;</span><br><span style="color: hsl(120, 100%, 40%);">+   res = ast_bridge_leave_hook(&user.features, send_event_hook_callback,</span><br><span style="color: hsl(120, 100%, 40%);">+             leave_hook_data, ast_free_ptr, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+     if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* join_hook_data is cleaned up by ast_bridge_features_cleanup via the goto */</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_free(leave_hook_data);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_ERROR, "Couldn't add bridge leave hook for channel '%s'\n", ast_channel_name(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+                goto confbridge_cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span> </span><br><span>        if (ast_bridge_join_hook(&user.features, join_callback, NULL, NULL, 0)) {</span><br><span>                async_play_sound_ready(user.chan);</span><br><span>@@ -2533,8 +2590,6 @@</span><br><span>           pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP");</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   send_leave_event(&user, conference);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>     /* if we're shutting down, don't attempt to do further processing */</span><br><span>         if (ast_shutting_down()) {</span><br><span>           /*</span><br><span>diff --git a/apps/confbridge/confbridge_manager.c b/apps/confbridge/confbridge_manager.c</span><br><span>index 51112ba..a7f2fce 100644</span><br><span>--- a/apps/confbridge/confbridge_manager.c</span><br><span>+++ b/apps/confbridge/confbridge_manager.c</span><br><span>@@ -395,6 +395,9 @@</span><br><span>        struct ast_stream *stream;</span><br><span>   struct ast_channel *chan = dir == LABEL_DIRECTION_SRC ? dest_chan : src_chan;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+     if (!chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span>    topology = ast_channel_get_stream_topology(chan);</span><br><span>    stream = get_stream(topology, AST_MEDIA_TYPE_VIDEO);</span><br><span>         if (stream) {</span><br><span>@@ -458,8 +461,8 @@</span><br><span>  ast_json_free(json);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void send_event_to_participants(struct confbridge_conference *conference,</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_channel *chan, struct stasis_message * msg)</span><br><span style="color: hsl(120, 100%, 40%);">+void conf_send_event_to_participants(struct confbridge_conference *conference,</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_channel *chan, struct stasis_message *msg)</span><br><span> {</span><br><span>   struct ast_bridge_blob *obj = stasis_message_data(msg);</span><br><span>      struct ast_json *extras = obj->blob;</span><br><span>@@ -597,13 +600,6 @@</span><br><span>               struct confbridge_conference *conference = conf_find_bridge(conference_name);</span><br><span> </span><br><span>            channel_text = ast_manager_build_channel_state_string(blob->channel);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                if (conference && ast_test_flag(&conference->b_profile, BRIDGE_OPT_ENABLE_EVENTS)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     struct ast_channel *chan = ast_channel_get_by_name(blob->channel->name);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                  send_event_to_participants(conference, chan, message);</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_channel_cleanup(chan);</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span>            ao2_cleanup(conference);</span><br><span>     }</span><br><span> </span><br><span>diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h</span><br><span>index 51ff9a4..ac403d8 100644</span><br><span>--- a/apps/confbridge/include/confbridge.h</span><br><span>+++ b/apps/confbridge/include/confbridge.h</span><br><span>@@ -701,6 +701,16 @@</span><br><span>  */</span><br><span> struct confbridge_conference *conf_find_bridge(const char *conference_name);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Send events to bridge participants.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 15.7</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.1</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param conference The conference bridge</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan The channel triggering the action</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param msg The stasis message describing the event</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void conf_send_event_to_participants(struct confbridge_conference *conference,</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_channel *chan, struct stasis_message *msg);</span><br><span> </span><br><span> #endif</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10311">change 10311</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10311"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I2660074f8a30a5224cb953d5e047ee84484a9036 </div>
<div style="display:none"> Gerrit-Change-Number: 10311 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>