<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15927">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_waitforcond: New application<br><br>While several applications exist to wait for<br>a certain event to occur, none allow waiting<br>for any generic expression to become true.<br>This application allows for waiting for a condition<br>to become true, with configurable timeout and<br>checking interval.<br><br>ASTERISK-29444<br><br>Change-Id: I08adf2824b8bc63405778cf355963b5005612f41<br>---<br>A apps/app_waitforcond.c<br>A doc/CHANGES-staging/app_waitforcond.txt<br>2 files changed, 232 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/27/15927/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_waitforcond.c b/apps/app_waitforcond.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b23fca1</span><br><span>--- /dev/null</span><br><span>+++ b/apps/app_waitforcond.c</span><br><span>@@ -0,0 +1,227 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2021, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Naveen Albert <asterisk@phreaknet.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</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%);">+/*! \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Sleep until a condition is true</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \author Naveen Albert <asterisk@phreaknet.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \ingroup applications</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%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+        <support_level>extended</support_level></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%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/logger.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/channel.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/pbx.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** DOCUMENTATION</span><br><span style="color: hsl(120, 100%, 40%);">+      <application name="WaitForCondition" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+              <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                      Wait (sleep) until the given condition is true.</span><br><span style="color: hsl(120, 100%, 40%);">+               </synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+             <syntax></span><br><span style="color: hsl(120, 100%, 40%);">+                        <parameter name="replacementchar" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+                          <para>Specifies the character in the expression used to replace the <literal>$</literal></span><br><span style="color: hsl(120, 100%, 40%);">+                            character. This character should not be used anywhere in the expression itself.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                  </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+                    <parameter name="expression" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+                               <para>A modified logical expression with the <literal>$</literal> characters replaced by</span><br><span style="color: hsl(120, 100%, 40%);">+                            <replaceable>replacementchar</replaceable>. This is necessary to pass the expression itself</span><br><span style="color: hsl(120, 100%, 40%);">+                               into the application, rather than its initial evaluation.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                        </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+                    <parameter name="timeout" /></span><br><span style="color: hsl(120, 100%, 40%);">+                  <parameter name="interval" /></span><br><span style="color: hsl(120, 100%, 40%);">+         </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+               <description></span><br><span style="color: hsl(120, 100%, 40%);">+                   <para>Waits until <replaceable>expression</replaceable> evaluates to true, checking every</span><br><span style="color: hsl(120, 100%, 40%);">+                   <replaceable>interval</replaceable> seconds for up to <replaceable>timeout</replaceable>. Default</span><br><span style="color: hsl(120, 100%, 40%);">+                     is evaluate <replaceable>expression</replaceable> every 50 milliseconds with no timeout.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                     <para>Sets <variable>WAITFORCONDITIONSTATUS</variable> to one of the following values:</para></span><br><span style="color: hsl(120, 100%, 40%);">+                 <variablelist></span><br><span style="color: hsl(120, 100%, 40%);">+                          <variable name="WAITFORCONDITIONSTATUS"></span><br><span style="color: hsl(120, 100%, 40%);">+                                      <value name="TRUE"></span><br><span style="color: hsl(120, 100%, 40%);">+                                           Condition evaluated to true before timeout expired.</span><br><span style="color: hsl(120, 100%, 40%);">+                                   </value></span><br><span style="color: hsl(120, 100%, 40%);">+                                        <value name="FAILURE"></span><br><span style="color: hsl(120, 100%, 40%);">+                                                Invalid argument.</span><br><span style="color: hsl(120, 100%, 40%);">+                                     </value></span><br><span style="color: hsl(120, 100%, 40%);">+                                        <value name="TIMEOUT"></span><br><span style="color: hsl(120, 100%, 40%);">+                                                Timeout elapsed without condition evaluating to true.</span><br><span style="color: hsl(120, 100%, 40%);">+                                 </value></span><br><span style="color: hsl(120, 100%, 40%);">+                                </variable></span><br><span style="color: hsl(120, 100%, 40%);">+                     </variablelist></span><br><span style="color: hsl(120, 100%, 40%);">+         </description></span><br><span style="color: hsl(120, 100%, 40%);">+  </application></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 char *app = "WaitForCondition";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int waitforcond_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int ms, i;</span><br><span style="color: hsl(120, 100%, 40%);">+    double timeout = 0, poll = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int timeout_ms = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   int poll_ms = 50; /* default is evaluate the condition every 50ms */</span><br><span style="color: hsl(120, 100%, 40%);">+  struct timeval start = ast_tvnow();</span><br><span style="color: hsl(120, 100%, 40%);">+   char dollarsignrep = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    int brackets = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     char *tmp, *expression, *optargs = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      char *expr;</span><br><span style="color: hsl(120, 100%, 40%);">+   char condition[512];</span><br><span style="color: hsl(120, 100%, 40%);">+  </span><br><span style="color: hsl(120, 100%, 40%);">+      AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_APP_ARG(timeout);</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_APP_ARG(interval);</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%);">+  tmp = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "Channel already gone\n");</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%);">+   if (ast_strlen_zero(tmp) || tmp[0] == '\0') {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_log(LOG_ERROR, "WaitForCondition requires a condition\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              pbx_builtin_setvar_helper(chan, "WAITFORCONDITIONSTATUS", "FAILURE");</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 style="color: hsl(120, 100%, 40%);">+   if (!strchr(tmp, '[') && !strchr(tmp, ']')) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_log(LOG_ERROR, "No expression detected. Did you forget to replace the $ signs?\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             pbx_builtin_setvar_helper(chan, "WAITFORCONDITIONSTATUS", "FAILURE");</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 style="color: hsl(120, 100%, 40%);">+   dollarsignrep = tmp[0];</span><br><span style="color: hsl(120, 100%, 40%);">+       if (dollarsignrep == '$' || dollarsignrep == '[' || dollarsignrep == ']'</span><br><span style="color: hsl(120, 100%, 40%);">+              || dollarsignrep == '{' || dollarsignrep == '}') {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_ERROR, "Dollar sign replacement cannot be %c.\n", dollarsignrep);</span><br><span style="color: hsl(120, 100%, 40%);">+               pbx_builtin_setvar_helper(chan, "WAITFORCONDITIONSTATUS", "FAILURE");</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%);">+     ++tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (tmp[0] != ',') {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "Invalid separator: %c\n", tmp[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+              pbx_builtin_setvar_helper(chan, "WAITFORCONDITIONSTATUS", "FAILURE");</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%);">+     ++tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (tmp[0] != dollarsignrep) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_log(LOG_ERROR, "Expression start does not match provided replacement: %c\n", tmp[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+           pbx_builtin_setvar_helper(chan, "WAITFORCONDITIONSTATUS", "FAILURE");</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 style="color: hsl(120, 100%, 40%);">+   expression = tmp; /* we're at the start of the expression */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* commas may appear within the expression, so go until we've encountered as many closing brackets as opening */</span><br><span style="color: hsl(120, 100%, 40%);">+  while (++tmp) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (tmp[0] == '\0') {</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_log(LOG_ERROR, "Could not parse end of expression.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 pbx_builtin_setvar_helper(chan, "WAITFORCONDITIONSTATUS", "FAILURE");</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 (tmp[0] == '[') {</span><br><span style="color: hsl(120, 100%, 40%);">+                  brackets++;</span><br><span style="color: hsl(120, 100%, 40%);">+           } else if (tmp[0] == ']') {</span><br><span style="color: hsl(120, 100%, 40%);">+                   brackets--;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (brackets == 0) { /* reached end of expression */</span><br><span style="color: hsl(120, 100%, 40%);">+                  break;</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%);">+     ++tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (tmp[0] != '\0') {</span><br><span style="color: hsl(120, 100%, 40%);">+         ++tmp; /* eat comma separator */</span><br><span style="color: hsl(120, 100%, 40%);">+              if (tmp[0] != '\0') {</span><br><span style="color: hsl(120, 100%, 40%);">+                 optargs = ast_strdupa(tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+                   AST_STANDARD_APP_ARGS(args, optargs);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (!ast_strlen_zero(args.timeout)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         if (sscanf(args.timeout, "%30lg", &timeout) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     ast_log(LOG_WARNING, "Invalid timeout provided: %s. No timeout set.\n", args.timeout);</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%);">+                             timeout_ms = timeout * 1000.0;</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%);">+                   if (!ast_strlen_zero(args.interval)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                if (sscanf(args.interval, "%30lg", &poll) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       ast_log(LOG_WARNING, "Invalid polling interval provided: %s. Default unchanged.\n", args.interval);</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%);">+                             if (poll < 0.001) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        ast_log(LOG_WARNING, "Polling interval cannot be less than 1ms. Default unchanged.\n");</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%);">+                             poll_ms = poll * 1000.0;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; expression[i] != '\0'; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (expression[i] == dollarsignrep) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 expression[i] = '$'; /* replace $s back into expression for variable parsing */</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%);">+   if (timeout_ms > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_debug(1, "Waiting for condition for %f seconds: %s (checking every %d ms)", timeout, expression, poll_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_debug(1, "Waiting for condition, forever: %s (checking every %d ms)", expression, poll_ms);</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%);">+   expr = ast_strdupa(expression); /* no need to re-evaluate each loop iteration */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           const char *cond;</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Substitute variables now */</span><br><span style="color: hsl(120, 100%, 40%);">+                pbx_substitute_variables_helper(chan, expr, condition, sizeof(condition) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                cond = ast_strdupa(condition);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (pbx_checkcondition(cond)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       pbx_builtin_setvar_helper(chan, "WAITFORCONDITIONSTATUS", "TRUE");</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 a timeout was specified, check that it hasn't expired */</span><br><span style="color: hsl(120, 100%, 40%);">+            if ((timeout_ms > 0) && !(ms = ast_remaining_ms(start, timeout_ms))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     pbx_builtin_setvar_helper(chan, "WAITFORCONDITIONSTATUS", "TIMEOUT");</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%);">+             ast_safe_sleep(chan, poll_ms); /* don't waste CPU, we don't need a super tight loop */</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%);">+static int unload_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return ast_unregister_application(app);</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 load_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_register_application_xml(app, waitforcond_exec);</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%);">+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait until condition is true");</span><br><span>diff --git a/doc/CHANGES-staging/app_waitforcond.txt b/doc/CHANGES-staging/app_waitforcond.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..a7ab600</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/app_waitforcond.txt</span><br><span>@@ -0,0 +1,5 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: WaitForCondition application</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This application provides a way to halt</span><br><span style="color: hsl(120, 100%, 40%);">+dialplan execution until a provided</span><br><span style="color: hsl(120, 100%, 40%);">+condition evaluates to true.</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/15927">change 15927</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/+/15927"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I08adf2824b8bc63405778cf355963b5005612f41 </div>
<div style="display:none"> Gerrit-Change-Number: 15927 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>