This commit adds res_geolocation which creates the core capabilities to manipulate Geolocation information on SIP INVITEs. An upcoming commit will add res_pjsip_geolocation which will allow the capabilities to be used with the pjsip channel driver. This commit message is intentionally short because this isn't a simple capability. See the documentation at https://wiki.asterisk.org/wiki/display/AST/Geolocation for more information. THE CAPABILITIES IMPLEMENTED HERE MAY CHANGE BASED ON USER FEEDBACK! ASTERISK-30127 Change-Id: Ibfde963121b1ecf57fd98ee7060c4f0808416303
152 lines
3.5 KiB
C
152 lines
3.5 KiB
C
/*
|
|
* Asterisk -- An open source telephony toolkit.
|
|
*
|
|
* Copyright (C) 2022, Sangoma Technologies Corporation
|
|
*
|
|
* George Joseph <gjoseph@sangoma.com>
|
|
*
|
|
* See http://www.asterisk.org for more information about
|
|
* the Asterisk project. Please do not directly contact
|
|
* any of the maintainers of this project for assistance;
|
|
* the project provides a web site, mailing lists and IRC
|
|
* channels for your use.
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
* at the top of the source tree.
|
|
*/
|
|
|
|
#include "asterisk.h"
|
|
#include "asterisk/config.h"
|
|
#include "asterisk/cli.h"
|
|
#include "asterisk/res_geolocation.h"
|
|
#include "asterisk/xml.h"
|
|
#include "geoloc_private.h"
|
|
|
|
static const char *addr_code_name_entries[] = {
|
|
"country",
|
|
"A1",
|
|
"A2",
|
|
"A3",
|
|
"A4",
|
|
"A5",
|
|
"A6",
|
|
"ADDCODE",
|
|
"BLD",
|
|
"FLR",
|
|
"HNO",
|
|
"HNS",
|
|
"LMK",
|
|
"LOC",
|
|
"NAM",
|
|
"PC",
|
|
"PCN",
|
|
"PLC",
|
|
"POBOX",
|
|
"POD",
|
|
"POM",
|
|
"PRD",
|
|
"PRM",
|
|
"RD",
|
|
"RD",
|
|
"RDBR",
|
|
"RDSEC",
|
|
"RDSUBBR",
|
|
"ROOM",
|
|
"SEAT",
|
|
"STS",
|
|
"UNIT",
|
|
};
|
|
|
|
static int compare_civicaddr_codes(const void *_a, const void *_b)
|
|
{
|
|
/* See the man page for qsort(3) for an explanation of the casts */
|
|
int rc = strcmp(*(const char **)_a, *(const char **)_b);
|
|
return rc;
|
|
}
|
|
|
|
int ast_geoloc_civicaddr_is_code_valid(const char *code)
|
|
{
|
|
const char **entry = bsearch(&code, addr_code_name_entries, ARRAY_LEN(addr_code_name_entries),
|
|
sizeof(const char *), compare_civicaddr_codes);
|
|
return (entry != NULL);
|
|
}
|
|
|
|
enum ast_geoloc_validate_result ast_geoloc_civicaddr_validate_varlist(
|
|
const struct ast_variable *varlist, const char **result)
|
|
{
|
|
const struct ast_variable *var = varlist;
|
|
for (; var; var = var->next) {
|
|
int valid = ast_geoloc_civicaddr_is_code_valid(var->name);
|
|
if (!valid) {
|
|
*result = var->name;
|
|
return AST_GEOLOC_VALIDATE_INVALID_VARNAME;
|
|
}
|
|
}
|
|
return AST_GEOLOC_VALIDATE_SUCCESS;
|
|
}
|
|
|
|
struct ast_xml_node *geoloc_civicaddr_list_to_xml(const struct ast_variable *resolved_location,
|
|
const char *ref_string)
|
|
{
|
|
char *lang = NULL;
|
|
char *s = NULL;
|
|
struct ast_variable *var;
|
|
struct ast_xml_node *ca_node;
|
|
struct ast_xml_node *child_node;
|
|
int rc = 0;
|
|
SCOPE_ENTER(3, "%s", ref_string);
|
|
|
|
lang = (char *)ast_variable_find_in_list(resolved_location, "lang");
|
|
if (ast_strlen_zero(lang)) {
|
|
lang = ast_strdupa(ast_defaultlanguage);
|
|
for (s = lang; *s; s++) {
|
|
if (*s == '_') {
|
|
*s = '-';
|
|
}
|
|
}
|
|
}
|
|
|
|
ca_node = ast_xml_new_node("civicAddress");
|
|
if (!ca_node) {
|
|
SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create 'civicAddress' XML node\n", ref_string);
|
|
}
|
|
rc = ast_xml_set_attribute(ca_node, "lang", lang);
|
|
if (rc != 0) {
|
|
ast_xml_free_node(ca_node);
|
|
SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create 'lang' XML attribute\n", ref_string);
|
|
}
|
|
|
|
for (var = (struct ast_variable *)resolved_location; var; var = var->next) {
|
|
if (ast_strings_equal(var->name, "lang")) {
|
|
continue;
|
|
}
|
|
child_node = ast_xml_new_child(ca_node, var->name);
|
|
if (!child_node) {
|
|
ast_xml_free_node(ca_node);
|
|
SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create '%s' XML node\n", var->name, ref_string);
|
|
}
|
|
ast_xml_set_text(child_node, var->value);
|
|
}
|
|
|
|
SCOPE_EXIT_RTN_VALUE(ca_node, "%s: Done\n", ref_string);
|
|
}
|
|
|
|
int geoloc_civicaddr_unload(void)
|
|
{
|
|
return AST_MODULE_LOAD_SUCCESS;
|
|
}
|
|
|
|
int geoloc_civicaddr_load(void)
|
|
{
|
|
qsort(addr_code_name_entries, ARRAY_LEN(addr_code_name_entries), sizeof(const char *),
|
|
compare_civicaddr_codes);
|
|
|
|
return AST_MODULE_LOAD_SUCCESS;
|
|
}
|
|
|
|
int geoloc_civicaddr_reload(void)
|
|
{
|
|
return AST_MODULE_LOAD_SUCCESS;
|
|
}
|