mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 11:25:35 +00:00
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
This commit is contained in:
committed by
Friendly Automation
parent
b221f0f86a
commit
bc6061bc5c
@@ -25,7 +25,6 @@
|
||||
#include "asterisk/strings.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/res_geolocation.h"
|
||||
#include "geoloc_private.h"
|
||||
|
||||
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,
|
||||
const char *cmd, char *data, struct ast_str **buf, ssize_t len)
|
||||
{
|
||||
char *parsed_data = ast_strdupa(data);
|
||||
const char *chan_name = ast_channel_name(chan);
|
||||
struct ast_datastore *ds;
|
||||
struct ast_geoloc_eprofile *orig_eprofile = NULL;
|
||||
struct ast_geoloc_eprofile *eprofile = NULL;
|
||||
struct ast_flags opts = { 0, };
|
||||
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(field);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
/* Check for zero arguments */
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
@@ -58,25 +89,45 @@ static int geoloc_profile_read(struct ast_channel *chan,
|
||||
AST_STANDARD_APP_ARGS(args, parsed_data);
|
||||
|
||||
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");
|
||||
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);
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
eprofile = ast_geoloc_datastore_get_eprofile(ds, 0);
|
||||
if (!eprofile) {
|
||||
ast_log(LOG_NOTICE, "%s: There is no geoloc profile on this channel\n", cmd);
|
||||
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) {
|
||||
ast_log(LOG_ERROR, "%s: Unable to duplicate eprofile\n", chan_name);
|
||||
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!eprofile->effective_location) {
|
||||
ast_geoloc_eprofile_refresh_location(eprofile);
|
||||
}
|
||||
|
||||
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "0");
|
||||
if (ast_strings_equal(args.field, "inheritable")) {
|
||||
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")) {
|
||||
ast_str_append(buf, len, "%s", eprofile->notes);
|
||||
} 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")) {
|
||||
varlist_to_str(eprofile->location_refinement, buf, len);
|
||||
RESOLVE_FOR_READ(location_refinement);
|
||||
} 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")) {
|
||||
varlist_to_str(eprofile->effective_location, buf, len);
|
||||
RESOLVE_FOR_READ(effective_location);
|
||||
} 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")) {
|
||||
varlist_to_str(eprofile->confidence, buf, len);
|
||||
} 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");
|
||||
}
|
||||
|
||||
@@ -121,6 +172,10 @@ static int geoloc_profile_read(struct ast_channel *chan,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define VAR_LIST_REPLACE(_old, _new) \
|
||||
ast_variables_destroy(_old); \
|
||||
_old = _new;
|
||||
|
||||
#define TEST_ENUM_VALUE(_chan_name, _ep, _field, _value) \
|
||||
({ \
|
||||
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"); \
|
||||
return 0; \
|
||||
} \
|
||||
ast_variables_destroy(_ep->_field); \
|
||||
_ep->_field = _list; \
|
||||
if (ast_test_flag(&opts, OPT_GEOLOC_APPEND)) { \
|
||||
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,
|
||||
@@ -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);
|
||||
struct ast_datastore *ds; /* Reminder: datastores aren't ao2 objects */
|
||||
RAII_VAR(struct ast_geoloc_eprofile *, eprofile, NULL, ao2_cleanup);
|
||||
struct ast_flags opts = { 0, };
|
||||
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(field);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
/* Check for zero arguments */
|
||||
@@ -173,6 +248,18 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
|
||||
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);
|
||||
if (!ds) {
|
||||
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")) {
|
||||
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")) {
|
||||
struct ast_geoloc_location *loc = ast_geoloc_get_location(value);
|
||||
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);
|
||||
} else if (ast_strings_equal(args.field, "pidf_element")) {
|
||||
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")) {
|
||||
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")) {
|
||||
TEST_VARLIST(chan_name, eprofile, location_refinement, value);
|
||||
RESOLVE_FOR_WRITE(location_refinement);
|
||||
} else if (ast_strings_equal(args.field, "location_variables")) {
|
||||
TEST_VARLIST(chan_name, eprofile, location_variables, value);
|
||||
RESOLVE_FOR_WRITE(location_variables);
|
||||
} else if (ast_strings_equal(args.field, "effective_location")) {
|
||||
TEST_VARLIST(chan_name, eprofile, effective_location, value);
|
||||
RESOLVE_FOR_WRITE(effective_location);
|
||||
} else if (ast_strings_equal(args.field, "usage_rules")) {
|
||||
TEST_VARLIST(chan_name, eprofile, usage_rules, value);
|
||||
RESOLVE_FOR_WRITE(usage_rules);
|
||||
} else if (ast_strings_equal(args.field, "confidence")) {
|
||||
TEST_VARLIST(chan_name, eprofile, confidence, value);
|
||||
} else {
|
||||
@@ -245,6 +341,7 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
|
||||
}
|
||||
|
||||
ast_geoloc_eprofile_refresh_location(eprofile);
|
||||
|
||||
pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "0");
|
||||
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user