From e9ae638978fb2470e1c5c871c827e3207eed8a1e Mon Sep 17 00:00:00 2001 From: George Joseph Date: Tue, 16 Aug 2022 06:25:10 -0600 Subject: [PATCH] res_geolocation: Add built-in profiles The trigger to perform outgoing geolocation processing is the presence of a geoloc_outgoing_call_profile on an endpoint. This is intentional so as to not leak location information to destinations that shouldn't receive it. In a totally dynamic configuration scenario however, there may not be any profiles defined in geolocation.conf. This makes it impossible to do outgoing processing without defining a "dummy" profile in the config file. This commit adds 4 built-in profiles: "" "" "" "" The profiles are empty except for having their precedence set and can be set on an endpoint to allow processing without entries in geolocation.conf. "" is actually the best one to use in this situation. ASTERISK-30182 Change-Id: I1819ccfa404ce59802a3a07ad1cabed60fb9480a --- configs/samples/geolocation.conf.sample | 10 +++ doc/CHANGES-staging/res_geolocation.txt | 8 +++ res/res_geolocation/geoloc_config.c | 86 ++++++++++++++++++++++--- 3 files changed, 95 insertions(+), 9 deletions(-) diff --git a/configs/samples/geolocation.conf.sample b/configs/samples/geolocation.conf.sample index 8c44edb801..c5c1306efb 100644 --- a/configs/samples/geolocation.conf.sample +++ b/configs/samples/geolocation.conf.sample @@ -272,3 +272,13 @@ profile_action = discard_incoming ======================================================================= --; + +-- NOTE --------------------------------------------------------------- +There are 4 built-in profiles that can be assigned to endpoints: + "" + "" + "" + "" +The profiles are empty except for having their precedence +set. + diff --git a/doc/CHANGES-staging/res_geolocation.txt b/doc/CHANGES-staging/res_geolocation.txt index bc12a317f4..325b380f4a 100644 --- a/doc/CHANGES-staging/res_geolocation.txt +++ b/doc/CHANGES-staging/res_geolocation.txt @@ -24,3 +24,11 @@ to manipulate Geolocation information on SIP INVITEs. * Delete a profile if 'inheritable' is set to no. * Fixed various bugs and leaks * Updated Asterisk WiKi documentation. + +Added 4 built-in profiles: + "" + "" + "" + "" +The profiles are empty except for having their precedence +set. diff --git a/res/res_geolocation/geoloc_config.c b/res/res_geolocation/geoloc_config.c index 772bdc7335..5916697215 100644 --- a/res/res_geolocation/geoloc_config.c +++ b/res/res_geolocation/geoloc_config.c @@ -85,7 +85,8 @@ static void geoloc_profile_destructor(void *obj) { static void *geoloc_profile_alloc(const char *name) { - struct ast_geoloc_profile *profile = ast_sorcery_generic_alloc(sizeof(*profile), geoloc_profile_destructor); + struct ast_geoloc_profile *profile = ast_sorcery_generic_alloc(sizeof(*profile), + geoloc_profile_destructor); if (profile) { ast_string_field_init(profile, 128); } @@ -581,18 +582,64 @@ int geoloc_config_unload(void) return 0; } +static int default_profile_create(const char *name) +{ + int rc = 0; + struct ast_geoloc_profile *profile; + char *id = ast_alloca(strlen(name) + 3 /* <, >, NULL */); + + sprintf(id, "<%s>", name); /* Safe */ + profile = ast_sorcery_alloc(geoloc_sorcery, "profile", id); + ast_assert_return(profile != NULL, 0); + + profile->precedence = ast_geoloc_precedence_str_to_enum(name); + profile->pidf_element = AST_PIDF_ELEMENT_DEVICE; + rc = ast_sorcery_create(geoloc_sorcery, profile); + /* + * We're either passing the ref to sorcery or there was an error. + * Either way we need to drop our reference. + */ + ao2_ref(profile, -1); + + /* ast_assert_return wants a true/false */ + return rc == 0 ? 1 : 0; +} + +static int geoloc_load_default_profiles(void) +{ + /* + * If any of these fail, the module will fail to load + * and clean up the sorcery instance so no error cleanup + * is required here. + */ + ast_assert_return(default_profile_create("prefer_config"), -1); + ast_assert_return(default_profile_create("discard_config"), -1); + ast_assert_return(default_profile_create("prefer_incoming"), -1); + ast_assert_return(default_profile_create("discard_incoming"), -1); + + return 0; +} + int geoloc_config_load(void) { + enum ast_sorcery_apply_result result; + int rc = 0; + if (!(geoloc_sorcery = ast_sorcery_open())) { ast_log(LOG_ERROR, "Failed to open geolocation sorcery\n"); return AST_MODULE_LOAD_DECLINE; } - ast_sorcery_apply_default(geoloc_sorcery, "location", "config", "geolocation.conf,criteria=type=location"); - if (ast_sorcery_object_register(geoloc_sorcery, "location", geoloc_location_alloc, NULL, geoloc_location_apply_handler)) { + ast_sorcery_apply_config(geoloc_sorcery, "location"); + result = ast_sorcery_apply_default(geoloc_sorcery, "location", "config", "geolocation.conf,criteria=type=location"); + if (result != AST_SORCERY_APPLY_SUCCESS) { + ast_log(LOG_ERROR, "Failed to apply defaults for geoloc location object with sorcery\n"); + return AST_MODULE_LOAD_DECLINE; + } + + rc = ast_sorcery_object_register(geoloc_sorcery, "location", geoloc_location_alloc, NULL, geoloc_location_apply_handler); + if (rc != 0) { ast_log(LOG_ERROR, "Failed to register geoloc location object with sorcery\n"); - ast_sorcery_unref(geoloc_sorcery); - geoloc_sorcery = NULL; return AST_MODULE_LOAD_DECLINE; } @@ -609,11 +656,25 @@ int geoloc_config_load(void) 0, STRFLDSET(struct ast_geoloc_location, method)); - ast_sorcery_apply_default(geoloc_sorcery, "profile", "config", "geolocation.conf,criteria=type=profile"); - if (ast_sorcery_object_register(geoloc_sorcery, "profile", geoloc_profile_alloc, NULL, geoloc_profile_apply_handler)) { + ast_sorcery_apply_config(geoloc_sorcery, "profile"); + /* + * The memory backend is used to contain the built-in profiles. + */ + result = ast_sorcery_apply_wizard_mapping(geoloc_sorcery, "profile", "memory", NULL, 0); + if (result == AST_SORCERY_APPLY_FAIL) { + ast_log(LOG_ERROR, "Failed to add memory wizard mapping to geoloc profile object\n"); + return AST_MODULE_LOAD_DECLINE; + } + + result = ast_sorcery_apply_wizard_mapping(geoloc_sorcery, "profile", "config", + "geolocation.conf,criteria=type=profile", 0); + if (result == AST_SORCERY_APPLY_FAIL) { + ast_log(LOG_ERROR, "Failed to add memory wizard mapping to geoloc profile object\n"); + return AST_MODULE_LOAD_DECLINE; + } + rc = ast_sorcery_object_register(geoloc_sorcery, "profile", geoloc_profile_alloc, NULL, geoloc_profile_apply_handler); + if (rc != 0) { ast_log(LOG_ERROR, "Failed to register geoloc profile object with sorcery\n"); - ast_sorcery_unref(geoloc_sorcery); - geoloc_sorcery = NULL; return AST_MODULE_LOAD_DECLINE; } @@ -638,6 +699,13 @@ int geoloc_config_load(void) ast_sorcery_load(geoloc_sorcery); + rc = geoloc_load_default_profiles(); + if (rc != 0) { + ast_log(LOG_ERROR, "Failed to load default geoloc profiles\n"); + return AST_MODULE_LOAD_DECLINE; + } + + ast_cli_register_multiple(geoloc_location_cli_commands, ARRAY_LEN(geoloc_location_cli_commands)); return AST_MODULE_LOAD_SUCCESS;