<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>