res_geolocation: Add two new options to GEOLOC_PROFILE

Added an 'a' option to the GEOLOC_PROFILE function to allow
variable lists like location_info_refinement to be appended
to instead of replacing the entire list.

Added an 'r' option to the GEOLOC_PROFILE function to resolve all
variables before a read operation and after a Set operation.

Added a few missing parameters to the ones allowed for writing
with GEOLOC_PROFILE.

Fixed a bug where calling GEOLOC_PROFILE to read a parameter
might actually update the profile object.

Cleaned up XML documentation a bit.

ASTERISK-30190

Change-Id: I75f541db43345509a2e86225bfa4cf8e242e5b6c
pull/30/head
George Joseph 3 years ago committed by Friendly Automation
parent b221f0f86a
commit bc6061bc5c

@ -40,3 +40,10 @@ a profile object for simple scenarios where the location
information isn't common with any other profiles. This is information isn't common with any other profiles. This is
mutually exclusive with setting location_reference on the mutually exclusive with setting location_reference on the
profile. profile.
Added an 'a' option to the GEOLOC_PROFILE function to allow
variable lists like location_info_refinement to be appended
to instead of replacing the entire list.
Added an 'r' option to the GEOLOC_PROFILE function to resolve all
variables before a read operation and after a Set operation.

@ -317,6 +317,15 @@ struct ast_datastore *ast_geoloc_datastore_find(struct ast_channel *chan);
*/ */
struct ast_geoloc_eprofile *ast_geoloc_eprofile_alloc(const char *name); struct ast_geoloc_eprofile *ast_geoloc_eprofile_alloc(const char *name);
/*!
* \brief Duplicate an effective profile.
*
* \param src The eprofile to duplicate.
*
* \return The duplicated effective profile ao2 object.
*/
struct ast_geoloc_eprofile *ast_geoloc_eprofile_dup(struct ast_geoloc_eprofile *src);
/*! /*!
* \brief Allocate a new effective profile from an existing profile. * \brief Allocate a new effective profile from an existing profile.
* *

@ -25,7 +25,6 @@
#include "asterisk/strings.h" #include "asterisk/strings.h"
#include "asterisk/utils.h" #include "asterisk/utils.h"
#include "asterisk/app.h" #include "asterisk/app.h"
#include "asterisk/res_geolocation.h"
#include "geoloc_private.h" #include "geoloc_private.h"
static void varlist_to_str(struct ast_variable *list, struct ast_str** buf, size_t len) static void varlist_to_str(struct ast_variable *list, struct ast_str** buf, size_t len)
@ -37,20 +36,52 @@ static void varlist_to_str(struct ast_variable *list, struct ast_str** buf, size
} }
} }
#define RESOLVE_FOR_READ(_param) \
({ \
if (ast_test_flag(&opts, OPT_GEOLOC_RESOLVE)) { \
struct ast_variable *resolved = geoloc_eprofile_resolve_varlist( \
eprofile->_param, eprofile->location_variables, chan); \
if (!resolved) { \
ast_log(LOG_ERROR, "%s: Unable to resolve " #_param "\n", chan_name); \
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3"); \
return 0; \
} \
varlist_to_str(resolved, buf, len); \
ast_variables_destroy(resolved); \
} else { \
varlist_to_str(eprofile->_param, buf, len); \
} \
})
enum my_app_option_flags {
OPT_GEOLOC_RESOLVE = (1 << 0),
OPT_GEOLOC_APPEND = (1 << 1),
};
AST_APP_OPTIONS(action_options, {
AST_APP_OPTION('r', OPT_GEOLOC_RESOLVE),
AST_APP_OPTION('a', OPT_GEOLOC_APPEND),
});
static int geoloc_profile_read(struct ast_channel *chan, static int geoloc_profile_read(struct ast_channel *chan,
const char *cmd, char *data, struct ast_str **buf, ssize_t len) const char *cmd, char *data, struct ast_str **buf, ssize_t len)
{ {
char *parsed_data = ast_strdupa(data); char *parsed_data = ast_strdupa(data);
const char *chan_name = ast_channel_name(chan);
struct ast_datastore *ds; struct ast_datastore *ds;
struct ast_geoloc_eprofile *orig_eprofile = NULL;
struct ast_geoloc_eprofile *eprofile = NULL; struct ast_geoloc_eprofile *eprofile = NULL;
struct ast_flags opts = { 0, };
AST_DECLARE_APP_ARGS(args, AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(field); AST_APP_ARG(field);
AST_APP_ARG(options);
); );
/* Check for zero arguments */ /* Check for zero arguments */
if (ast_strlen_zero(parsed_data)) { if (ast_strlen_zero(parsed_data)) {
ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", cmd); ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", chan_name);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1"); pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1");
return 0; return 0;
} }
@ -58,25 +89,45 @@ static int geoloc_profile_read(struct ast_channel *chan,
AST_STANDARD_APP_ARGS(args, parsed_data); AST_STANDARD_APP_ARGS(args, parsed_data);
if (ast_strlen_zero(args.field)) { if (ast_strlen_zero(args.field)) {
ast_log(LOG_ERROR, "%s: Cannot call without a field to query\n", cmd); ast_log(LOG_ERROR, "%s: Cannot call without a field to query\n", chan_name);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1"); pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1");
return 0; return 0;
} }
if (!ast_strlen_zero(args.options)) {
if (ast_app_parse_options(action_options, &opts, NULL, args.options)) {
ast_log(LOG_ERROR, "%s: Invalid options: %s\n", chan_name, args.options);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1");
return 0;
}
}
ds = ast_geoloc_datastore_find(chan); ds = ast_geoloc_datastore_find(chan);
if (!ds) { if (!ds) {
ast_log(LOG_NOTICE, "%s: There is no geoloc profile on this channel\n", cmd); ast_log(LOG_NOTICE, "%s: There is no geoloc profile on this channel\n", chan_name);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2"); pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");
return 0; return 0;
} }
eprofile = ast_geoloc_datastore_get_eprofile(ds, 0); orig_eprofile = ast_geoloc_datastore_get_eprofile(ds, 0);
if (!orig_eprofile) {
ast_log(LOG_NOTICE, "%s: There is no geoloc profile on this channel\n", chan_name);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");
return 0;
}
eprofile = ast_geoloc_eprofile_dup(orig_eprofile);
ao2_ref(orig_eprofile, -1);
if (!eprofile) { if (!eprofile) {
ast_log(LOG_NOTICE, "%s: There is no geoloc profile on this channel\n", cmd); ast_log(LOG_ERROR, "%s: Unable to duplicate eprofile\n", chan_name);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2"); pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");
return 0; return 0;
} }
if (!eprofile->effective_location) {
ast_geoloc_eprofile_refresh_location(eprofile);
}
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "0"); pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "0");
if (ast_strings_equal(args.field, "inheritable")) { if (ast_strings_equal(args.field, "inheritable")) {
ast_str_append(buf, len, "%s", ds->inheritance ? "true" : "false"); ast_str_append(buf, len, "%s", ds->inheritance ? "true" : "false");
@ -101,19 +152,19 @@ static int geoloc_profile_read(struct ast_channel *chan,
} else if (ast_strings_equal(args.field, "notes")) { } else if (ast_strings_equal(args.field, "notes")) {
ast_str_append(buf, len, "%s", eprofile->notes); ast_str_append(buf, len, "%s", eprofile->notes);
} else if (ast_strings_equal(args.field, "location_info")) { } else if (ast_strings_equal(args.field, "location_info")) {
varlist_to_str(eprofile->location_info, buf, len); RESOLVE_FOR_READ(location_info);
} else if (ast_strings_equal(args.field, "location_info_refinement")) { } else if (ast_strings_equal(args.field, "location_info_refinement")) {
varlist_to_str(eprofile->location_refinement, buf, len); RESOLVE_FOR_READ(location_refinement);
} else if (ast_strings_equal(args.field, "location_variables")) { } else if (ast_strings_equal(args.field, "location_variables")) {
varlist_to_str(eprofile->location_variables, buf, len); RESOLVE_FOR_READ(location_variables);
} else if (ast_strings_equal(args.field, "effective_location")) { } else if (ast_strings_equal(args.field, "effective_location")) {
varlist_to_str(eprofile->effective_location, buf, len); RESOLVE_FOR_READ(effective_location);
} else if (ast_strings_equal(args.field, "usage_rules")) { } else if (ast_strings_equal(args.field, "usage_rules")) {
varlist_to_str(eprofile->usage_rules, buf, len); RESOLVE_FOR_READ(usage_rules);
} else if (ast_strings_equal(args.field, "confidence")) { } else if (ast_strings_equal(args.field, "confidence")) {
varlist_to_str(eprofile->confidence, buf, len); varlist_to_str(eprofile->confidence, buf, len);
} else { } else {
ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", cmd, args.field); ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", chan_name, args.field);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3"); pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3");
} }
@ -121,6 +172,10 @@ static int geoloc_profile_read(struct ast_channel *chan,
return 0; return 0;
} }
#define VAR_LIST_REPLACE(_old, _new) \
ast_variables_destroy(_old); \
_old = _new;
#define TEST_ENUM_VALUE(_chan_name, _ep, _field, _value) \ #define TEST_ENUM_VALUE(_chan_name, _ep, _field, _value) \
({ \ ({ \
enum ast_geoloc_ ## _field v; \ enum ast_geoloc_ ## _field v; \
@ -142,8 +197,26 @@ static int geoloc_profile_read(struct ast_channel *chan,
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3"); \ pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3"); \
return 0; \ return 0; \
} \ } \
ast_variables_destroy(_ep->_field); \ if (ast_test_flag(&opts, OPT_GEOLOC_APPEND)) { \
_ep->_field = _list; \ ast_variable_list_append(&_ep->_field, _list); \
} else {\
VAR_LIST_REPLACE(_ep->_field, _list); \
} \
})
#define RESOLVE_FOR_WRITE(_param) \
({ \
if (ast_test_flag(&opts, OPT_GEOLOC_RESOLVE)) { \
struct ast_variable *resolved = geoloc_eprofile_resolve_varlist( \
eprofile->_param, eprofile->location_variables, chan); \
if (!resolved) { \
ast_log(LOG_ERROR, "%s: Unable to resolve " #_param " %p %p\n", chan_name, eprofile->_param, eprofile->location_variables); \
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3"); \
return 0; \
} \
VAR_LIST_REPLACE(eprofile->_param, resolved); \
} \
}) })
static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char *data, static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char *data,
@ -153,9 +226,11 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
const char *chan_name = ast_channel_name(chan); const char *chan_name = ast_channel_name(chan);
struct ast_datastore *ds; /* Reminder: datastores aren't ao2 objects */ struct ast_datastore *ds; /* Reminder: datastores aren't ao2 objects */
RAII_VAR(struct ast_geoloc_eprofile *, eprofile, NULL, ao2_cleanup); RAII_VAR(struct ast_geoloc_eprofile *, eprofile, NULL, ao2_cleanup);
struct ast_flags opts = { 0, };
AST_DECLARE_APP_ARGS(args, AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(field); AST_APP_ARG(field);
AST_APP_ARG(options);
); );
/* Check for zero arguments */ /* Check for zero arguments */
@ -173,6 +248,18 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
return 0; return 0;
} }
if (!ast_strlen_zero(args.options)) {
if (ast_app_parse_options(action_options, &opts, NULL, args.options)) {
ast_log(LOG_ERROR, "%s: Invalid options: %s\n", chan_name, args.options);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1");
return 0;
}
}
ast_debug(1, "%s: name: %s value: %s options: %s append: %s resolve: %s\n", chan_name,
args.field, value, args.options, ast_test_flag(&opts, OPT_GEOLOC_APPEND) ? "yes" : "no",
ast_test_flag(&opts, OPT_GEOLOC_RESOLVE) ? "yes" : "no");
ds = ast_geoloc_datastore_find(chan); ds = ast_geoloc_datastore_find(chan);
if (!ds) { if (!ds) {
ds = ast_geoloc_datastore_create(ast_channel_name(chan)); ds = ast_geoloc_datastore_create(ast_channel_name(chan));
@ -203,6 +290,8 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
if (ast_strings_equal(args.field, "inheritable")) { if (ast_strings_equal(args.field, "inheritable")) {
ast_geoloc_datastore_set_inheritance(ds, ast_true(value)); ast_geoloc_datastore_set_inheritance(ds, ast_true(value));
} else if (ast_strings_equal(args.field, "id")) {
ast_string_field_set(eprofile, id, value);
} else if (ast_strings_equal(args.field, "location_reference")) { } else if (ast_strings_equal(args.field, "location_reference")) {
struct ast_geoloc_location *loc = ast_geoloc_get_location(value); struct ast_geoloc_location *loc = ast_geoloc_get_location(value);
ao2_cleanup(loc); ao2_cleanup(loc);
@ -224,18 +313,25 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
TEST_ENUM_VALUE(chan_name, eprofile, format, value); TEST_ENUM_VALUE(chan_name, eprofile, format, value);
} else if (ast_strings_equal(args.field, "pidf_element")) { } else if (ast_strings_equal(args.field, "pidf_element")) {
TEST_ENUM_VALUE(chan_name, eprofile, pidf_element, value); TEST_ENUM_VALUE(chan_name, eprofile, pidf_element, value);
} else if (ast_strings_equal(args.field, "location_info")) {
TEST_VARLIST(chan_name, eprofile, location_info, value);
} else if (ast_strings_equal(args.field, "location_source")) { } else if (ast_strings_equal(args.field, "location_source")) {
ast_string_field_set(eprofile, location_source, value); ast_string_field_set(eprofile, location_source, value);
} else if (ast_strings_equal(args.field, "notes")) {
ast_string_field_set(eprofile, notes, value);
} else if (ast_strings_equal(args.field, "location_info")) {
TEST_VARLIST(chan_name, eprofile, location_info, value);
RESOLVE_FOR_WRITE(location_info);
} else if (ast_strings_equal(args.field, "location_info_refinement")) { } else if (ast_strings_equal(args.field, "location_info_refinement")) {
TEST_VARLIST(chan_name, eprofile, location_refinement, value); TEST_VARLIST(chan_name, eprofile, location_refinement, value);
RESOLVE_FOR_WRITE(location_refinement);
} else if (ast_strings_equal(args.field, "location_variables")) { } else if (ast_strings_equal(args.field, "location_variables")) {
TEST_VARLIST(chan_name, eprofile, location_variables, value); TEST_VARLIST(chan_name, eprofile, location_variables, value);
RESOLVE_FOR_WRITE(location_variables);
} else if (ast_strings_equal(args.field, "effective_location")) { } else if (ast_strings_equal(args.field, "effective_location")) {
TEST_VARLIST(chan_name, eprofile, effective_location, value); TEST_VARLIST(chan_name, eprofile, effective_location, value);
RESOLVE_FOR_WRITE(effective_location);
} else if (ast_strings_equal(args.field, "usage_rules")) { } else if (ast_strings_equal(args.field, "usage_rules")) {
TEST_VARLIST(chan_name, eprofile, usage_rules, value); TEST_VARLIST(chan_name, eprofile, usage_rules, value);
RESOLVE_FOR_WRITE(usage_rules);
} else if (ast_strings_equal(args.field, "confidence")) { } else if (ast_strings_equal(args.field, "confidence")) {
TEST_VARLIST(chan_name, eprofile, confidence, value); TEST_VARLIST(chan_name, eprofile, confidence, value);
} else { } else {
@ -245,6 +341,7 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
} }
ast_geoloc_eprofile_refresh_location(eprofile); ast_geoloc_eprofile_refresh_location(eprofile);
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "0"); pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "0");
return 0; return 0;

@ -7,12 +7,14 @@
<configObject name="location"> <configObject name="location">
<synopsis>Location</synopsis> <synopsis>Location</synopsis>
<description> <description>
<para>cffdffff</para> <para>Parameters for defining a Location object</para>
</description> </description>
<configOption name="type"> <configOption name="type">
<synopsis>Must be of type 'location'.</synopsis> <synopsis>Must be of type 'location'.</synopsis>
</configOption> </configOption>
<configOption name="format" default="">
<configOption name="format" default="none">
<synopsis>Location specification type</synopsis> <synopsis>Location specification type</synopsis>
<description> <description>
<enumlist> <enumlist>
@ -42,7 +44,8 @@
</enumlist> </enumlist>
</description> </description>
</configOption> </configOption>
<configOption name="location_info" default="">
<configOption name="location_info" default="none">
<synopsis>Location information</synopsis> <synopsis>Location information</synopsis>
<description> <description>
<para>The contents of this parameter are specific to the <para>The contents of this parameter are specific to the
@ -68,7 +71,8 @@
</enumlist> </enumlist>
</description> </description>
</configOption> </configOption>
<configOption name="location_source" default="">
<configOption name="location_source" default="none">
<synopsis>Fully qualified host name</synopsis> <synopsis>Fully qualified host name</synopsis>
<description> <description>
<para>This parameter isn't required but if provided, RFC8787 says it MUST be a fully <para>This parameter isn't required but if provided, RFC8787 says it MUST be a fully
@ -77,7 +81,8 @@
Geolocation</literal> header.</para> Geolocation</literal> header.</para>
</description> </description>
</configOption> </configOption>
<configOption name="method" default="">
<configOption name="method" default="none">
<synopsis>Location determination method</synopsis> <synopsis>Location determination method</synopsis>
<description> <description>
<para>This is a rarely used field in the specification that would <para>This is a rarely used field in the specification that would
@ -94,7 +99,8 @@
</enumlist> </enumlist>
</description> </description>
</configOption> </configOption>
<configOption name="confidence" default="">
<configOption name="confidence" default="none">
<synopsis>Level of confidence</synopsis> <synopsis>Level of confidence</synopsis>
<description> <description>
<para>This is a rarely used field in the specification that would <para>This is a rarely used field in the specification that would
@ -123,14 +129,16 @@
</see-also> </see-also>
</configOption> </configOption>
</configObject> </configObject>
<configObject name="profile"> <configObject name="profile">
<synopsis>Profile</synopsis> <synopsis>Profile</synopsis>
<description> <description>
<para>cffdffff</para> <para>Parameters for defining a Profile object</para>
</description> </description>
<configOption name="type"> <configOption name="type">
<synopsis>Must be of type 'profile'.</synopsis> <synopsis>Must be of type 'profile'.</synopsis>
</configOption> </configOption>
<configOption name="pidf_element" default="device"> <configOption name="pidf_element" default="device">
<synopsis>PIDF-LO element to place this profile in</synopsis> <synopsis>PIDF-LO element to place this profile in</synopsis>
<description> <description>
@ -148,21 +156,25 @@
<ref type="link">https://www.rfc-editor.org/rfc/rfc5491.html#section-3.4</ref> <ref type="link">https://www.rfc-editor.org/rfc/rfc5491.html#section-3.4</ref>
</see-also> </see-also>
</configOption> </configOption>
<configOption name="location_reference" default="">
<configOption name="location_reference" default="none">
<synopsis>Reference to a location object</synopsis> <synopsis>Reference to a location object</synopsis>
</configOption> </configOption>
<configOption name="location_info_refinement" default="">
<configOption name="location_info_refinement" default="none">
<synopsis>Reference to a location object</synopsis> <synopsis>Reference to a location object</synopsis>
</configOption> </configOption>
<configOption name="location_variables" default=""> <configOption name="location_variables" default="none">
<synopsis>Reference to a location object</synopsis> <synopsis>Reference to a location object</synopsis>
</configOption> </configOption>
<configOption name="usage_rules" default="yes">
<configOption name="usage_rules" default="empty &lt;usage_rules&gt; element">
<synopsis>location specification type</synopsis> <synopsis>location specification type</synopsis>
<description> <description>
<para>xxxx</para> <para>xxxx</para>
</description> </description>
</configOption> </configOption>
<configOption name="notes" default=""> <configOption name="notes" default="">
<synopsis>Notes to be added to the outgoing PIDF-LO document</synopsis> <synopsis>Notes to be added to the outgoing PIDF-LO document</synopsis>
<description> <description>
@ -171,11 +183,13 @@
outgoing PIDF-LO document. Its usage should be pre-negotiated with outgoing PIDF-LO document. Its usage should be pre-negotiated with
any recipients.</para> any recipients.</para>
</description> </description>
</configOption> </configOption>
<configOption name="allow_routing_use"> <configOption name="allow_routing_use" default="no">
<synopsis>Sets the value of the Geolocation-Routing header.</synopsis> <synopsis>Sets the value of the Geolocation-Routing header.</synopsis>
</configOption> </configOption>
<configOption name="suppress_empty_ca_elements">
<configOption name="suppress_empty_ca_elements" default="no">
<synopsis>Sets if empty Civic Address elements should be suppressed <synopsis>Sets if empty Civic Address elements should be suppressed
from the PIDF-LO document.</synopsis> from the PIDF-LO document.</synopsis>
</configOption> </configOption>
@ -207,6 +221,7 @@
</enumlist> </enumlist>
</description> </description>
</configOption> </configOption>
<xi:include xpointer="xpointer(/docs/configInfo[@name='res_geolocation']/configFile[@name='geolocation.conf']/configObject[@name='location']/configOption[@name='format'])"/> <xi:include xpointer="xpointer(/docs/configInfo[@name='res_geolocation']/configFile[@name='geolocation.conf']/configObject[@name='location']/configOption[@name='format'])"/>
<xi:include xpointer="xpointer(/docs/configInfo[@name='res_geolocation']/configFile[@name='geolocation.conf']/configObject[@name='location']/configOption[@name='location_info'])"/> <xi:include xpointer="xpointer(/docs/configInfo[@name='res_geolocation']/configFile[@name='geolocation.conf']/configObject[@name='location']/configOption[@name='location_info'])"/>
<xi:include xpointer="xpointer(/docs/configInfo[@name='res_geolocation']/configFile[@name='geolocation.conf']/configObject[@name='location']/configOption[@name='confidence'])"/> <xi:include xpointer="xpointer(/docs/configInfo[@name='res_geolocation']/configFile[@name='geolocation.conf']/configObject[@name='location']/configOption[@name='confidence'])"/>
@ -220,8 +235,8 @@
Get or Set a field in a geolocation profile Get or Set a field in a geolocation profile
</synopsis> </synopsis>
<syntax> <syntax>
<parameter name="field" required="true"> <parameter name="parameter" required="true">
<para>The profile field to operate on. The following fields from the <para>The profile parameter to operate on. The following fields from the
Location and Profile objects are supported.</para> Location and Profile objects are supported.</para>
<enumlist> <enumlist>
<enum name="id"/> <enum name="id"/>
@ -244,10 +259,38 @@
set to <literal>true</literal> or <literal>false</literal> to control set to <literal>true</literal> or <literal>false</literal> to control
whether the profile will be passed to the outgoing channel. whether the profile will be passed to the outgoing channel.
</para> </para>
<para>
</para>
</parameter>
<parameter name="options" required="false">
<optionlist>
<option name="a">
<para>Append provided value to the specified parameter
instead of replacing the existing value. This only applies
to variable list parameters like
<literal>location_info_refinement</literal>.
</para>
</option>
<option name="r">
<para>Before reading or after writing the specified parameter,
re-resolve the <literal>effective_location</literal> and
<literal>usage_rules</literal> parameters using the
<literal>location_variables</literal> parameter and the variables
set on the channel in effect at the time this function is called.
</para>
<note><para>On a read operation, this does not alter the actual profile
in any way. On a write operation however, the
<literal>effective_location</literal> and/or <literal>usage_rules</literal>
parameters may indeed change and those changes will be passed on
to any outgoing channel.
</para></note>
</option>
</optionlist>
</parameter> </parameter>
</syntax> </syntax>
<description><para> <description><para>
When used to set a field on a profile, if the profile doesn't already exist, a new When used to set a parameter on a profile, if the profile doesn't already exist, a new
one will be created automatically. one will be created automatically.
</para> </para>
<para> <para>
@ -258,8 +301,8 @@
<enum name="0"><para>Success</para></enum> <enum name="0"><para>Success</para></enum>
<enum name="-1"><para>No or not enough parameters were supplied</para></enum> <enum name="-1"><para>No or not enough parameters were supplied</para></enum>
<enum name="-2"><para>There was an internal error finding or creating a profile</para></enum> <enum name="-2"><para>There was an internal error finding or creating a profile</para></enum>
<enum name="-3"><para>There was an issue specific to the field specified <enum name="-3"><para>There was an issue specific to the parameter specified
(value not valid or field name not found)</para></enum> (value not valid or parameter name not found, etc.)</para></enum>
</enumlist> </enumlist>
</description> </description>
</function> </function>

@ -156,6 +156,67 @@ int ast_geoloc_eprofile_refresh_location(struct ast_geoloc_eprofile *eprofile)
return 0; return 0;
} }
struct ast_geoloc_eprofile *ast_geoloc_eprofile_dup(struct ast_geoloc_eprofile *src)
{
struct ast_geoloc_eprofile *eprofile;
const char *profile_id;
int rc = 0;
if (!src) {
return NULL;
}
profile_id = ast_strdupa(src->id);
eprofile = ast_geoloc_eprofile_alloc(profile_id);
if (!eprofile) {
return NULL;
}
eprofile->allow_routing_use = src->allow_routing_use;
eprofile->pidf_element = src->pidf_element;
eprofile->suppress_empty_ca_elements = src->suppress_empty_ca_elements;
eprofile->format = src->format;
eprofile->precedence = src->precedence;
rc = ast_string_field_set(eprofile, location_reference, src->location_reference);
if (rc == 0) {
ast_string_field_set(eprofile, notes, src->notes);
}
if (rc == 0) {
ast_string_field_set(eprofile, method, src->method);
}
if (rc == 0) {
ast_string_field_set(eprofile, location_source, src->location_source);
}
if (rc == 0) {
rc = DUP_VARS(eprofile->location_info, src->location_info);
}
if (rc == 0) {
rc = DUP_VARS(eprofile->effective_location, src->effective_location);
}
if (rc == 0) {
rc = DUP_VARS(eprofile->location_refinement, src->location_refinement);
}
if (rc == 0) {
rc = DUP_VARS(eprofile->location_variables, src->location_variables);
}
if (rc == 0) {
rc = DUP_VARS(eprofile->usage_rules, src->usage_rules);
}
if (rc == 0) {
rc = DUP_VARS(eprofile->confidence, src->confidence);
}
if (rc != 0) {
ao2_ref(eprofile, -1);
return NULL;
}
return eprofile;
}
struct ast_geoloc_eprofile *ast_geoloc_eprofile_create_from_profile(struct ast_geoloc_profile *profile) struct ast_geoloc_eprofile *ast_geoloc_eprofile_create_from_profile(struct ast_geoloc_profile *profile)
{ {
struct ast_geoloc_eprofile *eprofile; struct ast_geoloc_eprofile *eprofile;
@ -287,7 +348,7 @@ struct ast_geoloc_eprofile *ast_geoloc_eprofile_create_from_uri(const char *uri,
return eprofile; return eprofile;
} }
static struct ast_variable *geoloc_eprofile_resolve_varlist(struct ast_variable *source, struct ast_variable *geoloc_eprofile_resolve_varlist(struct ast_variable *source,
struct ast_variable *variables, struct ast_channel *chan) struct ast_variable *variables, struct ast_channel *chan)
{ {
struct ast_variable *dest = NULL; struct ast_variable *dest = NULL;

@ -155,4 +155,8 @@ int geoloc_eprofile_reload(void);
struct ast_sorcery *geoloc_get_sorcery(void); struct ast_sorcery *geoloc_get_sorcery(void);
struct ast_variable *geoloc_eprofile_resolve_varlist(struct ast_variable *source,
struct ast_variable *variables, struct ast_channel *chan);
#endif /* GEOLOC_PRIVATE_H_ */ #endif /* GEOLOC_PRIVATE_H_ */

@ -574,7 +574,10 @@ static void handle_outgoing_request(struct ast_sip_session *session, struct pjsi
session_name); session_name);
} }
ast_geoloc_eprofile_refresh_location(final_eprofile); if (!final_eprofile->effective_location) {
ast_geoloc_eprofile_refresh_location(final_eprofile);
}
if (final_eprofile->format == AST_GEOLOC_FORMAT_URI) { if (final_eprofile->format == AST_GEOLOC_FORMAT_URI) {
uri = ast_geoloc_eprofile_to_uri(final_eprofile, channel, &buf, session_name); uri = ast_geoloc_eprofile_to_uri(final_eprofile, channel, &buf, session_name);
if (!uri) { if (!uri) {

Loading…
Cancel
Save