<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18192">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_geolocation: Dialplan function initial commit<br><br>Also did more renames and added additional error checking<br>to ast_geoloc_eprofile_refresh_location().<br><br>Change-Id: Ibbf9bebaf510fd2fc1f535d17cda5d3bb1fa2009<br>---<br>M include/asterisk/res_geolocation.h<br>M main/config.c<br>M res/res_geolocation/geoloc_config.c<br>M res/res_geolocation/geoloc_datastore.c<br>M res/res_geolocation/geoloc_dialplan.c<br>M res/res_geolocation/geoloc_doc.xml<br>M res/res_geolocation/geoloc_eprofile.c<br>M res/res_geolocation/geoloc_private.h<br>M res/res_pjsip_geolocation.c<br>9 files changed, 590 insertions(+), 94 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/92/18192/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>index 80f1caf..139eb74 100644</span><br><span>--- a/include/asterisk/res_geolocation.h</span><br><span>+++ b/include/asterisk/res_geolocation.h</span><br><span>@@ -24,6 +24,8 @@</span><br><span> #include "asterisk/xml.h"</span><br><span> #include "asterisk/optional_api.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define AST_GEOLOC_INVALID_VALUE -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> enum ast_geoloc_pidf_element {</span><br><span> AST_PIDF_ELEMENT_NONE = 0,</span><br><span> AST_PIDF_ELEMENT_TUPLE,</span><br><span>@@ -38,11 +40,11 @@</span><br><span> AST_GEOLOC_FORMAT_URI,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-enum ast_geoloc_location_disposition {</span><br><span style="color: hsl(0, 100%, 40%);">- AST_GEOLOC_LOC_DISP_DISCARD = 0,</span><br><span style="color: hsl(0, 100%, 40%);">- AST_GEOLOC_LOC_DISP_APPEND,</span><br><span style="color: hsl(0, 100%, 40%);">- AST_GEOLOC_LOC_DISP_PREPEND,</span><br><span style="color: hsl(0, 100%, 40%);">- AST_GEOLOC_LOC_DISP_REPLACE,</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_geoloc_action {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_GEOLOC_ACTION_DISCARD = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_GEOLOC_ACTION_APPEND,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_GEOLOC_ACTION_PREPEND,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_GEOLOC_ACTION_REPLACE,</span><br><span> };</span><br><span> </span><br><span> struct ast_geoloc_location {</span><br><span>@@ -51,7 +53,7 @@</span><br><span> AST_STRING_FIELD(method);</span><br><span> );</span><br><span> enum ast_geoloc_format format;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *location_vars;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *location_info;</span><br><span> };</span><br><span> </span><br><span> struct ast_geoloc_profile {</span><br><span>@@ -60,12 +62,12 @@</span><br><span> AST_STRING_FIELD(location_reference);</span><br><span> );</span><br><span> enum ast_geoloc_pidf_element pidf_element;</span><br><span style="color: hsl(0, 100%, 40%);">- enum ast_geoloc_location_disposition location_disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_geoloc_action action;</span><br><span> int geolocation_routing;</span><br><span> int send_location;</span><br><span> struct ast_variable *location_refinement;</span><br><span> struct ast_variable *location_variables;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *usage_rules_vars;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *usage_rules;</span><br><span> };</span><br><span> </span><br><span> struct ast_geoloc_eprofile {</span><br><span>@@ -75,15 +77,15 @@</span><br><span> AST_STRING_FIELD(method);</span><br><span> );</span><br><span> enum ast_geoloc_pidf_element pidf_element;</span><br><span style="color: hsl(0, 100%, 40%);">- enum ast_geoloc_location_disposition location_disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_geoloc_action action;</span><br><span> int geolocation_routing;</span><br><span> int send_location;</span><br><span> enum ast_geoloc_format format;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *location_vars;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *location_info;</span><br><span> struct ast_variable *location_refinement;</span><br><span> struct ast_variable *location_variables;</span><br><span> struct ast_variable *effective_location;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *usage_rules_vars;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *usage_rules;</span><br><span> };</span><br><span> </span><br><span> /*!</span><br><span>@@ -143,13 +145,13 @@</span><br><span> const char *ast_geoloc_civicaddr_resolve_variable(const char *variable);</span><br><span> </span><br><span> enum ast_geoloc_validate_result {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_GEOLOC_VALIDATE_INVALID_VALUE = -1,</span><br><span> AST_GEOLOC_VALIDATE_SUCCESS = 0,</span><br><span> AST_GEOLOC_VALIDATE_MISSING_TYPE,</span><br><span> AST_GEOLOC_VALIDATE_INVALID_TYPE,</span><br><span> AST_GEOLOC_VALIDATE_INVALID_VARNAME,</span><br><span> AST_GEOLOC_VALIDATE_NOT_ENOUGH_VARNAMES,</span><br><span> AST_GEOLOC_VALIDATE_TOO_MANY_VARNAMES,</span><br><span style="color: hsl(0, 100%, 40%);">- AST_GEOLOC_VALIDATE_INVALID_VALUE,</span><br><span> };</span><br><span> </span><br><span> const char *ast_geoloc_validate_result_to_str(enum ast_geoloc_validate_result result);</span><br><span>@@ -176,6 +178,12 @@</span><br><span> enum ast_geoloc_validate_result ast_geoloc_gml_validate_varlist(const struct ast_variable *varlist,</span><br><span> const char **result);</span><br><span> </span><br><span 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 Geolocation datastore Functions</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span> * \brief Create a geoloc datastore from a profile name</span><br><span> *</span><br><span>@@ -195,13 +203,94 @@</span><br><span> struct ast_datastore *ast_geoloc_datastore_create_from_eprofile(</span><br><span> struct ast_geoloc_eprofile *eprofile);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Create an empty geoloc datastore.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param id An id to use for the datastore.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The datastore.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> struct ast_datastore *ast_geoloc_datastore_create(const char *id);</span><br><span 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 Retrieve a geoloc datastore's id.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ds The datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The datastore's id.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *ast_geoloc_datastore_get_id(struct ast_datastore *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%);">+ * \brief Add an eprofile to a datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ds The datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param eprofile The eprofile to add.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The number of eprofiles.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> int ast_geoloc_datastore_add_eprofile(struct ast_datastore *ds,</span><br><span> struct ast_geoloc_eprofile *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%);">+ * \brief Retrieves the number of eprofiles in the datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ds The datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The number of eprofiles.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> int ast_geoloc_datastore_size(struct ast_datastore *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%);">+ * \brief Sets the inheritance flag on the datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ds The datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param inherit 1 to allow the datastore to be inherited by other channels</span><br><span style="color: hsl(120, 100%, 40%);">+ * 0 to prevent the datastore to be inherited by other channels</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 if successful, -1 otherwise.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_geoloc_datastore_set_inheritance(struct ast_datastore *ds, int inherit);</span><br><span 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 Retrieve a specific eprofile from a datastore by index</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ds The datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ix The index</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The effective profile ao2 object with its reference count bumped.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> struct ast_geoloc_eprofile *ast_geoloc_datastore_get_eprofile(struct ast_datastore *ds, int ix);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Delete a specific eprofile from a datastore by index</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ds The datastore</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ix The index</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 if succesful, -1 otherwise.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_geoloc_datastore_delete_eprofile(struct ast_datastore *ds, int ix);</span><br><span 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 Retrieves the geoloc datastore from a channel, if any</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan Channel</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return datastore if found, NULL otherwise.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_datastore *ast_geoloc_datastore_find(struct ast_channel *chan);</span><br><span 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Geolocation Effective Profile Functions</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Allocate a new, empty effective profile.</span><br><span> *</span><br><span> * \param name The profile's name</span><br><span>@@ -250,4 +339,8 @@</span><br><span> */</span><br><span> int ast_geoloc_eprofile_refresh_location(struct ast_geoloc_eprofile *eprofile);</span><br><span> </span><br><span 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> #endif /* INCLUDE_ASTERISK_RES_GEOLOCATION_H_ */</span><br><span>diff --git a/main/config.c b/main/config.c</span><br><span>index 07925bd..dcf1b9a 100644</span><br><span>--- a/main/config.c</span><br><span>+++ b/main/config.c</span><br><span>@@ -746,8 +746,16 @@</span><br><span> </span><br><span> while ((item = ast_strsep_strict(&item_string, item_sep, quote, AST_STRSEP_ALL))) {</span><br><span> item_name = ast_strsep_strict(&item, nv_sep, quote, AST_STRSEP_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!item_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(new_list);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> item_value = ast_strsep_strict(&item, nv_sep, quote, AST_STRSEP_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!item_value) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(new_list);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> new_var = ast_variable_new(item_name, item_value, "");</span><br><span> if (!new_var) {</span><br><span>diff --git a/res/res_geolocation/geoloc_config.c b/res/res_geolocation/geoloc_config.c</span><br><span>index 309df22..2350463 100644</span><br><span>--- a/res/res_geolocation/geoloc_config.c</span><br><span>+++ b/res/res_geolocation/geoloc_config.c</span><br><span>@@ -38,7 +38,7 @@</span><br><span> "URI",</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const char * location_disposition_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const char * action_names[] = {</span><br><span> "discard",</span><br><span> "append",</span><br><span> "prepend",</span><br><span>@@ -46,13 +46,13 @@</span><br><span> };</span><br><span> </span><br><span> CONFIG_ENUM(location, format)</span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_VAR_LIST(location, location_vars)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST(location, location_info)</span><br><span> </span><br><span> static void geoloc_location_destructor(void *obj) {</span><br><span> struct ast_geoloc_location *location = obj;</span><br><span> </span><br><span> ast_string_field_free_memory(location);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(location->location_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(location->location_info);</span><br><span> }</span><br><span> </span><br><span> static void *geoloc_location_alloc(const char *name)</span><br><span>@@ -67,10 +67,10 @@</span><br><span> </span><br><span> </span><br><span> CONFIG_ENUM(profile, pidf_element)</span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_ENUM(profile, location_disposition)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_ENUM(profile, action)</span><br><span> CONFIG_VAR_LIST(profile, location_refinement)</span><br><span> CONFIG_VAR_LIST(profile, location_variables)</span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_VAR_LIST(profile, usage_rules_vars)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST(profile, usage_rules)</span><br><span> </span><br><span> </span><br><span> static void geoloc_profile_destructor(void *obj) {</span><br><span>@@ -79,7 +79,7 @@</span><br><span> ast_string_field_free_memory(profile);</span><br><span> ast_variables_destroy(profile->location_refinement);</span><br><span> ast_variables_destroy(profile->location_variables);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(profile->usage_rules_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(profile->usage_rules);</span><br><span> }</span><br><span> </span><br><span> static void *geoloc_profile_alloc(const char *name)</span><br><span>@@ -105,7 +105,7 @@</span><br><span> ast_log(LOG_ERROR, "Location '%s' must have a format\n", location_id);</span><br><span> return -1;</span><br><span> case AST_GEOLOC_FORMAT_CIVIC_ADDRESS:</span><br><span style="color: hsl(0, 100%, 40%);">- result = ast_geoloc_civicaddr_validate_varlist(location->location_vars, &failed);</span><br><span style="color: hsl(120, 100%, 40%);">+ result = ast_geoloc_civicaddr_validate_varlist(location->location_info, &failed);</span><br><span> if (result != AST_GEOLOC_VALIDATE_SUCCESS) {</span><br><span> ast_log(LOG_ERROR, "Location '%s' has invalid item '%s' in the location\n",</span><br><span> location_id, failed);</span><br><span>@@ -113,7 +113,7 @@</span><br><span> }</span><br><span> break;</span><br><span> case AST_GEOLOC_FORMAT_GML:</span><br><span style="color: hsl(0, 100%, 40%);">- result = ast_geoloc_gml_validate_varlist(location->location_vars, &failed);</span><br><span style="color: hsl(120, 100%, 40%);">+ result = ast_geoloc_gml_validate_varlist(location->location_info, &failed);</span><br><span> if (result != AST_GEOLOC_VALIDATE_SUCCESS) {</span><br><span> ast_log(LOG_ERROR, "%s for item '%s' in location '%s'\n",</span><br><span> ast_geoloc_validate_result_to_str(result), failed, location_id);</span><br><span>@@ -122,9 +122,9 @@</span><br><span> </span><br><span> break;</span><br><span> case AST_GEOLOC_FORMAT_URI:</span><br><span style="color: hsl(0, 100%, 40%);">- uri = ast_variable_find_in_list(location->location_vars, "URI");</span><br><span style="color: hsl(120, 100%, 40%);">+ uri = ast_variable_find_in_list(location->location_info, "URI");</span><br><span> if (!uri) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_str *str = ast_variable_list_join(location->location_vars, ",", "=", "\"", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *str = ast_variable_list_join(location->location_info, ",", "=", "\"", NULL);</span><br><span> </span><br><span> 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> location_id, format_names[AST_GEOLOC_FORMAT_URI], ast_str_buffer(str));</span><br><span>@@ -259,7 +259,7 @@</span><br><span> struct ast_str *str;</span><br><span> </span><br><span> ao2_lock(loc);</span><br><span style="color: hsl(0, 100%, 40%);">- str = ast_variable_list_join(loc->location_vars, ",", "=", "\"", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ str = ast_variable_list_join(loc->location_info, ",", "=", "\"", NULL);</span><br><span> if (!str) {</span><br><span> ao2_unlock(loc);</span><br><span> ao2_ref(loc, -1);</span><br><span>@@ -295,7 +295,7 @@</span><br><span> int using_regex = 0;</span><br><span> char *result = CLI_SUCCESS;</span><br><span> int ret = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- char *disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *action;</span><br><span> int count = 0;</span><br><span> </span><br><span> switch (cmd) {</span><br><span>@@ -352,14 +352,14 @@</span><br><span> for (; (profile = ao2_iterator_next(&iter)); ao2_ref(profile, -1)) {</span><br><span> ao2_lock(profile);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- location_disposition_to_str(profile, NULL, &disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+ action_to_str(profile, NULL, &action);</span><br><span> ast_cli(a->fd, "%-46.46s %-13s %-6s %-s\n",</span><br><span> ast_sorcery_object_get_id(profile),</span><br><span style="color: hsl(0, 100%, 40%);">- disposition,</span><br><span style="color: hsl(120, 100%, 40%);">+ action,</span><br><span> profile->send_location ? "yes" : "no",</span><br><span> profile->location_reference);</span><br><span> ao2_unlock(profile);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(action);</span><br><span> count++;</span><br><span> }</span><br><span> ao2_iterator_destroy(&iter);</span><br><span>@@ -428,7 +428,7 @@</span><br><span> </span><br><span> iter = ao2_iterator_init(sorted_container, AO2_ITERATOR_UNLINK);</span><br><span> for (; (profile = ao2_iterator_next(&iter)); ) {</span><br><span style="color: hsl(0, 100%, 40%);">- char *disposition = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *action = NULL;</span><br><span> struct ast_str *loc_str = NULL;</span><br><span> struct ast_str *refinement_str = NULL;</span><br><span> struct ast_str *variables_str = NULL;</span><br><span>@@ -437,14 +437,14 @@</span><br><span> ao2_ref(profile, -1);</span><br><span> </span><br><span> if (!ast_strlen_zero(eprofile->location_reference)) {</span><br><span style="color: hsl(0, 100%, 40%);">- loc_str = ast_variable_list_join(eprofile->location_vars, ",", "=", "\"", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ loc_str = ast_variable_list_join(eprofile->location_info, ",", "=", "\"", NULL);</span><br><span> resolved_str = ast_variable_list_join(eprofile->effective_location, ",", "=", "\"", NULL);</span><br><span> }</span><br><span> </span><br><span> refinement_str = ast_variable_list_join(eprofile->location_refinement, ",", "=", "\"", NULL);</span><br><span> variables_str = ast_variable_list_join(eprofile->location_variables, ",", "=", "\"", NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- location_disposition_to_str(eprofile, NULL, &disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+ action_to_str(eprofile, NULL, &action);</span><br><span> </span><br><span> ast_cli(a->fd,</span><br><span> "id: %-s\n"</span><br><span>@@ -458,7 +458,7 @@</span><br><span> "location_variables: %-s\n"</span><br><span> "effective_location: %-s\n\n",</span><br><span> eprofile->id,</span><br><span style="color: hsl(0, 100%, 40%);">- disposition,</span><br><span style="color: hsl(120, 100%, 40%);">+ action,</span><br><span> eprofile->send_location ? "yes" : "no",</span><br><span> pidf_element_names[eprofile->pidf_element],</span><br><span> S_OR(eprofile->location_reference, "<none>"),</span><br><span>@@ -469,7 +469,7 @@</span><br><span> S_COR(resolved_str, ast_str_buffer(resolved_str), "<none>"));</span><br><span> ao2_ref(eprofile, -1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(action);</span><br><span> ast_free(loc_str);</span><br><span> ast_free(refinement_str);</span><br><span> ast_free(variables_str);</span><br><span>@@ -573,8 +573,8 @@</span><br><span> ast_sorcery_object_field_register(geoloc_sorcery, "location", "type", "", OPT_NOOP_T, 0, 0);</span><br><span> ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "format", AST_GEOLOC_FORMAT_NONE,</span><br><span> format_handler, format_to_str, NULL, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "location", NULL,</span><br><span style="color: hsl(0, 100%, 40%);">- location_vars_handler, location_vars_to_str, location_vars_dup, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "location_info", NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+ location_info_handler, location_info_to_str, location_info_dup, 0, 0);</span><br><span> </span><br><span> ast_sorcery_apply_default(geoloc_sorcery, "profile", "config", "geolocation.conf,criteria=type=profile");</span><br><span> if (ast_sorcery_object_register(geoloc_sorcery, "profile", geoloc_profile_alloc, NULL, geoloc_profile_apply_handler)) {</span><br><span>@@ -589,12 +589,12 @@</span><br><span> pidf_element_handler, pidf_element_to_str, NULL, 0, 0);</span><br><span> ast_sorcery_object_field_register(geoloc_sorcery, "profile", "location_reference", "", OPT_STRINGFIELD_T,</span><br><span> 0, STRFLDSET(struct ast_geoloc_profile, location_reference));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "received_location_disposition", "discard",</span><br><span style="color: hsl(0, 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_custom(geoloc_sorcery, "profile", "action", "discard",</span><br><span style="color: hsl(120, 100%, 40%);">+ action_handler, action_to_str, NULL, 0, 0);</span><br><span> ast_sorcery_object_field_register(geoloc_sorcery, "profile", "send_location", "no",</span><br><span> OPT_BOOL_T, 1, FLDSET(struct ast_geoloc_profile, send_location));</span><br><span> ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "usage_rules", NULL,</span><br><span style="color: hsl(0, 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%);">+ usage_rules_handler, usage_rules_to_str, usage_rules_dup, 0, 0);</span><br><span> ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_refinement", NULL,</span><br><span> location_refinement_handler, location_refinement_to_str, location_refinement_dup, 0, 0);</span><br><span> ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_variables", NULL,</span><br><span>diff --git a/res/res_geolocation/geoloc_datastore.c b/res/res_geolocation/geoloc_datastore.c</span><br><span>index 17e2847..e920659 100644</span><br><span>--- a/res/res_geolocation/geoloc_datastore.c</span><br><span>+++ b/res/res_geolocation/geoloc_datastore.c</span><br><span>@@ -19,6 +19,7 @@</span><br><span> #include "asterisk.h"</span><br><span> #include "asterisk/astobj2.h"</span><br><span> #include "asterisk/datastore.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/channel.h"</span><br><span> #include "asterisk/res_geolocation.h"</span><br><span> #include "asterisk/vector.h"</span><br><span> #include "geoloc_private.h"</span><br><span>@@ -41,11 +42,58 @@</span><br><span> ast_free(eds);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void *geoloc_datastore_duplicate(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct eprofiles_datastore *in_eds = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct eprofiles_datastore *out_eds;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int eprofile_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ out_eds = ast_calloc(1, sizeof(*out_eds));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!out_eds) {</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%);">+ rc = AST_VECTOR_INIT(&out_eds->eprofiles, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(out_eds);</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%);">+ eprofile_count = AST_VECTOR_SIZE(&in_eds->eprofiles);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < eprofile_count; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = AST_VECTOR_APPEND(&out_eds->eprofiles, ao2_bump(AST_VECTOR_GET(&in_eds->eprofiles, i)));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ geoloc_datastore_free(out_eds);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return out_eds;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct ast_datastore_info geoloc_datastore_info = {</span><br><span> .type = GEOLOC_DS_TYPE,</span><br><span style="color: hsl(0, 100%, 40%);">- .destroy = geoloc_datastore_free</span><br><span style="color: hsl(120, 100%, 40%);">+ .destroy = geoloc_datastore_free,</span><br><span style="color: hsl(120, 100%, 40%);">+ .duplicate = geoloc_datastore_duplicate,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define IS_GEOLOC_DS(_ds) (_ds && _ds->data && ast_strings_equal(_ds->info->type, GEOLOC_DS_TYPE))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const char *ast_geoloc_datastore_get_id(struct ast_datastore *ds)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct eprofiles_datastore *eds = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!IS_GEOLOC_DS(ds)) {</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%);">+ eds = (struct eprofiles_datastore *)ds->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return eds->id;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct ast_datastore *ast_geoloc_datastore_create(const char *id)</span><br><span> {</span><br><span> struct ast_datastore *ds = NULL;</span><br><span>@@ -88,12 +136,12 @@</span><br><span> struct eprofiles_datastore *eds = NULL;</span><br><span> int rc = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!ds || !ast_strings_equal(ds->info->type, GEOLOC_DS_TYPE) || !ds->data || !eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!IS_GEOLOC_DS(ds) || !eprofile) {</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span> eds = ds->data;</span><br><span style="color: hsl(0, 100%, 40%);">- rc = AST_VECTOR_APPEND(&eds->eprofiles, eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = AST_VECTOR_APPEND(&eds->eprofiles, ao2_bump(eprofile));</span><br><span> if (rc != 0) {</span><br><span> ast_log(LOG_ERROR, "Couldn't add eprofile '%s' to geoloc datastore '%s'\n", eprofile->id, eds->id);</span><br><span> }</span><br><span>@@ -105,7 +153,7 @@</span><br><span> {</span><br><span> struct eprofiles_datastore *eds = NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!ds || !ast_strings_equal(ds->info->type, GEOLOC_DS_TYPE) || !ds->data) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!IS_GEOLOC_DS(ds)) {</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span>@@ -114,12 +162,21 @@</span><br><span> return AST_VECTOR_SIZE(&eds->eprofiles);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int ast_geoloc_datastore_set_inheritance(struct ast_datastore *ds, int inherit)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!IS_GEOLOC_DS(ds)) {</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%);">+ ds->inheritance = inherit ? DATASTORE_INHERIT_FOREVER : 0;</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> struct ast_geoloc_eprofile *ast_geoloc_datastore_get_eprofile(struct ast_datastore *ds, int ix)</span><br><span> {</span><br><span> struct eprofiles_datastore *eds = NULL;</span><br><span> struct ast_geoloc_eprofile *eprofile;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!ds || !ast_strings_equal(ds->info->type, GEOLOC_DS_TYPE) || !ds->data) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!IS_GEOLOC_DS(ds)) {</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span>@@ -133,6 +190,29 @@</span><br><span> return ao2_bump(eprofile);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_datastore *ast_geoloc_datastore_find(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_channel_datastore_find(chan, &geoloc_datastore_info, 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%);">+int ast_geoloc_datastore_delete_eprofile(struct ast_datastore *ds, int ix)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct eprofiles_datastore *eds = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!IS_GEOLOC_DS(ds)) {</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%);">+ eds = ds->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ix >= AST_VECTOR_SIZE(&eds->eprofiles)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_VECTOR_REMOVE(&eds->eprofiles, ix, 1);</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> struct ast_datastore *ast_geoloc_datastore_create_from_eprofile(</span><br><span> struct ast_geoloc_eprofile *eprofile)</span><br><span> {</span><br><span>diff --git a/res/res_geolocation/geoloc_dialplan.c b/res/res_geolocation/geoloc_dialplan.c</span><br><span>index 776441c..5f5e507 100644</span><br><span>--- a/res/res_geolocation/geoloc_dialplan.c</span><br><span>+++ b/res/res_geolocation/geoloc_dialplan.c</span><br><span>@@ -19,20 +19,297 @@</span><br><span> #include "asterisk.h"</span><br><span> #include "asterisk/config.h"</span><br><span> #include "asterisk/cli.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/channel.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/pbx.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/strings.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/app.h"</span><br><span> #include "asterisk/res_geolocation.h"</span><br><span> #include "geoloc_private.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void varlist_to_str(struct ast_variable *list, struct ast_str** buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *var = list;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (; var; var = var->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s=\"%s\"%s", var->name, var->value, var->next ? "," : "");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int geoloc_profile_read(struct ast_channel *chan,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *cmd, char *data, struct ast_str **buf, ssize_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *parsed_data = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+ int index = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_datastore *ds;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_eprofile *eprofile = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ int profile_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(field);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(index);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check for zero arguments */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(parsed_data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STANDARD_APP_ARGS(args, parsed_data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(args.field)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Cannot call without a field to query\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(args.index)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (sscanf(args.index, "%30d", &index) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: profile_index '%s' is invalid\n", cmd, args.index);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ds = ast_geoloc_datastore_find(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ds) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_NOTICE, "%s: There are no geoloc profiles on this channel\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ profile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (index < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strings_equal(args.field, "count")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%d", profile_count);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "inheritable")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%d", ds->inheritance ? 1 : 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", cmd, args.field);</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%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (index >= profile_count) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: index %d is out of range 0 -> %d\n", cmd, index, profile_count);</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%);">+ eprofile = ast_geoloc_datastore_get_eprofile(ds, index);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Internal Error. Profile at index %d couldn't be retrieved.\n", cmd, index);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strings_equal(args.field, "id")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", eprofile->id);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "location_reference")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", eprofile->location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "method")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", eprofile->method);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "geolocation_routing")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", eprofile->geolocation_routing ? "yes" : "no");</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "send_location")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", eprofile->send_location ? "yes" : "no");</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "action")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", geoloc_action_to_name(eprofile->action));</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "format")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", geoloc_format_to_name(eprofile->format));</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "pidf_element")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", geoloc_pidf_element_to_name(eprofile->pidf_element));</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "location_info")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ varlist_to_str(eprofile->location_info, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "location_refinement")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ varlist_to_str(eprofile->location_refinement, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "location_variables")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ varlist_to_str(eprofile->location_variables, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "effective_location")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ varlist_to_str(eprofile->effective_location, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "usage_rules")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ varlist_to_str(eprofile->usage_rules, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", cmd, args.field);</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%);">+ ao2_ref(eprofile, -1);</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 TEST_ENUM_VALUE(_cmd, _ep, _field, _value) \</span><br><span style="color: hsl(120, 100%, 40%);">+({ \</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_geoloc_ ## _field v; \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!_ep) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Field %s requires a valid index\n", _cmd, #_field); \</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%);">+ v = geoloc_ ## _field ## _str_to_enum(_value); \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (v == AST_GEOLOC_INVALID_VALUE) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: %s '%s' is invalid\n", _cmd, #_field, value); \</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%);">+ _ep->_field = v; \</span><br><span 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 TEST_VARLIST(_cmd, _ep, _field, _value) \</span><br><span style="color: hsl(120, 100%, 40%);">+({ \</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *_list; \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!_ep) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Field %s requires a valid index\n", _cmd, #_field); \</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%);">+ _list = ast_variable_list_from_string(_value, ",", "=", "\"" ); \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!_list) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: %s '%s' is malformed or contains invalid values", _cmd, #_field, _value); \</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%);">+ ast_variables_destroy(_ep->_field); \</span><br><span style="color: hsl(120, 100%, 40%);">+ _ep->_field = _list; \</span><br><span 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_write(struct ast_channel *chan, const char *cmd, char *data,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *parsed_data = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_datastore *ds;</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_geoloc_eprofile *, eprofile, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ int profile_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int index = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(field);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(index);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check for zero arguments */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(parsed_data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STANDARD_APP_ARGS(args, parsed_data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(args.field)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Cannot call without a field to set\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(args.index)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (sscanf(args.index, "%30d", &index) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: profile_index '%s' is invalid\n", cmd, args.index);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ds = ast_geoloc_datastore_find(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ds) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "%s: There are no geoloc profiles on this channel\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ profile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (index >= 0 && index < profile_count) {</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile = ast_geoloc_datastore_get_eprofile(ds, index);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Internal Error. Profile at index %d couldn't be retrieved.\n", cmd, index);</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%);">+ } else if (index >= profile_count) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: index %d is out of range 0 -> %d\n", cmd, index, profile_count);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strings_equal(args.field, "inheritable")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_geoloc_datastore_set_inheritance(ds, ast_true(value));</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Field '%s' is not valid or requires a profile index\n", cmd, args.field);</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%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strings_equal(args.field, "all")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ char *v = ast_strdupa(value);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(ast_strip_quoted(v, "'\"", "'\""))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_geoloc_datastore_delete_eprofile(ds, index);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Only an empty string is valid for field 'all'\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "location_reference")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_location *loc = ast_geoloc_get_location(value);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(loc);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!loc) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Location reference '%s' doesn't exist\n", cmd, value);</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%);">+ ast_string_field_set(eprofile, location_reference, value);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "method")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(eprofile, method, value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "geolocation_routing")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->geolocation_routing = ast_true(value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "send_location")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->send_location = ast_true(value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "action")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ TEST_ENUM_VALUE(cmd, eprofile, action, value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "format")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ TEST_ENUM_VALUE(cmd, eprofile, format, value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "pidf_element")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ TEST_ENUM_VALUE(cmd, eprofile, pidf_element, value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "location_info")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ TEST_VARLIST(cmd, eprofile, location_info, value);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "location_refinement")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ TEST_VARLIST(cmd, eprofile, location_refinement, value);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "location_variables")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ TEST_VARLIST(cmd, eprofile, location_variables, value);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "effective_location")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ TEST_VARLIST(cmd, eprofile, effective_location, value);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "usage_rules")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ TEST_VARLIST(cmd, eprofile, usage_rules, value);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", cmd, args.field);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_geoloc_eprofile_refresh_location(eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_custom_function geoloc_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "GEOLOC_PROFILE",</span><br><span style="color: hsl(120, 100%, 40%);">+ .read2 = geoloc_profile_read,</span><br><span style="color: hsl(120, 100%, 40%);">+ .write = geoloc_profile_write,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int geoloc_dialplan_unload(void)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_custom_function_unregister(&geoloc_function);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return AST_MODULE_LOAD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span> int geoloc_dialplan_load(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return AST_MODULE_LOAD_SUCCESS;</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 = ast_custom_function_register(&geoloc_function);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return res == 0 ? AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;</span><br><span> }</span><br><span> </span><br><span> int geoloc_dialplan_reload(void)</span><br><span> {</span><br><span> return AST_MODULE_LOAD_SUCCESS;</span><br><span> }</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>index 8322585..45f1fc9 100644</span><br><span>--- a/res/res_geolocation/geoloc_doc.xml</span><br><span>+++ b/res/res_geolocation/geoloc_doc.xml</span><br><span>@@ -41,8 +41,8 @@</span><br><span> </enumlist></span><br><span> </description></span><br><span> </configOption></span><br><span style="color: hsl(0, 100%, 40%);">- <configOption name="location" default=""></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis>Location Data</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <configOption name="location_info" default=""></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis>Location information</synopsis></span><br><span> <description></span><br><span> <para>The contents of this parameter are specific to the</span><br><span> specification type.</para></span><br><span>@@ -89,7 +89,7 @@</span><br><span> <para>xxxx</para></span><br><span> </description></span><br><span> </configOption></span><br><span style="color: hsl(0, 100%, 40%);">- <configOption name="received_location_disposition" default="no"></span><br><span style="color: hsl(120, 100%, 40%);">+ <configOption name="action" default="no"></span><br><span> <synopsis>Determine whether the location information supplied to a</span><br><span> channel should be used</synopsis></span><br><span> <description></span><br><span>@@ -134,5 +134,18 @@</span><br><span> </configObject></span><br><span> </configFile></span><br><span> </configInfo></span><br><span style="color: hsl(120, 100%, 40%);">+ <function name="GEOLOC_PROFILE" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ Get or Set a field in a geolocation profile</span><br><span style="color: hsl(120, 100%, 40%);">+ </synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="field" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The profile field to operate on.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="index" required="false"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The index of the profile to operate on. Not required for the special fields.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ </function></span><br><span> </docs></span><br><span> </span><br><span>diff --git a/res/res_geolocation/geoloc_eprofile.c b/res/res_geolocation/geoloc_eprofile.c</span><br><span>index 2fecd62..0c09d9d 100644</span><br><span>--- a/res/res_geolocation/geoloc_eprofile.c</span><br><span>+++ b/res/res_geolocation/geoloc_eprofile.c</span><br><span>@@ -32,15 +32,29 @@</span><br><span> </span><br><span> static struct ast_sorcery *geoloc_sorcery;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define DUP_VARS(_dest, _source) \</span><br><span style="color: hsl(120, 100%, 40%);">+({ \</span><br><span style="color: hsl(120, 100%, 40%);">+ int _rc = 0; \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (_source) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *_vars = ast_variables_dup(_source); \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!_vars) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ _rc = -1; \</span><br><span style="color: hsl(120, 100%, 40%);">+ } else { \</span><br><span style="color: hsl(120, 100%, 40%);">+ _dest = _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%);">+ (_rc); \</span><br><span style="color: hsl(120, 100%, 40%);">+})</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void geoloc_effective_profile_destructor(void *obj) {</span><br><span> struct ast_geoloc_eprofile *eprofile = obj;</span><br><span> </span><br><span> ast_string_field_free_memory(eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(eprofile->location_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->location_info);</span><br><span> ast_variables_destroy(eprofile->location_refinement);</span><br><span> ast_variables_destroy(eprofile->location_variables);</span><br><span> ast_variables_destroy(eprofile->effective_location);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(eprofile->usage_rules_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->usage_rules);</span><br><span> }</span><br><span> </span><br><span> struct ast_geoloc_eprofile *ast_geoloc_eprofile_alloc(const char *name)</span><br><span>@@ -57,7 +71,14 @@</span><br><span> int ast_geoloc_eprofile_refresh_location(struct ast_geoloc_eprofile *eprofile)</span><br><span> {</span><br><span> struct ast_geoloc_location *loc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *temp_locinfo = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *temp_effloc = NULL;</span><br><span> struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> if (!ast_strlen_zero(eprofile->location_reference)) {</span><br><span> loc = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", eprofile->location_reference);</span><br><span>@@ -68,45 +89,46 @@</span><br><span> }</span><br><span> </span><br><span> eprofile->format = loc->format;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(eprofile->location_vars);</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_vars = loc->location_vars ? ast_variables_dup(loc->location_vars) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = DUP_VARS(temp_locinfo, loc->location_info);</span><br><span> ao2_ref(loc, -1);</span><br><span style="color: hsl(0, 100%, 40%);">- loc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != 0) {</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%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ temp_locinfo = eprofile->location_info;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(eprofile->effective_location);</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->effective_location = eprofile->location_vars ? ast_variables_dup(eprofile->location_vars) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = DUP_VARS(temp_effloc, temp_locinfo);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(temp_locinfo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> if (eprofile->location_refinement) {</span><br><span> for (var = eprofile->location_refinement; var; var = var->next) {</span><br><span> struct ast_variable *newvar = ast_variable_new(var->name, var->value, "");</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_variable_list_replace(&eprofile->effective_location, newvar)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variable_list_append(&eprofile->effective_location, newvar);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!newvar) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(temp_locinfo);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(temp_effloc);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_variable_list_replace(&temp_effloc, newvar)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variable_list_append(&temp_effloc, newvar);</span><br><span> }</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->location_info);</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->location_info = temp_locinfo;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->effective_location);</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->effective_location = temp_effloc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define DUP_VARS(_dest, _source) \</span><br><span style="color: hsl(0, 100%, 40%);">-({ \</span><br><span style="color: hsl(0, 100%, 40%);">- int _rc = 0; \</span><br><span style="color: hsl(0, 100%, 40%);">- if (_source) { \</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *_vars = ast_variables_dup(_source); \</span><br><span style="color: hsl(0, 100%, 40%);">- if (!_vars) { \</span><br><span style="color: hsl(0, 100%, 40%);">- _rc = -1; \</span><br><span style="color: hsl(0, 100%, 40%);">- } else { \</span><br><span style="color: hsl(0, 100%, 40%);">- _dest = _vars; \</span><br><span style="color: hsl(0, 100%, 40%);">- } \</span><br><span style="color: hsl(0, 100%, 40%);">- } \</span><br><span style="color: hsl(0, 100%, 40%);">- (_rc); \</span><br><span style="color: hsl(0, 100%, 40%);">-})</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_geoloc_effective_profile *ast_geoloc_eprofile_create_from_profile(struct ast_geoloc_profile *profile)</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_geoloc_eprofile *ast_geoloc_eprofile_create_from_profile(struct ast_geoloc_profile *profile)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_geoloc_effective_profile *eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_eprofile *eprofile;</span><br><span> const char *profile_id;</span><br><span> int rc = 0;</span><br><span> </span><br><span>@@ -131,7 +153,7 @@</span><br><span> rc = DUP_VARS(eprofile->location_variables, profile->location_variables);</span><br><span> }</span><br><span> if (rc == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- rc = DUP_VARS(eprofile->usage_rules_vars, profile->usage_rules_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = DUP_VARS(eprofile->usage_rules, profile->usage_rules);</span><br><span> }</span><br><span> if (rc != 0) {</span><br><span> ao2_unlock(profile);</span><br><span>@@ -139,7 +161,7 @@</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_disposition = profile->location_disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->action = profile->action;</span><br><span> eprofile->send_location = profile->send_location;</span><br><span> ao2_unlock(profile);</span><br><span> </span><br><span>@@ -176,7 +198,7 @@</span><br><span> }</span><br><span> </span><br><span> eprofile->format = AST_GEOLOC_FORMAT_URI;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_vars = ast_variable_new("URI", local_uri, "");</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->location_info = ast_variable_new("URI", local_uri, "");</span><br><span> </span><br><span> return eprofile;</span><br><span> }</span><br><span>@@ -227,8 +249,8 @@</span><br><span> </span><br><span> location_str = ast_xml_get_text(location_info);</span><br><span> duped = ast_strdupa(location_str);</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_vars = ast_variable_list_from_string(duped, ",", "=", "\"");</span><br><span style="color: hsl(0, 100%, 40%);">- if (!eprofile->location_vars) {</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->location_info = ast_variable_list_from_string(duped, ",", "=", "\"");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!eprofile->location_info) {</span><br><span> ao2_ref(eprofile, -1);</span><br><span> ast_log(LOG_ERROR, "%s: Unable to create location variables from '%s'\n", reference_string, location_str);</span><br><span> return NULL;</span><br><span>@@ -236,7 +258,7 @@</span><br><span> </span><br><span> usage_str = ast_xml_get_text(usage_rules);</span><br><span> duped = ast_strdupa(usage_str);</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->usage_rules_vars = ast_variable_list_from_string(duped, ",", "=", "\"");</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->usage_rules = ast_variable_list_from_string(duped, ",", "=", "\"");</span><br><span> </span><br><span> method_str = ast_xml_get_text(method);</span><br><span> ast_string_field_set(eprofile, method, method_str);</span><br><span>@@ -382,8 +404,8 @@</span><br><span> eprofile = ast_geoloc_eprofile_create_from_uri("http://some_uri&a=b", __func__);</span><br><span> ast_test_validate(test, eprofile != NULL);</span><br><span> ast_test_validate(test, eprofile->format == AST_GEOLOC_FORMAT_URI);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_test_validate(test, eprofile->location_vars != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- uri = ast_variable_find_in_list(eprofile->location_vars, "URI");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, eprofile->location_info != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ uri = ast_variable_find_in_list(eprofile->location_info, "URI");</span><br><span> ast_test_validate(test, uri != NULL);</span><br><span> ast_test_validate(test, strcmp(uri, "http://some_uri&a=b") == 0);</span><br><span> </span><br><span>@@ -426,13 +448,13 @@</span><br><span> ast_test_validate(test, eprofile->format == format);</span><br><span> ast_test_validate(test, ast_strings_equal(eprofile->method, method));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- str = ast_variable_list_join(eprofile->location_vars, ",", "=", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ str = ast_variable_list_join(eprofile->location_info, ",", "=", NULL, NULL);</span><br><span> ast_test_validate(test, str != NULL);</span><br><span> ast_test_status_update(test, "location_vars: %s\n", ast_str_buffer(str));</span><br><span> ast_test_validate(test, ast_strings_equal(ast_str_buffer(str), location));</span><br><span> ast_free(str);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- str = ast_variable_list_join(eprofile->usage_rules_vars, ",", "=", "'", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ str = ast_variable_list_join(eprofile->usage_rules, ",", "=", "'", NULL);</span><br><span> ast_test_validate(test, str != NULL);</span><br><span> ast_test_status_update(test, "usage_rules: %s\n", ast_str_buffer(str));</span><br><span> ast_test_validate(test, ast_strings_equal(ast_str_buffer(str), usage));</span><br><span>diff --git a/res/res_geolocation/geoloc_private.h b/res/res_geolocation/geoloc_private.h</span><br><span>index c5ea981..18b51a7 100644</span><br><span>--- a/res/res_geolocation/geoloc_private.h</span><br><span>+++ b/res/res_geolocation/geoloc_private.h</span><br><span>@@ -28,11 +28,11 @@</span><br><span> #define CONFIG_STR_TO_ENUM_DECL(_stem) int geoloc_ ## _stem ## _str_to_enum(const char *str);</span><br><span> CONFIG_STR_TO_ENUM_DECL(pidf_element)</span><br><span> CONFIG_STR_TO_ENUM_DECL(format);</span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_STR_TO_ENUM_DECL(location_disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_STR_TO_ENUM_DECL(action);</span><br><span> #define GEOLOC_ENUM_TO_NAME_DECL(_stem) const char * geoloc_ ## _stem ## _to_name(int ix);</span><br><span> GEOLOC_ENUM_TO_NAME_DECL(pidf_element)</span><br><span> GEOLOC_ENUM_TO_NAME_DECL(format);</span><br><span style="color: hsl(0, 100%, 40%);">-GEOLOC_ENUM_TO_NAME_DECL(location_disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+GEOLOC_ENUM_TO_NAME_DECL(action);</span><br><span> </span><br><span> </span><br><span> #define CONFIG_STR_TO_ENUM(_stem) \</span><br><span>diff --git a/res/res_pjsip_geolocation.c b/res/res_pjsip_geolocation.c</span><br><span>index cd8ba79..8e3156b 100644</span><br><span>--- a/res/res_pjsip_geolocation.c</span><br><span>+++ b/res/res_pjsip_geolocation.c</span><br><span>@@ -145,7 +145,7 @@</span><br><span> "%s: Couldn't allocate a geoloc datastore\n", session_name);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (config_profile->location_disposition == AST_GEOLOC_LOC_DISP_DISCARD) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config_profile->action == AST_GEOLOC_ACTION_DISCARD) {</span><br><span> ast_trace(4, "%s: Profile '%s' location_disposition is 'discard' so "</span><br><span> "discarding Geolocation: " PJSTR_PRINTF_SPEC, session_name,</span><br><span> ast_sorcery_object_get_id(config_profile),</span><br><span>@@ -164,17 +164,17 @@</span><br><span> config_eprofile->id);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_lock(channel);</span><br><span> ast_channel_datastore_add(channel, ds);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_unlock(channel);</span><br><span> /*</span><br><span style="color: hsl(0, 100%, 40%);">- * We gave our eprofile reference to the datastore and the</span><br><span style="color: hsl(0, 100%, 40%);">- * datastore to the channel so don't let RAII_VAR clean them up.</span><br><span style="color: hsl(120, 100%, 40%);">+ * We gave the datastore to the channel so don't let RAII_VAR clean it up.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- config_eprofile = NULL;</span><br><span> ds = NULL;</span><br><span> </span><br><span> SCOPE_EXIT_RTN_VALUE(0, "%s: Added geoloc datastore with 1 eprofile\n",</span><br><span> session_name);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (config_profile->location_disposition == AST_GEOLOC_LOC_DISP_PREPEND) {</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (config_profile->action == AST_GEOLOC_ACTION_PREPEND) {</span><br><span> ast_trace(4, "%s: Profile '%s' location_disposition is 'prepend' so "</span><br><span> "adding to datastore first", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span> </span><br><span>@@ -190,16 +190,17 @@</span><br><span> "%s: Couldn't add eprofile '%s' to datastore\n", session_name,</span><br><span> config_eprofile->id);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- config_eprofile = NULL;</span><br><span> </span><br><span> if (!geoloc_hdr) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_lock(channel);</span><br><span> ast_channel_datastore_add(channel, ds);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_unlock(channel);</span><br><span> ds = NULL;</span><br><span> </span><br><span> SCOPE_EXIT_RTN_VALUE(0, "%s: No Geolocation header so just adding config profile "</span><br><span> "'%s' to datastore\n", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (config_profile->location_disposition == AST_GEOLOC_LOC_DISP_REPLACE) {</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (config_profile->action == AST_GEOLOC_ACTION_REPLACE) {</span><br><span> if (geoloc_hdr) {</span><br><span> ast_trace(4, "%s: Profile '%s' location_disposition is 'replace' so "</span><br><span> "we don't need to do anything with the configured profile", session_name,</span><br><span>@@ -275,19 +276,19 @@</span><br><span> </span><br><span> eprofile = ast_geoloc_eprofile_create_from_pidf(incoming_doc, session_name);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_disposition = config_profile->location_disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->action = config_profile->action;</span><br><span> eprofile->send_location = config_profile->send_location;</span><br><span> </span><br><span> ast_trace(4, "Processing URI '%s'. Adding to datastore\n", geoloc_uri);</span><br><span> rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(eprofile, -1);</span><br><span> if (rc != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(eprofile, -1);</span><br><span> ast_log(LOG_WARNING, "%s: Unable to add effective profile for URI '%s' to datastore. Skipping\n",</span><br><span> session_name, geoloc_uri);</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (config_profile->location_disposition == AST_GEOLOC_LOC_DISP_APPEND) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config_profile->action == AST_GEOLOC_ACTION_APPEND) {</span><br><span> ast_trace(4, "%s: Profile '%s' location_disposition is 'prepend' so "</span><br><span> "adding to datastore first", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span> </span><br><span>@@ -313,7 +314,9 @@</span><br><span> session_name);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_lock(channel);</span><br><span> ast_channel_datastore_add(channel, ds);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_unlock(channel);</span><br><span> ds = NULL;</span><br><span> </span><br><span> SCOPE_EXIT_RTN_VALUE(0, "%s: Added geoloc datastore with %" PRIu64 " eprofiles\n",</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18192">change 18192</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/+/18192"/><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: Ibbf9bebaf510fd2fc1f535d17cda5d3bb1fa2009 </div>
<div style="display:none"> Gerrit-Change-Number: 18192 </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>