<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18566">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">func_query: Add function to retrieve remote text data.<br><br>Adds the TEXT_QUERY function, which makes it easy for<br>users to be able to remotely query data available on<br>remote systems.<br><br>For example, the result of functions like DEVICE_STATE<br>can be made easily available to other systems through<br>this function, which presents such data as easily as if<br>it were available locally. As it is tech-agnostic, behind<br>the scenes, a call is initiated to the specified endpoint,<br>and then the buffer is filled with the results of the<br>data transfer.<br><br>Data transfer remains done using SendText; this function<br>merely makes it seamless to use such data from other systems.<br><br>ASTERISK-30066<br><br>Change-Id: I51cdfe2db398db15a67d7e2068cd95c6710ee33c<br>---<br>A doc/CHANGES-staging/func_query.txt<br>A funcs/func_query.c<br>2 files changed, 188 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/66/18566/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/func_query.txt b/doc/CHANGES-staging/func_query.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..e89ff04</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/func_query.txt</span><br><span>@@ -0,0 +1,6 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: func_query</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Adds the TEXT_QUERY function, which can be used to</span><br><span style="color: hsl(120, 100%, 40%);">+retrieve textual data from a remote endpoint in a</span><br><span style="color: hsl(120, 100%, 40%);">+technology-agnostic way. This makes it easy to</span><br><span style="color: hsl(120, 100%, 40%);">+query functions available on remote Asterisk systems.</span><br><span>diff --git a/funcs/func_query.c b/funcs/func_query.c</span><br><span>new file mode 100644</span><br><span>index 0000000..c055218</span><br><span>--- /dev/null</span><br><span>+++ b/funcs/func_query.c</span><br><span>@@ -0,0 +1,182 @@</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) 2022, Naveen Albert</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 Remote text querying</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 functions</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/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/pbx.h"    /* function register/unregister */</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/format_cache.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/frame.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/strings.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/conversions.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%);">+       <function name="TEXT_QUERY" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+               <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                      Remote string querying</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="dialstr" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+                          <para>Dial string, such as provided to the Dial application</para></span><br><span style="color: hsl(120, 100%, 40%);">+                        </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+                    <parameter name="timeout" required="false"></span><br><span style="color: hsl(120, 100%, 40%);">+                         <para>Timeout to wait, in seconds. Default is 5 seconds.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                   </parameter></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>Initiate a call and receive a text data transfer.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                    <para>This function can be used to implement simple remote procedure</span><br><span style="color: hsl(120, 100%, 40%);">+                    calls between endpoints that support text frames. For example, you</span><br><span style="color: hsl(120, 100%, 40%);">+                    can use this to retrieve the results of certain dialplan functions</span><br><span style="color: hsl(120, 100%, 40%);">+                    on a different node as easily as if they were local.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                     <para>The other end should use SendText to send the data transfer.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                 <example title="Query device state of endpoints at the main branch office"></span><br><span style="color: hsl(120, 100%, 40%);">+                   [rx-node] ; Node A</span><br><span style="color: hsl(120, 100%, 40%);">+                    exten => rx,1,Set(remotestate=${QUERY(IAX2/mainbranch/2368@device-state-context)})</span><br><span style="color: hsl(120, 100%, 40%);">+                         same => n,ExecIf($[ "${remotestate}" = "NOT_INUSE" ]?Dial(IAX2/mainbranch/2368@extensions))</span><br><span style="color: hsl(120, 100%, 40%);">+                            same => n,Hangup()</span><br><span style="color: hsl(120, 100%, 40%);">+                 [extensions] ; Node B: allow other Asterisk systems to query local device states.</span><br><span style="color: hsl(120, 100%, 40%);">+                     exten => _2XXX,1,Dial(${HINT(${EXTEN})})</span><br><span style="color: hsl(120, 100%, 40%);">+                           same => n,Hangup()</span><br><span style="color: hsl(120, 100%, 40%);">+                 [device-state-context] ; Node B</span><br><span style="color: hsl(120, 100%, 40%);">+                       exten => _2XXX,1,SendText(${DEVICE_STATE(${HINT(${EXTEN})})})</span><br><span style="color: hsl(120, 100%, 40%);">+                              same => n,Hangup()</span><br><span style="color: hsl(120, 100%, 40%);">+                 </example></span><br><span style="color: hsl(120, 100%, 40%);">+              </description></span><br><span style="color: hsl(120, 100%, 40%);">+  </function></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 acf_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_format_cap *cap;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_channel *c;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *parse, *rbuf;</span><br><span style="color: hsl(120, 100%, 40%);">+   char *tech, *destination;</span><br><span style="color: hsl(120, 100%, 40%);">+     int timeout_sec = 0, timeout_ms = 5000;</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(dialstr);</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_APP_ARG(timeout);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_custom_function *cdr_prop_func = ast_custom_function_find("CDR_PROP");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_WARNING, "Missing arguments: dialstring\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%);">+     if (!chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);</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%);">+   parse = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_STANDARD_APP_ARGS(args, parse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(args.dialstr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_WARNING, "Missing arguments: dialstring\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%);">+     if (!ast_strlen_zero(args.timeout)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if ((ast_str_to_int(args.timeout, &timeout_sec) || timeout_sec < 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_log(LOG_WARNING, "Invalid timeout: %s\n", args.timeout);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      timeout_ms *= 1000;</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%);">+   tech = args.dialstr;</span><br><span style="color: hsl(120, 100%, 40%);">+  destination = strchr(tech, '/');</span><br><span style="color: hsl(120, 100%, 40%);">+      if (destination) {</span><br><span style="color: hsl(120, 100%, 40%);">+            *destination = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+          destination++;</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_WARNING, "Dial string must have technology/resource\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%);">+   cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!cap) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_format_cap_append(cap, ast_format_slin, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     c = ast_request(tech, cap, NULL, chan, destination, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    ao2_cleanup(cap);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!c) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</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_channel_unlock(c);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Disable CDR for this temporary channel. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cdr_prop_func) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_func_write(c, "CDR_PROP(disable)", "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_call(c, destination, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_ERROR, "Unable to place outbound call to %s\n", args.dialstr);</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_hangup(c);</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%);">+   /* Wait for data transfer */</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_autoservice_start(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_channel_ref(c);</span><br><span style="color: hsl(120, 100%, 40%);">+   rbuf = ast_recvtext(c, timeout_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_channel_unref(c);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_autoservice_stop(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!rbuf) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_WARNING, "No data received before channel hung up\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%);">+   ast_copy_string(buf, rbuf, sizeof(buf));</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 style="color: hsl(120, 100%, 40%);">+static struct ast_custom_function query_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+  .name = "TEXT_QUERY",</span><br><span style="color: hsl(120, 100%, 40%);">+       .read = acf_query_read,</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_custom_function_unregister(&query_function);</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_custom_function_register(&query_function);</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_EXTENDED(ASTERISK_GPL_KEY, "Remote text querying");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18566">change 18566</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/+/18566"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I51cdfe2db398db15a67d7e2068cd95c6710ee33c </div>
<div style="display:none"> Gerrit-Change-Number: 18566 </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>