<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18068">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_geolocation:  Initial commit<br><br>This is the first commit for res_geolocation.  It is in no way<br>complete but what is here is functional.<br><br>Change-Id: Ieb6e3640f31a676da42d8c144ebbb31ad795d849<br>---<br>A include/asterisk/res_geolocation.h<br>M include/asterisk/res_pjsip.h<br>M res/Makefile<br>A res/res_geolocation.c<br>A res/res_geolocation.exports.in<br>A res/res_geolocation/geoloc_channel.c<br>A res/res_geolocation/geoloc_civicaddr.c<br>A res/res_geolocation/geoloc_config.c<br>A res/res_geolocation/geoloc_dialplan.c<br>A res/res_geolocation/geoloc_doc.xml<br>A res/res_geolocation/geoloc_gml.c<br>A res/res_geolocation/geoloc_private.h<br>12 files changed, 1,720 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/68/18068/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/res_geolocation.h b/include/asterisk/res_geolocation.h</span><br><span>new file mode 100644</span><br><span>index 0000000..d0efe4d</span><br><span>--- /dev/null</span><br><span>+++ b/include/asterisk/res_geolocation.h</span><br><span>@@ -0,0 +1,148 @@</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, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></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%);">+#ifndef INCLUDE_ASTERISK_RES_GEOLOCATION_H_</span><br><span style="color: hsl(120, 100%, 40%);">+#define INCLUDE_ASTERISK_RES_GEOLOCATION_H_</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/sorcery.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum geoloc_pidf_section {</span><br><span style="color: hsl(120, 100%, 40%);">+   PIDF_SECTION_NONE = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+        PIDF_SECTION_TUPLE,</span><br><span style="color: hsl(120, 100%, 40%);">+   PIDF_SECTION_DEVICE,</span><br><span style="color: hsl(120, 100%, 40%);">+  PIDF_SECTION_PERSON</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%);">+enum geoloc_format {</span><br><span style="color: hsl(120, 100%, 40%);">+       GEOLOC_FORMAT_NONE = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+       GEOLOC_FORMAT_CIVIC_ADDRESS,</span><br><span style="color: hsl(120, 100%, 40%);">+  GEOLOC_FORMAT_GML,</span><br><span style="color: hsl(120, 100%, 40%);">+    GEOLOC_FORMAT_URI,</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%);">+enum geoloc_location_disposition {</span><br><span style="color: hsl(120, 100%, 40%);">+  GEOLOC_LOC_DISP_DISCARD = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  GEOLOC_LOC_DISP_APPEND,</span><br><span style="color: hsl(120, 100%, 40%);">+       GEOLOC_LOC_DISP_PREPEND,</span><br><span style="color: hsl(120, 100%, 40%);">+      GEOLOC_LOC_DISP_REPLACE,</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%);">+struct ast_geoloc_location {</span><br><span style="color: hsl(120, 100%, 40%);">+  SORCERY_OBJECT(details);</span><br><span style="color: hsl(120, 100%, 40%);">+      enum geoloc_format format;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_variable *location_vars;</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%);">+struct ast_geoloc_profile {</span><br><span style="color: hsl(120, 100%, 40%);">+        SORCERY_OBJECT(details);</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_STRING_FIELD(location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+    enum geoloc_pidf_section pidf_section;</span><br><span style="color: hsl(120, 100%, 40%);">+        enum geoloc_location_disposition location_disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+        int geolocation_routing;</span><br><span style="color: hsl(120, 100%, 40%);">+      int send_location;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_variable *location_refinement;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_variable *location_variables;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_variable *usage_rules_vars;</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%);">+struct ast_geoloc_effective_profile {</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_STRING_FIELD(id);</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_STRING_FIELD(location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+    enum geoloc_pidf_section pidf_section;</span><br><span style="color: hsl(120, 100%, 40%);">+        enum geoloc_location_disposition location_disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+        int geolocation_routing;</span><br><span style="color: hsl(120, 100%, 40%);">+      int send_location;</span><br><span style="color: hsl(120, 100%, 40%);">+    enum geoloc_format format;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_variable *location_vars;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_variable *location_refinement;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_variable *location_variables;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_variable *effective_location;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_variable *usage_rules_vars;</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%);">+ * \brief Given an official civicAddress code, return its friendly name.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param code Pointer to the code to check</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Pointer to the friendly name ot NULL if code wasn't found.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *ast_geoloc_civicaddr_get_name_from_code(const char *code);</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%);">+ * \brief Given a civicAddress friendly name, return its official code.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param name Pointer to the name to check</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Pointer to the official code or NULL if name wasn't found.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *ast_geoloc_civicaddr_get_code_from_name(const char *name);</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%);">+ * \brief Given an unknown location variable, return its official civicAddress code.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param variable Pointer to the name or code to check</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Pointer to the official code or NULL if variable wasn't a name or code.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *ast_geoloc_civicaddr_resolve_variable(const char *variable);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_geoloc_validate_result {</span><br><span style="color: hsl(120, 100%, 40%);">+     AST_GEOLOC_VALIDATE_SUCCESS = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_GEOLOC_VALIDATE_MISSING_TYPE,</span><br><span style="color: hsl(120, 100%, 40%);">+     AST_GEOLOC_VALIDATE_INVALID_TYPE,</span><br><span style="color: hsl(120, 100%, 40%);">+     AST_GEOLOC_VALIDATE_INVALID_VARNAME,</span><br><span style="color: hsl(120, 100%, 40%);">+  AST_GEOLOC_VALIDATE_NOT_ENOUGH_VARNAMES,</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_GEOLOC_VALIDATE_TOO_MANY_VARNAMES,</span><br><span style="color: hsl(120, 100%, 40%);">+        AST_GEOLOC_VALIDATE_INVALID_VALUE,</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%);">+const char *ast_geoloc_validate_result_to_str(enum ast_geoloc_validate_result result);</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%);">+ * \brief Validate that the names of the variables in the list are valid codes or synonyms</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param varlist Variable list to check.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param result[OUT] Pointer to char * to receive failing item.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return result code.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_geoloc_validate_result ast_geoloc_civicaddr_validate_varlist(struct ast_variable *varlist,</span><br><span style="color: hsl(120, 100%, 40%);">+   const char **result);</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%);">+ * \brief Validate that the variables in the list represent a valid GML shape</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param varlist Variable list to check.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param result[OUT] Pointer to char * to receive failing item.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return result code.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_geoloc_validate_result ast_geoloc_gml_validate_varlist(struct ast_variable *varlist,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char **result);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_datastore *ast_geoloc_datastore_create(const char *profile_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_geoloc_effective_profile *ast_geoloc_effective_profile_create(struct ast_geoloc_profile *profile);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* INCLUDE_ASTERISK_RES_GEOLOCATION_H_ */</span><br><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index a4d0607..e71773b 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -3465,4 +3465,8 @@</span><br><span>  */</span><br><span> void ast_sip_transport_state_unregister(struct ast_sip_tpmgr_state_callback *element);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define PJSTR_SPEC "%.*s"</span><br><span style="color: hsl(120, 100%, 40%);">+#define PJSIP_STR_FOR_PRINTF(_str) (int)_str.slen, _str.ptr</span><br><span style="color: hsl(120, 100%, 40%);">+#define PJSIP_STR_ADDR_FOR_PRINTF(_str) (int)_str->slen, _str->ptr</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif /* _RES_PJSIP_H */</span><br><span>diff --git a/res/Makefile b/res/Makefile</span><br><span>index cd6e8ad..a6dd181 100644</span><br><span>--- a/res/Makefile</span><br><span>+++ b/res/Makefile</span><br><span>@@ -67,6 +67,7 @@</span><br><span> $(call MOD_ADD_C,res_ari_model,ari/ari_model_validators.c)</span><br><span> $(call MOD_ADD_C,res_stasis_recording,stasis_recording/stored.c)</span><br><span> $(call MOD_ADD_C,res_stir_shaken,$(wildcard res_stir_shaken/*.c))</span><br><span style="color: hsl(120, 100%, 40%);">+$(call MOD_ADD_C,res_geolocation,$(wildcard res_geolocation/*.c))</span><br><span> </span><br><span> res_parking.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)</span><br><span> snmp/agent.o: _ASTCFLAGS+=-fPIC</span><br><span>diff --git a/res/res_geolocation.c b/res/res_geolocation.c</span><br><span>new file mode 100644</span><br><span>index 0000000..df54ed2</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation.c</span><br><span>@@ -0,0 +1,109 @@</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, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></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%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+  <support_level>core</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "res_geolocation/geoloc_private.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *result_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   "Success",</span><br><span style="color: hsl(120, 100%, 40%);">+  "Missing type",</span><br><span style="color: hsl(120, 100%, 40%);">+     "Invalid shape type",</span><br><span style="color: hsl(120, 100%, 40%);">+       "Invalid variable name",</span><br><span style="color: hsl(120, 100%, 40%);">+    "Not enough variables",</span><br><span style="color: hsl(120, 100%, 40%);">+     "Too many variables",</span><br><span style="color: hsl(120, 100%, 40%);">+       "Invalid variable value"</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%);">+const char *ast_geoloc_validate_result_to_str(enum ast_geoloc_validate_result result)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    return result_names[result];</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 reload_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        res += geoloc_civicaddr_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+     res += geoloc_gml_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+   res += geoloc_config_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+        res += geoloc_dialplan_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+      res += geoloc_channel_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+       return (res != 0 ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS);</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%);">+        int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        res += geoloc_channel_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+       res += geoloc_dialplan_unload();</span><br><span style="color: hsl(120, 100%, 40%);">+      res += geoloc_config_unload();</span><br><span style="color: hsl(120, 100%, 40%);">+        res += geoloc_gml_unload();</span><br><span style="color: hsl(120, 100%, 40%);">+   res += geoloc_civicaddr_unload();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return (res != 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 int load_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        res = geoloc_gml_load();</span><br><span style="color: hsl(120, 100%, 40%);">+      if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return AST_MODULE_LOAD_DECLINE;</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%);">+   res = geoloc_civicaddr_load();</span><br><span style="color: hsl(120, 100%, 40%);">+        if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+            unload_module();</span><br><span style="color: hsl(120, 100%, 40%);">+              return AST_MODULE_LOAD_DECLINE;</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%);">+   res = geoloc_config_load();</span><br><span style="color: hsl(120, 100%, 40%);">+   if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+            unload_module();</span><br><span style="color: hsl(120, 100%, 40%);">+              return AST_MODULE_LOAD_DECLINE;</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%);">+   res = geoloc_dialplan_load();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+            unload_module();</span><br><span style="color: hsl(120, 100%, 40%);">+              return AST_MODULE_LOAD_DECLINE;</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%);">+   res = geoloc_channel_load();</span><br><span style="color: hsl(120, 100%, 40%);">+  if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+            unload_module();</span><br><span style="color: hsl(120, 100%, 40%);">+              return AST_MODULE_LOAD_DECLINE;</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 AST_MODULE_LOAD_SUCCESS;</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(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "res_geolocation Module for Asterisk",</span><br><span style="color: hsl(120, 100%, 40%);">+ .support_level = AST_MODULE_SUPPORT_CORE,</span><br><span style="color: hsl(120, 100%, 40%);">+     .load = load_module,</span><br><span style="color: hsl(120, 100%, 40%);">+  .unload = unload_module,</span><br><span style="color: hsl(120, 100%, 40%);">+      .reload = reload_module,</span><br><span style="color: hsl(120, 100%, 40%);">+      .load_pri = AST_MODPRI_CHANNEL_DEPEND - 10,</span><br><span style="color: hsl(120, 100%, 40%);">+);</span><br><span>diff --git a/res/res_geolocation.exports.in b/res/res_geolocation.exports.in</span><br><span>new file mode 100644</span><br><span>index 0000000..da0a981</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation.exports.in</span><br><span>@@ -0,0 +1,6 @@</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    global:</span><br><span style="color: hsl(120, 100%, 40%);">+               LINKER_SYMBOL_PREFIXast_geo*;</span><br><span style="color: hsl(120, 100%, 40%);">+ local:</span><br><span style="color: hsl(120, 100%, 40%);">+                *;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span>diff --git a/res/res_geolocation/geoloc_channel.c b/res/res_geolocation/geoloc_channel.c</span><br><span>new file mode 100644</span><br><span>index 0000000..83787c3</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_channel.c</span><br><span>@@ -0,0 +1,72 @@</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, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></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%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/datastore.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "geoloc_private.h"</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%);">+struct ast_sorcery *geoloc_sorcery;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void geoloc_datastore_destructor(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_geoloc_effective_profile *eprofile = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+  ao2_ref(eprofile, -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%);">+static const struct ast_datastore_info geoloc_datastore_info = {</span><br><span style="color: hsl(120, 100%, 40%);">+       .type = "geolocation",</span><br><span style="color: hsl(120, 100%, 40%);">+      .destroy = geoloc_datastore_destructor</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%);">+struct ast_datastore *ast_geoloc_datastore_create(const char *profile_name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_datastore *ds = ast_datastore_alloc(&geoloc_datastore_info, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_geoloc_effective_profile *eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_geoloc_profile *profile = ast_sorcery_retrieve_by_id(geoloc_sorcery, "profile", profile_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!profile) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_ERROR, "A profile with the name '%s' was not found", profile_name);</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%);">+   eprofile = ast_geoloc_effective_profile_create(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+      ds->data = eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return ds;</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%);">+int geoloc_channel_unload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (geoloc_sorcery) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_sorcery_unref(geoloc_sorcery);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_channel_load(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        geoloc_sorcery = geoloc_get_sorcery();</span><br><span style="color: hsl(120, 100%, 40%);">+        return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_channel_reload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/res/res_geolocation/geoloc_civicaddr.c b/res/res_geolocation/geoloc_civicaddr.c</span><br><span>new file mode 100644</span><br><span>index 0000000..17f35ae</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_civicaddr.c</span><br><span>@@ -0,0 +1,173 @@</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, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></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%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/config.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/cli.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/res_geolocation.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "geoloc_private.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct addr_field_entry {</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *code;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *name;</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 addr_field_entry addr_code_name_entries[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  {"A1", "state_province"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"A2", "county_district"},</span><br><span style="color: hsl(120, 100%, 40%);">+        {"A3", "city"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"A4", "city_district"},</span><br><span style="color: hsl(120, 100%, 40%);">+  {"A5", "neighborhood"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"A6", "street_group"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"ADDCODE", "additional_code"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"BLD", "building"},</span><br><span style="color: hsl(120, 100%, 40%);">+      {"country", "country"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"FLR", "floor"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"HNO", "house_number"},</span><br><span style="color: hsl(120, 100%, 40%);">+  {"HNS", "house_number_suffix"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"LMK", "landmark"},</span><br><span style="color: hsl(120, 100%, 40%);">+      {"LOC", "additional_location"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"NAM", "location_name"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"PC", "postal_code"},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"PCN", "postal_community"},</span><br><span style="color: hsl(120, 100%, 40%);">+      {"PLC", "place_type"},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"POBOX", "po_box"},</span><br><span style="color: hsl(120, 100%, 40%);">+      {"POD", "trailing_street_suffix"},</span><br><span style="color: hsl(120, 100%, 40%);">+        {"POM", "road_post_modifier"},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"PRD", "leading_road_direction"},</span><br><span style="color: hsl(120, 100%, 40%);">+        {"PRM", "road_pre_modifier"},</span><br><span style="color: hsl(120, 100%, 40%);">+     {"RD", "road"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"RD", "street"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"RDBR", "road_branch"},</span><br><span style="color: hsl(120, 100%, 40%);">+  {"RDSEC", "road_section"},</span><br><span style="color: hsl(120, 100%, 40%);">+        {"RDSUBBR", "road_sub_branch"},</span><br><span style="color: hsl(120, 100%, 40%);">+   {"ROOM", "room"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"SEAT", "seat"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"STS", "street_suffix"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"UNIT", "unit"},</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 addr_field_entry addr_name_code_entries[ARRAY_LEN(addr_code_name_entries)];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int compare_civicaddr_codes(const void *_a, const void *_b)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       const struct addr_field_entry *a = _a;</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct addr_field_entry *b = _b;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return strcmp(a->code, b->code);</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 compare_civicaddr_names(const void *_a, const void *_b)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct addr_field_entry *a = _a;</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct addr_field_entry *b = _b;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return strcmp(a->name, b->name);</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%);">+const char *ast_geoloc_civicaddr_get_name_from_code(const char *code)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct addr_field_entry key = { .code = code };</span><br><span style="color: hsl(120, 100%, 40%);">+       struct addr_field_entry *entry = bsearch(&key, addr_code_name_entries, ARRAY_LEN(addr_code_name_entries),</span><br><span style="color: hsl(120, 100%, 40%);">+         sizeof(struct addr_field_entry), compare_civicaddr_codes);</span><br><span style="color: hsl(120, 100%, 40%);">+    return entry ? entry->name : 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%);">+const char *ast_geoloc_civicaddr_get_code_from_name(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct addr_field_entry key = { .name = name };</span><br><span style="color: hsl(120, 100%, 40%);">+       struct addr_field_entry *entry = bsearch(&key, addr_name_code_entries, ARRAY_LEN(addr_name_code_entries),</span><br><span style="color: hsl(120, 100%, 40%);">+         sizeof(struct addr_field_entry), compare_civicaddr_names);</span><br><span style="color: hsl(120, 100%, 40%);">+    return entry ? entry->code : 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%);">+const char *ast_geoloc_civicaddr_resolve_variable(const char *variable)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *result = ast_geoloc_civicaddr_get_name_from_code(variable);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (result) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return result;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     return ast_geoloc_civicaddr_get_code_from_name(variable);</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%);">+enum ast_geoloc_validate_result ast_geoloc_civicaddr_validate_varlist(struct ast_variable *varlist,</span><br><span style="color: hsl(120, 100%, 40%);">+   const char **result)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+     for (var = varlist; var; var = var->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                const char *newname = ast_geoloc_civicaddr_resolve_variable(var->name);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!newname) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       *result = var->name;</span><br><span style="color: hsl(120, 100%, 40%);">+                       return AST_GEOLOC_VALIDATE_INVALID_VARNAME;</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 AST_GEOLOC_VALIDATE_SUCCESS;</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 *handle_civicaddr_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+                e->command = "geoloc show civicAddr_mappings";</span><br><span style="color: hsl(120, 100%, 40%);">+           e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+                 "Usage: geoloc show civicAddr_mappings\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                   "       Show the mappings between civicAddress official codes and synonyms.\n";</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  case CLI_GENERATE:</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_cli(a->fd, "%-16s %-32s\n", "Official Code", "Synonym");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "================ ================================\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < ARRAY_LEN(addr_code_name_entries); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_cli(a->fd, "%-16s %-32s\n", addr_code_name_entries[i].code, addr_code_name_entries[i].name);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_cli(a->fd, "\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return CLI_SUCCESS;</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_cli_entry geoloc_civicaddr_cli[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_CLI_DEFINE(handle_civicaddr_show, "Show the mappings between civicAddress official codes and synonyms"),</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%);">+int geoloc_civicaddr_unload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_cli_unregister_multiple(geoloc_civicaddr_cli, ARRAY_LEN(geoloc_civicaddr_cli));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_civicaddr_load(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(addr_name_code_entries, addr_code_name_entries, sizeof(addr_code_name_entries));</span><br><span style="color: hsl(120, 100%, 40%);">+       qsort(addr_code_name_entries, ARRAY_LEN(addr_code_name_entries), sizeof(struct addr_field_entry), compare_civicaddr_codes);</span><br><span style="color: hsl(120, 100%, 40%);">+   qsort(addr_name_code_entries, ARRAY_LEN(addr_name_code_entries), sizeof(struct addr_field_entry), compare_civicaddr_names);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli_register_multiple(geoloc_civicaddr_cli, ARRAY_LEN(geoloc_civicaddr_cli));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_civicaddr_reload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/res/res_geolocation/geoloc_config.c b/res/res_geolocation/geoloc_config.c</span><br><span>new file mode 100644</span><br><span>index 0000000..3bdc005</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_config.c</span><br><span>@@ -0,0 +1,644 @@</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, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></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%);">+#include "asterisk.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/cli.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "geoloc_private.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/res_geolocation.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_sorcery *geoloc_sorcery;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *pidf_section_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       "<none>",</span><br><span style="color: hsl(120, 100%, 40%);">+     "tuple",</span><br><span style="color: hsl(120, 100%, 40%);">+    "device",</span><br><span style="color: hsl(120, 100%, 40%);">+   "person"</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 const char *format_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       "<none>",</span><br><span style="color: hsl(120, 100%, 40%);">+     "civicAddress",</span><br><span style="color: hsl(120, 100%, 40%);">+     "GML",</span><br><span style="color: hsl(120, 100%, 40%);">+      "URI",</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 const char * location_disposition_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  "discard",</span><br><span style="color: hsl(120, 100%, 40%);">+  "append",</span><br><span style="color: hsl(120, 100%, 40%);">+   "prepend",</span><br><span style="color: hsl(120, 100%, 40%);">+  "replace"</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%);">+CONFIG_ENUM(location, format)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST(location, location_vars)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void geoloc_location_destructor(void *obj) {</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_geoloc_location *location = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(location->location_vars);</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 void *geoloc_location_alloc(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_geoloc_location *location = ast_sorcery_generic_alloc(sizeof(*location), geoloc_location_destructor);</span><br><span style="color: hsl(120, 100%, 40%);">+      return location;</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%);">+CONFIG_ENUM(profile, pidf_section)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_ENUM(profile, location_disposition)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST(profile, location_refinement)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST(profile, location_variables)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST(profile, usage_rules_vars)</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 void geoloc_profile_destructor(void *obj) {</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_geoloc_profile *profile = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_string_field_free_memory(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_variables_destroy(profile->location_refinement);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_variables_destroy(profile->location_variables);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_variables_destroy(profile->usage_rules_vars);</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 void *geoloc_profile_alloc(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_geoloc_profile *profile = ast_sorcery_generic_alloc(sizeof(*profile), geoloc_profile_destructor);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_string_field_init(profile, 128);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return profile;</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 void geoloc_effective_profile_destructor(void *obj) {</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_geoloc_effective_profile *eprofile = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_string_field_free_memory(eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_variables_destroy(eprofile->location_refinement);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_variables_destroy(eprofile->location_variables);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_variables_destroy(eprofile->effective_location);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_variables_destroy(eprofile->usage_rules_vars);</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 void *geoloc_effective_profile_alloc(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_geoloc_effective_profile *eprofile = ao2_alloc_options(sizeof(*eprofile),</span><br><span style="color: hsl(120, 100%, 40%);">+          geoloc_effective_profile_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_string_field_init(eprofile, 256);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(eprofile, id, name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return eprofile;</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%);">+struct ast_geoloc_effective_profile *ast_geoloc_effective_profile_create(struct ast_geoloc_profile *profile)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_geoloc_effective_profile *eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *profile_id = ast_sorcery_object_get_id(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_geoloc_location *loc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       eprofile = geoloc_effective_profile_alloc(profile_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      ao2_lock(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_string_field_set(eprofile, location_reference, profile->location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+   eprofile->geolocation_routing = profile->geolocation_routing;</span><br><span style="color: hsl(120, 100%, 40%);">+   eprofile->pidf_section = profile->pidf_section;</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->location_refinement = profile->location_refinement ? ast_variables_dup(profile->location_refinement) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       eprofile->location_variables = profile->location_variables ? ast_variables_dup(profile->location_variables) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  eprofile->usage_rules_vars = profile->usage_rules_vars ? ast_variables_dup(profile->usage_rules_vars) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        eprofile->location_disposition = profile->location_disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->send_location = profile->send_location;</span><br><span style="color: hsl(120, 100%, 40%);">+       ao2_unlock(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ast_strlen_zero(eprofile->location_reference)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              loc = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", eprofile->location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (loc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+                     eprofile->format = loc->format;</span><br><span style="color: hsl(120, 100%, 40%);">+                 eprofile->location_vars = ast_variables_dup(loc->location_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+                        ao2_ref(loc, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   eprofile->effective_location = ast_variables_dup(loc->location_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+                   for (var = profile->location_refinement; var; var = var->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct ast_variable *newvar = ast_variable_new(var->name, var->value, "");</span><br><span style="color: hsl(120, 100%, 40%);">+                            if (ast_variable_list_replace(&eprofile->effective_location, newvar)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        ast_variable_list_append(&eprofile->effective_location, newvar);</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%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_log(LOG_ERROR, "Profile '%s' referenced location '%s' does not exist!", profile_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                             eprofile->location_reference);</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 eprofile;</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 geoloc_location_apply_handler(const struct ast_sorcery *sorcery, void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_geoloc_location *location = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *location_id = ast_sorcery_object_get_id(location);</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *failed;</span><br><span style="color: hsl(120, 100%, 40%);">+   enum ast_geoloc_validate_result result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (location->format) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case GEOLOC_FORMAT_NONE:</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_log(LOG_ERROR, "Location '%s' must have a format\n", location_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                      return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case GEOLOC_FORMAT_CIVIC_ADDRESS:</span><br><span style="color: hsl(120, 100%, 40%);">+             result = ast_geoloc_civicaddr_validate_varlist(location->location_vars, &failed);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (result != AST_GEOLOC_VALIDATE_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_log(LOG_ERROR, "Location '%s' has invalid item '%s' in the location\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                         location_id, failed);</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%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case GEOLOC_FORMAT_GML:</span><br><span style="color: hsl(120, 100%, 40%);">+               result = ast_geoloc_gml_validate_varlist(location->location_vars, &failed);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (result != AST_GEOLOC_VALIDATE_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_log(LOG_ERROR, "%s for item '%s' in location '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_geoloc_validate_result_to_str(result),      failed, location_id);</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%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case GEOLOC_FORMAT_URI:</span><br><span style="color: hsl(120, 100%, 40%);">+               const char *uri = ast_variable_find_in_list(location->location_vars, "URI");</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!uri) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   struct ast_str *str = ast_variable_list_join(location->location_vars, ",", "=", "\"", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_log(LOG_ERROR, "Geolocation location '%s' format is set to '%s' but no 'URI' was found in location parameter '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           location_id, format_names[GEOLOC_FORMAT_URI], ast_str_buffer(str));</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_free(str);</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%);">+             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%);">+   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 int geoloc_profile_apply_handler(const struct ast_sorcery *sorcery, void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_geoloc_profile *profile = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_geoloc_location *location;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *profile_id = ast_sorcery_object_get_id(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *failed;</span><br><span style="color: hsl(120, 100%, 40%);">+   enum ast_geoloc_validate_result result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ast_strlen_zero(profile->location_reference)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (profile->location_refinement ||</span><br><span style="color: hsl(120, 100%, 40%);">+                        profile->location_variables) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_log(LOG_ERROR, "Profile '%s' can't have location_refinement or location_variables without a location_reference",</span><br><span style="color: hsl(120, 100%, 40%);">+                            profile_id);</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%);">+             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%);">+   location = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", profile->location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!location) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_ERROR, "Profile '%s' has a location_reference '%s' that doesn't exist",</span><br><span style="color: hsl(120, 100%, 40%);">+                     profile_id, profile->location_reference);</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 (profile->location_refinement) {</span><br><span style="color: hsl(120, 100%, 40%);">+                switch (location->format) {</span><br><span style="color: hsl(120, 100%, 40%);">+                case GEOLOC_FORMAT_NONE:</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GEOLOC_FORMAT_CIVIC_ADDRESS:</span><br><span style="color: hsl(120, 100%, 40%);">+                     result = ast_geoloc_civicaddr_validate_varlist(profile->location_refinement, &failed);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (result != AST_GEOLOC_VALIDATE_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          ast_log(LOG_ERROR, "Profile '%s' error: %s: for item '%s' in the location_refinement\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    profile_id,     ast_geoloc_validate_result_to_str(result), failed);</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%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GEOLOC_FORMAT_GML:</span><br><span style="color: hsl(120, 100%, 40%);">+                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GEOLOC_FORMAT_URI:</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%);">+</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%);">+struct ast_sorcery *geoloc_get_sorcery(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_sorcery_ref(geoloc_sorcery);</span><br><span style="color: hsl(120, 100%, 40%);">+      return geoloc_sorcery;</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 *geoloc_config_list_locations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ao2_iterator iter;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ao2_container *sorted_container;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ao2_container *unsorted_container;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_geoloc_location *loc;</span><br><span style="color: hsl(120, 100%, 40%);">+      int using_regex = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *result = CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *format_name;</span><br><span style="color: hsl(120, 100%, 40%);">+    int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+                e->command = "geoloc list locations";</span><br><span style="color: hsl(120, 100%, 40%);">+            e->usage = "Usage: geoloc list locations [ like <pattern> ]\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                         "      List Geolocation Location Objects\n";</span><br><span style="color: hsl(120, 100%, 40%);">+            return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  case CLI_GENERATE:</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%);">+   if (a->argc != 3 && a->argc != 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return CLI_SHOWUSAGE;</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 (a->argc == 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcasecmp(a->argv[3], "like")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             using_regex = 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%);">+   sorted_container = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_sorcery_object_id_sort, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!sorted_container) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_cli(a->fd, "Geolocation Location Objects: Unable to allocate temporary container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return CLI_FAILURE;</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%);">+   /* Get a sorted snapshot of the scheduled tasks */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (using_regex) {</span><br><span style="color: hsl(120, 100%, 40%);">+            unsorted_container = ast_sorcery_retrieve_by_regex(geoloc_sorcery, "location", a->argv[4]);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              unsorted_container = ast_sorcery_retrieve_by_fields(geoloc_sorcery, "location",</span><br><span style="color: hsl(120, 100%, 40%);">+                     AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, 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%);">+   ret = ao2_container_dup(sorted_container, unsorted_container, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_ref(unsorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ret != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ao2_ref(sorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_cli(a->fd, "Geolocation Location Objects: Unable to sort temporary container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return CLI_FAILURE;</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_cli(a->fd, "Geolocation Location Objects:\n\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_cli(a->fd,</span><br><span style="color: hsl(120, 100%, 40%);">+             "<Object ID...................................> <Format.....> <Details.............>\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "===================================================================================\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ iter = ao2_iterator_init(sorted_container, AO2_ITERATOR_UNLINK);</span><br><span style="color: hsl(120, 100%, 40%);">+      for (; (loc = ao2_iterator_next(&iter)); ao2_ref(loc, -1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              struct ast_str *str;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                ao2_lock(loc);</span><br><span style="color: hsl(120, 100%, 40%);">+                str = ast_variable_list_join(loc->location_vars, ",", "=", "\"", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!str) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   ao2_unlock(loc);</span><br><span style="color: hsl(120, 100%, 40%);">+                      ao2_ref(loc, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_cli(a->fd, "Geolocation Location Objects: Unable to allocate temp string for '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                ast_sorcery_object_get_id(loc));</span><br><span style="color: hsl(120, 100%, 40%);">+                      result = CLI_FAILURE;</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%);">+           format_to_str(loc, NULL, &format_name);</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_cli(a->fd, "%-46.46s %-13s %-s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_sorcery_object_get_id(loc),</span><br><span style="color: hsl(120, 100%, 40%);">+                       format_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_str_buffer(str));</span><br><span style="color: hsl(120, 100%, 40%);">+         ao2_unlock(loc);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_free(str);</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_free(format_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                count++;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_iterator_destroy(&iter);</span><br><span style="color: hsl(120, 100%, 40%);">+      ao2_ref(sorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_cli(a->fd, "\nTotal Location Objects: %d\n\n", count);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return result;</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 *geoloc_config_list_profiles(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ao2_iterator iter;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ao2_container *sorted_container;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ao2_container *unsorted_container;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_geoloc_profile *profile;</span><br><span style="color: hsl(120, 100%, 40%);">+   int using_regex = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *result = CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+    int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+                e->command = "geoloc list profiles";</span><br><span style="color: hsl(120, 100%, 40%);">+             e->usage = "Usage: geoloc list profiles [ like <pattern> ]\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                          "      List Geolocation Profile Objects\n";</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  case CLI_GENERATE:</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%);">+   if (a->argc != 3 && a->argc != 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return CLI_SHOWUSAGE;</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 (a->argc == 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcasecmp(a->argv[3], "like")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             using_regex = 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%);">+   sorted_container = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_sorcery_object_id_sort, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!sorted_container) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_cli(a->fd, "Geolocation Profile Objects: Unable to allocate temporary container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return CLI_FAILURE;</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%);">+   /* Get a sorted snapshot of the scheduled tasks */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (using_regex) {</span><br><span style="color: hsl(120, 100%, 40%);">+            unsorted_container = ast_sorcery_retrieve_by_regex(geoloc_sorcery, "profile", a->argv[4]);</span><br><span style="color: hsl(120, 100%, 40%);">+       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              unsorted_container = ast_sorcery_retrieve_by_fields(geoloc_sorcery, "profile",</span><br><span style="color: hsl(120, 100%, 40%);">+                      AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, 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%);">+   ret = ao2_container_dup(sorted_container, unsorted_container, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_ref(unsorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ret != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ao2_ref(sorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_cli(a->fd, "Geolocation Profile Objects: Unable to sort temporary container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             return CLI_FAILURE;</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_cli(a->fd, "Geolocation Profile Objects:\n\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_cli(a->fd,</span><br><span style="color: hsl(120, 100%, 40%);">+             "<Object ID...................................> <Disposition> <Send> <Location Reference> \n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "=========================================================================================\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   iter = ao2_iterator_init(sorted_container, AO2_ITERATOR_UNLINK);</span><br><span style="color: hsl(120, 100%, 40%);">+      for (; (profile = ao2_iterator_next(&iter)); ao2_ref(profile, -1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ao2_lock(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          location_disposition_to_str(profile, NULL, &disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_cli(a->fd, "%-46.46s %-13s %-6s %-s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_sorcery_object_get_id(profile),</span><br><span style="color: hsl(120, 100%, 40%);">+                   disposition,</span><br><span style="color: hsl(120, 100%, 40%);">+                  profile->send_location ? "yes" : "no",</span><br><span style="color: hsl(120, 100%, 40%);">+                 profile->location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+              ao2_unlock(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_free(disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+                count++;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_iterator_destroy(&iter);</span><br><span style="color: hsl(120, 100%, 40%);">+      ao2_ref(sorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_cli(a->fd, "\nTotal Profile Objects: %d\n\n", count);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return result;</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 *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ao2_iterator iter;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ao2_container *sorted_container;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ao2_container *unsorted_container;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_geoloc_profile *profile;</span><br><span style="color: hsl(120, 100%, 40%);">+   int using_regex = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *result = CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+                e->command = "geoloc show profiles";</span><br><span style="color: hsl(120, 100%, 40%);">+             e->usage = "Usage: geoloc show profiles [ like <pattern> ]\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                          "      List Geolocation Profile Objects\n";</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  case CLI_GENERATE:</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%);">+   if (a->argc != 3 && a->argc != 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return CLI_SHOWUSAGE;</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 (a->argc == 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcasecmp(a->argv[3], "like")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             using_regex = 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%);">+   sorted_container = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_sorcery_object_id_sort, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!sorted_container) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_cli(a->fd, "Geolocation Profile Objects: Unable to allocate temporary container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return CLI_FAILURE;</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%);">+   /* Get a sorted snapshot of the scheduled tasks */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (using_regex) {</span><br><span style="color: hsl(120, 100%, 40%);">+            unsorted_container = ast_sorcery_retrieve_by_regex(geoloc_sorcery, "profile", a->argv[4]);</span><br><span style="color: hsl(120, 100%, 40%);">+       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              unsorted_container = ast_sorcery_retrieve_by_fields(geoloc_sorcery, "profile",</span><br><span style="color: hsl(120, 100%, 40%);">+                      AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, 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%);">+   ret = ao2_container_dup(sorted_container, unsorted_container, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_ref(unsorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ret != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ao2_ref(sorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_cli(a->fd, "Geolocation Profile Objects: Unable to sort temporary container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             return CLI_FAILURE;</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_cli(a->fd, "Geolocation Profile Objects:\n\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    iter = ao2_iterator_init(sorted_container, AO2_ITERATOR_UNLINK);</span><br><span style="color: hsl(120, 100%, 40%);">+      for (; (profile = ao2_iterator_next(&iter)); ) {</span><br><span style="color: hsl(120, 100%, 40%);">+          char *disposition = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+             struct ast_str *loc_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+               struct ast_str *refinement_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                struct ast_str *variables_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+         struct ast_str *resolved_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          struct ast_geoloc_effective_profile *eprofile = ast_geoloc_effective_profile_create(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+         ao2_ref(profile, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!ast_strlen_zero(eprofile->location_reference)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      loc_str = ast_variable_list_join(eprofile->location_vars, ",", "=", "\"", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                        resolved_str = ast_variable_list_join(eprofile->effective_location, ",", "=", "\"", 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%);">+           refinement_str = ast_variable_list_join(eprofile->location_refinement, ",", "=", "\"", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+           variables_str = ast_variable_list_join(eprofile->location_variables, ",", "=", "\"", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           location_disposition_to_str(eprofile, NULL, &disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_cli(a->fd,</span><br><span style="color: hsl(120, 100%, 40%);">+                     "id:                            %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "received_location_disposition: %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "send_location:                 %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "pidf_section:                  %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "location_reference:            %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "Location_format:               %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "location_reference_details:    %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "location_refinement:           %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "location_variables:            %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "effective_location:            %-s\n\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   eprofile->id,</span><br><span style="color: hsl(120, 100%, 40%);">+                      disposition,</span><br><span style="color: hsl(120, 100%, 40%);">+                  eprofile->send_location ? "yes" : "no",</span><br><span style="color: hsl(120, 100%, 40%);">+                        pidf_section_names[eprofile->pidf_section],</span><br><span style="color: hsl(120, 100%, 40%);">+                        S_OR(eprofile->location_reference, "<none>"),</span><br><span style="color: hsl(120, 100%, 40%);">+                      format_names[eprofile->format],</span><br><span style="color: hsl(120, 100%, 40%);">+                    S_COR(loc_str, ast_str_buffer(loc_str), "<none>"),</span><br><span style="color: hsl(120, 100%, 40%);">+                    S_COR(refinement_str, ast_str_buffer(refinement_str), "<none>"),</span><br><span style="color: hsl(120, 100%, 40%);">+                      S_COR(variables_str, ast_str_buffer(variables_str), "<none>"),</span><br><span style="color: hsl(120, 100%, 40%);">+                        S_COR(resolved_str, ast_str_buffer(resolved_str), "<none>"));</span><br><span style="color: hsl(120, 100%, 40%);">+         ao2_ref(eprofile, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_free(disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_free(loc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_free(refinement_str);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_free(variables_str);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_free(resolved_str);</span><br><span style="color: hsl(120, 100%, 40%);">+               count++;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_iterator_destroy(&iter);</span><br><span style="color: hsl(120, 100%, 40%);">+      ao2_ref(sorted_container, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_cli(a->fd, "\nTotal Profile Objects: %d\n\n", count);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return result;</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 *geoloc_config_cli_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char *result = CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+                e->command = "geoloc reload";</span><br><span style="color: hsl(120, 100%, 40%);">+            e->usage = "Usage: geoloc reload\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                          "      Reload Geolocation Configuration\n";</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  case CLI_GENERATE:</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%);">+   if (a->argc != 2) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return CLI_SHOWUSAGE;</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%);">+   geoloc_config_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_cli(a->fd, "Geolocation Configuration reloaded.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return result;</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_cli_entry geoloc_location_cli_commands[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_CLI_DEFINE(geoloc_config_list_locations, "List Geolocation Location Objects"),</span><br><span style="color: hsl(120, 100%, 40%);">+  AST_CLI_DEFINE(geoloc_config_list_profiles, "List Geolocation Profile Objects"),</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_CLI_DEFINE(geoloc_config_show_profiles, "Show Geolocation Profile Objects"),</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_CLI_DEFINE(geoloc_config_cli_reload, "Reload Geolocation Configuration"),</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%);">+int geoloc_config_reload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (geoloc_sorcery) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_sorcery_reload(geoloc_sorcery);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_config_unload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_cli_unregister_multiple(geoloc_location_cli_commands, ARRAY_LEN(geoloc_location_cli_commands));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (geoloc_sorcery) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_sorcery_unref(geoloc_sorcery);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     geoloc_sorcery = NULL;</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%);">+int geoloc_config_load(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!(geoloc_sorcery = ast_sorcery_open())) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_log(LOG_ERROR, "Failed to open geolocation sorcery\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_MODULE_LOAD_DECLINE;</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_sorcery_apply_default(geoloc_sorcery, "location", "config", "geolocation.conf,criteria=type=location");</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ast_sorcery_object_register(geoloc_sorcery, "location", geoloc_location_alloc, NULL, geoloc_location_apply_handler)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "Failed to register geoloc location object with sorcery\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_sorcery_unref(geoloc_sorcery);</span><br><span style="color: hsl(120, 100%, 40%);">+            geoloc_sorcery = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                return AST_MODULE_LOAD_DECLINE;</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_sorcery_object_field_register(geoloc_sorcery, "location", "type", "", OPT_NOOP_T, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "format", GEOLOC_FORMAT_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+                format_handler, format_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "location", NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+            location_vars_handler, location_vars_to_str, location_vars_dup, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_sorcery_apply_default(geoloc_sorcery, "profile", "config", "geolocation.conf,criteria=type=profile");</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ast_sorcery_object_register(geoloc_sorcery, "profile", geoloc_profile_alloc, NULL, geoloc_profile_apply_handler)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_ERROR, "Failed to register geoloc profile object with sorcery\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_sorcery_unref(geoloc_sorcery);</span><br><span style="color: hsl(120, 100%, 40%);">+            geoloc_sorcery = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                return AST_MODULE_LOAD_DECLINE;</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_sorcery_object_field_register(geoloc_sorcery, "profile", "type", "", OPT_NOOP_T, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "pidf_lo_section", PIDF_SECTION_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+         pidf_section_handler, pidf_section_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_sorcery_object_field_register(geoloc_sorcery, "profile", "location_reference", "", OPT_STRINGFIELD_T,</span><br><span style="color: hsl(120, 100%, 40%);">+               0, STRFLDSET(struct ast_geoloc_profile, location_reference));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "received_location_disposition", "discard",</span><br><span style="color: hsl(120, 100%, 40%);">+         location_disposition_handler, location_disposition_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_sorcery_object_field_register(geoloc_sorcery, "profile", "send_location", "no",</span><br><span style="color: hsl(120, 100%, 40%);">+             OPT_BOOL_T, 1, FLDSET(struct ast_geoloc_profile, send_location));</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "usage_rules", NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+          usage_rules_vars_handler, usage_rules_vars_to_str, usage_rules_vars_dup, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_refinement", NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+          location_refinement_handler, location_refinement_to_str, location_refinement_dup, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_variables", NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+           location_variables_handler, location_variables_to_str, location_variables_dup, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_sorcery_load(geoloc_sorcery);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_cli_register_multiple(geoloc_location_cli_commands, ARRAY_LEN(geoloc_location_cli_commands));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/res/res_geolocation/geoloc_dialplan.c b/res/res_geolocation/geoloc_dialplan.c</span><br><span>new file mode 100644</span><br><span>index 0000000..776441c</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_dialplan.c</span><br><span>@@ -0,0 +1,38 @@</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, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></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%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/config.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/cli.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/res_geolocation.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "geoloc_private.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_dialplan_unload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_dialplan_load(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_dialplan_reload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/res/res_geolocation/geoloc_doc.xml b/res/res_geolocation/geoloc_doc.xml</span><br><span>new file mode 100644</span><br><span>index 0000000..36bfa3c</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_doc.xml</span><br><span>@@ -0,0 +1,138 @@</span><br><span style="color: hsl(120, 100%, 40%);">+<?xml version="1.0" encoding="UTF-8"?></span><br><span style="color: hsl(120, 100%, 40%);">+<!DOCTYPE docs SYSTEM "appdocsxml.dtd"></span><br><span style="color: hsl(120, 100%, 40%);">+<docs></span><br><span style="color: hsl(120, 100%, 40%);">+     <configInfo name="res_geolocation" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+                <synopsis>Core Geolocation Support</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+             <configFile name="geolocation.conf"></span><br><span style="color: hsl(120, 100%, 40%);">+                  <configObject name="location"></span><br><span style="color: hsl(120, 100%, 40%);">+                                <synopsis>Location</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                             <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                   <para>cffdffff</para></span><br><span style="color: hsl(120, 100%, 40%);">+                             </description></span><br><span style="color: hsl(120, 100%, 40%);">+                          <configOption name="type"></span><br><span style="color: hsl(120, 100%, 40%);">+                                    <synopsis>Must be of type 'location'.</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                          </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="format" default=""></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <synopsis>Location specification type</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                           <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                                      <enum name="civicAddress"></span><br><span style="color: hsl(120, 100%, 40%);">+                                                            <para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                                  The</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                   <literal>location</literal></span><br><span style="color: hsl(120, 100%, 40%);">+                                                                       parameter must contain a comma separated list of IANA codes</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                   describing this location.</span><br><span style="color: hsl(120, 100%, 40%);">+                                                             </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                 </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                                                 <enum name="GML"></span><br><span style="color: hsl(120, 100%, 40%);">+                                                             <para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                                  The</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                   <literal>location</literal> parameter must contain a comma</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                        separated list valid GML elements describing this location.</span><br><span style="color: hsl(120, 100%, 40%);">+                                                           </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                 </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                                                 <enum name="URI"></span><br><span style="color: hsl(120, 100%, 40%);">+                                                             <para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                                  The</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                   <literal>location</literal> parameter must contain a single</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                       URI parameter which contains an external URI describing this location.</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                 </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                                         </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                     </description></span><br><span style="color: hsl(120, 100%, 40%);">+                          </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="location" default=""></span><br><span style="color: hsl(120, 100%, 40%);">+                                   <synopsis>Location Data</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                                        <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                           <para>The contents of this parameter are specific to the</span><br><span style="color: hsl(120, 100%, 40%);">+                                                        specification type.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                                      </description></span><br><span style="color: hsl(120, 100%, 40%);">+                          </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                 </configObject>   </span><br><span style="color: hsl(120, 100%, 40%);">+                      <configObject name="profile"></span><br><span style="color: hsl(120, 100%, 40%);">+                         <synopsis>Profile</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                              <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                   <para>cffdffff</para></span><br><span style="color: hsl(120, 100%, 40%);">+                             </description></span><br><span style="color: hsl(120, 100%, 40%);">+                          <configOption name="type"></span><br><span style="color: hsl(120, 100%, 40%);">+                                    <synopsis>Must be of type 'profile'.</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                           </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="pidf_lo_section" default="device"></span><br><span style="color: hsl(120, 100%, 40%);">+                                      <synopsis>PIDF-LO element to place this profile in</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                           <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                                      <enum name="tuple" /></span><br><span style="color: hsl(120, 100%, 40%);">+                                                 <enum name="device" /></span><br><span style="color: hsl(120, 100%, 40%);">+                                                        <enum name="person" /></span><br><span style="color: hsl(120, 100%, 40%);">+                                                </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                             <para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                  Based on RFC5491 (see below) the recommended and default element</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      is <literal>device</literal>.</span><br><span style="color: hsl(120, 100%, 40%);">+                                             </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                 </description></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+                                              <ref type="link">https://www.rfc-editor.org/rfc/rfc5491.html#section-3.4</ref></span><br><span style="color: hsl(120, 100%, 40%);">+                                  </see-also></span><br><span style="color: hsl(120, 100%, 40%);">+                             </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="location_reference" default=""></span><br><span style="color: hsl(120, 100%, 40%);">+                                 <synopsis>Reference to a location object</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                               </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="location_refinement" default=""></span><br><span style="color: hsl(120, 100%, 40%);">+                                        <synopsis>Reference to a location object</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                               </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="location_variables" default=""></span><br><span style="color: hsl(120, 100%, 40%);">+                                 <synopsis>Reference to a location object</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                               </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="usage_rules" default="yes"></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <synopsis>location specification type</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                           <para>xxxx</para></span><br><span style="color: hsl(120, 100%, 40%);">+                                 </description></span><br><span style="color: hsl(120, 100%, 40%);">+                          </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="received_location_disposition" default="no"></span><br><span style="color: hsl(120, 100%, 40%);">+                                    <synopsis>Determine whether the location information supplied to a</span><br><span style="color: hsl(120, 100%, 40%);">+                                              channel should be used</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                                       <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                           <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                                      <enum name="discard"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                                        <enum name="append"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                                 <enum name="prepend"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                                        <enum name="replace"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                                </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                     </description></span><br><span style="color: hsl(120, 100%, 40%);">+                          </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="send_location" default="no"></span><br><span style="color: hsl(120, 100%, 40%);">+                                    <synopsis>Determine whether the channel will send location</span><br><span style="color: hsl(120, 100%, 40%);">+                                              information</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                           <para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                  For an incoming call leg, this determines if location information</span><br><span style="color: hsl(120, 100%, 40%);">+                                                     will be forwarded to the dialplan. If <replaceable>accept_location</replaceable></span><br><span style="color: hsl(120, 100%, 40%);">+                                                  is set to <literal>yes</literal> and location information was actually</span><br><span style="color: hsl(120, 100%, 40%);">+                                                    received from the client, it will be forwarded to the dialplan and any location</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       information in this profile will be ignored. If <replaceable>accept_location</replaceable></span><br><span style="color: hsl(120, 100%, 40%);">+                                                        is set to <literal>no</literal> or no location information was received</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   from the client, location information from this profile, if any, will be</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      forwarded to the dialplan. Dialplan functions can modify this information before</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      forwarding to the outgoing call leg.</span><br><span style="color: hsl(120, 100%, 40%);">+                                          </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                         <para></span><br><span style="color: hsl(120, 100%, 40%);">+                                                  For an outgoing call leg, this determines if location information</span><br><span style="color: hsl(120, 100%, 40%);">+                                                     will be forwarded to the remote UAS. If</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       <replaceable>accept_location</replaceable></span><br><span style="color: hsl(120, 100%, 40%);">+                                                        is set to <literal>yes</literal> and location information was actually received from</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      the dialplan, it will be sent and any location information in this</span><br><span style="color: hsl(120, 100%, 40%);">+                                                    profile will be ignored. If <replaceable>accept_location</replaceable></span><br><span style="color: hsl(120, 100%, 40%);">+                                                    is set to <literal>no</literal> or no location information was received from</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      the dialplan, location information from this profile, if any, will be sent.</span><br><span style="color: hsl(120, 100%, 40%);">+                                           </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                 </description></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+                                              <ref type="configOption">accept_location</ref></span><br><span style="color: hsl(120, 100%, 40%);">+                                  </see-also></span><br><span style="color: hsl(120, 100%, 40%);">+                             </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                 </configObject></span><br><span style="color: hsl(120, 100%, 40%);">+         </configFile></span><br><span style="color: hsl(120, 100%, 40%);">+   </configInfo></span><br><span style="color: hsl(120, 100%, 40%);">+</docs></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/res/res_geolocation/geoloc_gml.c b/res/res_geolocation/geoloc_gml.c</span><br><span>new file mode 100644</span><br><span>index 0000000..972f5b9</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_gml.c</span><br><span>@@ -0,0 +1,255 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2022, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></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%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/config.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/cli.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/res_geolocation.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "geoloc_private.h"</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 1 //not used yet.</span><br><span style="color: hsl(120, 100%, 40%);">+enum geoloc_shape_attrs {</span><br><span style="color: hsl(120, 100%, 40%);">+   GEOLOC_SHAPE_ATTR_POS = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+    GEOLOC_SHAPE_ATTR_POS3D,</span><br><span style="color: hsl(120, 100%, 40%);">+      GEOLOC_SHAPE_ATTR_RADIUS,</span><br><span style="color: hsl(120, 100%, 40%);">+     GEOLOC_SHAPE_ATTR_SEMI_MAJOR_AXIS,</span><br><span style="color: hsl(120, 100%, 40%);">+    GEOLOC_SHAPE_ATTR_SEMI_MINOR_AXIS,</span><br><span style="color: hsl(120, 100%, 40%);">+    GEOLOC_SHAPE_ATTR_VERTICAL_AXIS,</span><br><span style="color: hsl(120, 100%, 40%);">+      GEOLOC_SHAPE_ATTR_HEIGHT,</span><br><span style="color: hsl(120, 100%, 40%);">+     GEOLOC_SHAPE_ATTR_ORIENTATION,</span><br><span style="color: hsl(120, 100%, 40%);">+        GEOLOC_SHAPE_ATTR_ORIENTATION_UOM,</span><br><span style="color: hsl(120, 100%, 40%);">+    GEOLOC_SHAPE_ATTR_INNER_RADIUS,</span><br><span style="color: hsl(120, 100%, 40%);">+       GEOLOC_SHAPE_ATTR_OUTER_RADIUS,</span><br><span style="color: hsl(120, 100%, 40%);">+       GEOLOC_SHAPE_ATTR_STARTING_ANGLE,</span><br><span style="color: hsl(120, 100%, 40%);">+     GEOLOC_SHAPE_ATTR_OPENING_ANGLE,</span><br><span style="color: hsl(120, 100%, 40%);">+      GEOLOC_SHAPE_ATTR_ANGLE_UOM,</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%);">+struct geoloc_gml_attr_def {</span><br><span style="color: hsl(120, 100%, 40%);">+      enum geoloc_shape_attrs attr;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+     int (*validator)(const char *value);</span><br><span style="color: hsl(120, 100%, 40%);">+  int (*transformer)(struct ast_variable *value);</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%);">+struct geoloc_gml_attr_def gml_attr_defs[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { GEOLOC_SHAPE_ATTR_POS, "pos", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+        { GEOLOC_SHAPE_ATTR_POS3D,"pos3d", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+     { GEOLOC_SHAPE_ATTR_RADIUS,"radius", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+   { GEOLOC_SHAPE_ATTR_SEMI_MAJOR_AXIS,"semiMajorAxis", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+   { GEOLOC_SHAPE_ATTR_SEMI_MINOR_AXIS,"semiMinorAxis", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+   { GEOLOC_SHAPE_ATTR_VERTICAL_AXIS,"verticalAxis", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+      { GEOLOC_SHAPE_ATTR_HEIGHT,"height", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+   { GEOLOC_SHAPE_ATTR_ORIENTATION,"orientation", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+ { GEOLOC_SHAPE_ATTR_ORIENTATION_UOM,"orientation_uom", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+ { GEOLOC_SHAPE_ATTR_INNER_RADIUS,"innerRadius", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+        { GEOLOC_SHAPE_ATTR_OUTER_RADIUS,"outerRadius", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+        { GEOLOC_SHAPE_ATTR_STARTING_ANGLE,"startingAngle", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+    { GEOLOC_SHAPE_ATTR_OPENING_ANGLE,"openingAngle", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+      { GEOLOC_SHAPE_ATTR_ANGLE_UOM,"angle_uom", NULL, NULL},</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+#endif  //not used yet.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct geoloc_gml_attr {</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *attribute;</span><br><span style="color: hsl(120, 100%, 40%);">+        int min_required;</span><br><span style="color: hsl(120, 100%, 40%);">+     int max_allowed;</span><br><span style="color: hsl(120, 100%, 40%);">+      int (*validator)(const char *value);</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%);">+struct geoloc_gml_shape_def {</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *shape_type;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct geoloc_gml_attr required_attributes[8];</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 pos_validator(const char *value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  float lat;</span><br><span style="color: hsl(120, 100%, 40%);">+    float lon;</span><br><span style="color: hsl(120, 100%, 40%);">+    return (sscanf(value, "%f %f", &lat, &lon) == 2);</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 pos3d_validator(const char *value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    float lat;</span><br><span style="color: hsl(120, 100%, 40%);">+    float lon;</span><br><span style="color: hsl(120, 100%, 40%);">+    float alt;</span><br><span style="color: hsl(120, 100%, 40%);">+    return (sscanf(value, "%f %f %f", &lat, &lon, &alt) == 3);</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 float_validator(const char *value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       float val;</span><br><span style="color: hsl(120, 100%, 40%);">+    return (sscanf(value, "%f", &val) == 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%);">+static int uom_validator(const char *value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   return (ast_strings_equal(value, "degrees") || ast_strings_equal(value, "radians"));</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 struct geoloc_gml_shape_def gml_shape_defs[8] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     { "Point", { {"pos", 1, 1, pos_validator}, {NULL, -1, -1} }},</span><br><span style="color: hsl(120, 100%, 40%);">+     { "Polygon", { {"pos", 3, -1, pos_validator}, {NULL, -1, -1} }},</span><br><span style="color: hsl(120, 100%, 40%);">+  { "Circle", { {"pos", 1, 1, pos_validator}, {"radius", 1, 1, float_validator},{NULL, -1, -1}}},</span><br><span style="color: hsl(120, 100%, 40%);">+ { "Ellipse", { {"pos", 1, 1, pos_validator}, {"semiMajorAxis", 1, 1, float_validator},</span><br><span style="color: hsl(120, 100%, 40%);">+          {"semiMinorAxis", 1, 1, float_validator}, {"orientation", 1, 1, float_validator},</span><br><span style="color: hsl(120, 100%, 40%);">+         {"orientation_uom", 1, 1, uom_validator}, {NULL, -1, -1} }},</span><br><span style="color: hsl(120, 100%, 40%);">+        { "ArcBand", { {"pos", 1, 1, pos_validator}, {"innerRadius", 1, 1, float_validator},</span><br><span style="color: hsl(120, 100%, 40%);">+            {"outerRadius", 1, 1, float_validator}, {"startAngle", 1, 1, float_validator},</span><br><span style="color: hsl(120, 100%, 40%);">+            {"startAngle_uom", 1, 1, uom_validator}, {"openingAngle", 1, 1, float_validator},</span><br><span style="color: hsl(120, 100%, 40%);">+         {"openingAngle_uom", 1, 1, uom_validator}, {NULL, -1, -1} }},</span><br><span style="color: hsl(120, 100%, 40%);">+       { "Sphere", { {"pos3d", 1, 1, pos3d_validator}, {"radius", 1, 1, float_validator}, {NULL, -1, -1} }},</span><br><span style="color: hsl(120, 100%, 40%);">+   { "Ellipse", { {"pos3d", 1, 1, pos3d_validator}, {"semiMajorAxis", 1, 1, float_validator},</span><br><span style="color: hsl(120, 100%, 40%);">+              {"semiMinorAxis", 1, 1, float_validator}, {"verticalAxis", 1, 1, float_validator},</span><br><span style="color: hsl(120, 100%, 40%);">+                {"orientation", 1, 1, float_validator}, {"orientation_uom", 1, 1, uom_validator}, {NULL, -1, -1} }},</span><br><span style="color: hsl(120, 100%, 40%);">+      { "Prism", { {"pos3d", 3, -1, pos_validator}, {"height", 1, 1, float_validator}, {NULL, -1, -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%);">+enum ast_geoloc_validate_result ast_geoloc_gml_validate_varlist(struct ast_variable *varlist,</span><br><span style="color: hsl(120, 100%, 40%);">+        const char **result)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int def_index = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+     int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *shape_type = ast_variable_find_in_list(varlist, "type");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!shape_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return AST_GEOLOC_VALIDATE_MISSING_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%);">+   for (i = 0; i < ARRAY_LEN(gml_shape_defs); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (ast_strings_equal(gml_shape_defs[i].shape_type, shape_type)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    def_index = i;</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 (def_index < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+               return AST_GEOLOC_VALIDATE_INVALID_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%);">+   for (var = varlist; var; var = var->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                int vname_index = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+         if (ast_strings_equal("type", var->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             for (i = 0; i < ARRAY_LEN(gml_shape_defs[def_index].required_attributes); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (gml_shape_defs[def_index].required_attributes[i].attribute == NULL) {</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%);">+                     if (ast_strings_equal(gml_shape_defs[def_index].required_attributes[i].attribute, var->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            vname_index = i;</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%);">+             if (vname_index < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     *result = var->name;</span><br><span style="color: hsl(120, 100%, 40%);">+                       return AST_GEOLOC_VALIDATE_INVALID_VARNAME;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!gml_shape_defs[def_index].required_attributes[vname_index].validator(var->value)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   *result = var->name;</span><br><span style="color: hsl(120, 100%, 40%);">+                       return AST_GEOLOC_VALIDATE_INVALID_VALUE;</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; i < ARRAY_LEN(gml_shape_defs[def_index].required_attributes); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                if (gml_shape_defs[def_index].required_attributes[i].attribute == NULL) {</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%);">+           for (var = varlist; var; var = var->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (ast_strings_equal(gml_shape_defs[def_index].required_attributes[i].attribute, var->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            count++;</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 (count < gml_shape_defs[def_index].required_attributes[i].min_required) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       *result = gml_shape_defs[def_index].required_attributes[i].attribute;</span><br><span style="color: hsl(120, 100%, 40%);">+                 return AST_GEOLOC_VALIDATE_NOT_ENOUGH_VARNAMES;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (gml_shape_defs[def_index].required_attributes[i].max_allowed > 0 &&</span><br><span style="color: hsl(120, 100%, 40%);">+                    count > gml_shape_defs[def_index].required_attributes[i].max_allowed) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    *result = gml_shape_defs[def_index].required_attributes[i].attribute;</span><br><span style="color: hsl(120, 100%, 40%);">+                 return AST_GEOLOC_VALIDATE_TOO_MANY_VARNAMES;</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 AST_GEOLOC_VALIDATE_SUCCESS;</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 *handle_gml_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+                e->command = "geoloc show gml_shape_defs";</span><br><span style="color: hsl(120, 100%, 40%);">+               e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+                 "Usage: geoloc show gml_shape_defs\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "       Show the GML Shape definitions.\n";</span><br><span style="color: hsl(120, 100%, 40%);">+         return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  case CLI_GENERATE:</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_cli(a->fd, "%-16s %-32s\n", "Shape", "Attributes name(min,max)");</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_cli(a->fd, "================ ===============================\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < ARRAY_LEN(gml_shape_defs); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          int j;</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_cli(a->fd, "%-16s", gml_shape_defs[i].shape_type);</span><br><span style="color: hsl(120, 100%, 40%);">+           for (j = 0; j < ARRAY_LEN(gml_shape_defs[i].required_attributes); j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (gml_shape_defs[i].required_attributes[j].attribute == NULL) {</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%);">+                     if (gml_shape_defs[i].required_attributes[j].max_allowed >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_cli(a->fd, " %s(%d,%d)", gml_shape_defs[i].required_attributes[j].attribute,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 gml_shape_defs[i].required_attributes[j].min_required,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        gml_shape_defs[i].required_attributes[j].max_allowed);</span><br><span style="color: hsl(120, 100%, 40%);">+                        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_cli(a->fd, " %s(%d,unl)", gml_shape_defs[i].required_attributes[j].attribute,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        gml_shape_defs[i].required_attributes[j].min_required);</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_cli(a->fd, "\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_cli(a->fd, "\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return CLI_SUCCESS;</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_cli_entry geoloc_gml_cli[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_CLI_DEFINE(handle_gml_show, "Show the GML Shape definitions"),</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%);">+int geoloc_gml_unload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_cli_unregister_multiple(geoloc_gml_cli, ARRAY_LEN(geoloc_gml_cli));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_gml_load(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_cli_register_multiple(geoloc_gml_cli, ARRAY_LEN(geoloc_gml_cli));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return AST_MODULE_LOAD_SUCCESS;</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%);">+int geoloc_gml_reload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/res/res_geolocation/geoloc_private.h b/res/res_geolocation/geoloc_private.h</span><br><span>new file mode 100644</span><br><span>index 0000000..2a5b6fb</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_private.h</span><br><span>@@ -0,0 +1,132 @@</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, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></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%);">+#ifndef GEOLOC_PRIVATE_H_</span><br><span style="color: hsl(120, 100%, 40%);">+#define GEOLOC_PRIVATE_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/config.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/sorcery.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/lock.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/res_geolocation.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONFIG_STR_TO_ENUM(_stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+static int _stem ## _str_to_enum(const char *str) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+      for (int i = 0; i < ARRAY_LEN(_stem ## _names); i++) { \</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ast_strings_equal(str, _stem ## _names[i])) { \</span><br><span style="color: hsl(120, 100%, 40%);">+                   return i; \</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 -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%);">+#define CONFIG_ENUM_HANDLER(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+static int _stem ## _handler(const struct aco_option *opt, struct ast_variable *var, void *obj) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_geoloc_ ## _object *_thisobject = obj; \</span><br><span style="color: hsl(120, 100%, 40%);">+   int enumval = _stem ## _str_to_enum(var->value); \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (enumval == -1) { \</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%);">+   _thisobject->_stem = enumval; \</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%);">+#define CONFIG_ENUM_TO_STR(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+static int _stem ## _to_str(const void *obj, const intptr_t *args, char **buf) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_geoloc_ ## _object *_thisobject = obj; \</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ARRAY_IN_BOUNDS(_thisobject->_stem, _stem ## _names)) { \</span><br><span style="color: hsl(120, 100%, 40%);">+             *buf = ast_strdup("none"); \</span><br><span style="color: hsl(120, 100%, 40%);">+        } else { \</span><br><span style="color: hsl(120, 100%, 40%);">+            *buf = ast_strdup(_stem ## _names[_thisobject->_stem]); \</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%);">+#define CONFIG_ENUM(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_STR_TO_ENUM(_stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_ENUM_HANDLER(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_ENUM_TO_STR(_object, _stem)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONFIG_VAR_LIST_HANDLER(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+static int _stem ## _handler(const struct aco_option *opt, struct ast_variable *var, void *obj) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_geoloc_ ## _object *_thisobject = obj; \</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_variable *new_var; \</span><br><span style="color: hsl(120, 100%, 40%);">+       char *item_string, *item, *item_name, *item_value; \</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ast_strlen_zero(var->value)) { return 0; } \</span><br><span style="color: hsl(120, 100%, 40%);">+   item_string = ast_strdupa(var->value); \</span><br><span style="color: hsl(120, 100%, 40%);">+   while ((item = ast_strsep(&item_string, ',', AST_STRSEP_ALL))) { \</span><br><span style="color: hsl(120, 100%, 40%);">+                item_name = ast_strsep(&item, '=', AST_STRSEP_ALL); \</span><br><span style="color: hsl(120, 100%, 40%);">+             item_value = ast_strsep(&item, '=', AST_STRSEP_ALL); \</span><br><span style="color: hsl(120, 100%, 40%);">+            new_var = ast_variable_new(item_name, item_value, ""); \</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_variable_list_append(&_thisobject->_stem, new_var); \</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%);">+#define CONFIG_VAR_LIST_DUP(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+static int _stem ## _dup(const void *obj, struct ast_variable **fields) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+       const struct ast_geoloc_ ## _object *_thisobject = obj; \</span><br><span style="color: hsl(120, 100%, 40%);">+     if (_thisobject->_stem) { \</span><br><span style="color: hsl(120, 100%, 40%);">+                *fields = ast_variables_dup(_thisobject->_stem); \</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%);">+#define CONFIG_VAR_LIST_TO_STR(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+static int _stem ## _to_str(const void *obj, const intptr_t *args, char **buf) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct ast_geoloc_ ## _object *_thisobject = obj; \</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_str *str = ast_variable_list_join(_thisobject->_stem, ",", "=", "\"", NULL); \</span><br><span style="color: hsl(120, 100%, 40%);">+       *buf = ast_strdup(ast_str_buffer(str)); \</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_free(str); \</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%);">+#define CONFIG_VAR_LIST(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST_HANDLER(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST_DUP(_object, _stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST_TO_STR(_object, _stem)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_config_load(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_config_reload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_config_unload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_civicaddr_load(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_civicaddr_unload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_civicaddr_reload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_gml_unload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_gml_load(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_gml_reload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_dialplan_unload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_dialplan_load(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_dialplan_reload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_channel_unload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_channel_load(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_channel_reload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_sorcery *geoloc_get_sorcery(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* GEOLOC_PRIVATE_H_ */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18068">change 18068</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/+/18068"/><meta itemprop="name" content="View Change"/></div></div>

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