<p>Kevin Harwell <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/16529">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Kevin Harwell: Looks good to me, but someone else must approve; Approved for Submit
George Joseph: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_queue: Fix hint updates for included contexts<br><br>Previously, if custom hints were used with the hint:<br>format in app_queue, when device state changes occured,<br>app_queue would only do a literal string comparison of<br>the context used for the hint in app_queue and the context<br>of the hint which just changed state. This caused hints<br>to not update and become stale if the context associated<br>with the agent included the context which actually changes<br>state, essentially completely breaking device state for<br>any such agents defined in this manner.<br><br>This fix adds an additional check to ensure that included<br>contexts are also compared against the context which changed<br>state, so that the behavior is correct no matter whether the<br>context is specified to app_queue directly or indirectly.<br><br>ASTERISK-29578 #close<br><br>Change-Id: I8caf2f8da8157ef3d9ea71a8568c1eec95592b78<br>---<br>M apps/app_queue.c<br>1 file changed, 47 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_queue.c b/apps/app_queue.c</span><br><span>index 93adb3f..3c4cdbc 100644</span><br><span>--- a/apps/app_queue.c</span><br><span>+++ b/apps/app_queue.c</span><br><span>@@ -2630,6 +2630,46 @@</span><br><span> return state;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Returns if one context includes another context</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param parent Parent context to search for child</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param child Context to check for inclusion in parent</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function recrusively checks if the context child is included in the context parent.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 1 if child is included in parent, 0 if not</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int context_included(const char *parent, const char *child);</span><br><span style="color: hsl(120, 100%, 40%);">+static int context_included(const char *parent, const char *child)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_context *c = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ c = ast_context_find(parent);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!c) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* well, if parent doesn't exist, how can the child be included in it? */</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%);">+ if (!strcmp(ast_get_context_name(c), parent)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* found the context of the hint app_queue is using. Now, see</span><br><span style="color: hsl(120, 100%, 40%);">+ if that context includes the one that just changed state */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_include *inc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((inc = (struct ast_include*) ast_walk_context_includes(c, inc))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *includename = ast_get_include_name(inc);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcasecmp(child, includename)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* recurse on this context, for nested includes. The</span><br><span style="color: hsl(120, 100%, 40%);">+ PBX extension parser will prevent infinite recursion. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (context_included(includename, child)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</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%);">+ }</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> static int extension_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)</span><br><span> {</span><br><span> struct ao2_iterator miter, qiter;</span><br><span>@@ -2650,9 +2690,14 @@</span><br><span> miter = ao2_iterator_init(q->members, 0);</span><br><span> for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {</span><br><span> if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ found = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcmp(m->state_exten, exten) && context_included(m->state_context, context)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* context could be included in m->state_context. We need to check. */</span><br><span style="color: hsl(120, 100%, 40%);">+ found = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (found) {</span><br><span> update_status(q, m, device_state);</span><br><span> ao2_ref(m, -1);</span><br><span style="color: hsl(0, 100%, 40%);">- found = 1;</span><br><span> break;</span><br><span> }</span><br><span> }</span><br><span>@@ -2663,7 +2708,7 @@</span><br><span> }</span><br><span> ao2_iterator_destroy(&qiter);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (found) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (found) {</span><br><span> ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));</span><br><span> } else {</span><br><span> ast_debug(3, "Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",</span><br><span></span><br></pre><div style="white-space:pre-wrap"></div><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/16529">change 16529</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/c/asterisk/+/16529"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 19 </div>
<div style="display:none"> Gerrit-Change-Id: I8caf2f8da8157ef3d9ea71a8568c1eec95592b78 </div>
<div style="display:none"> Gerrit-Change-Number: 16529 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>