Asterisk - The Open Source Telephony Project GIT-master-55f4e6d
geoloc_gml.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022, Sangoma Technologies Corporation
3 *
4 * George Joseph <gjoseph@sangoma.com>
5 *
6 * See http://www.asterisk.org for more information about
7 * the Asterisk project. Please do not directly contact
8 * any of the maintainers of this project for assistance;
9 * the project provides a web site, mailing lists and IRC
10 * channels for your use.
11 *
12 * This program is free software, distributed under the terms of
13 * the GNU General Public License Version 2. See the LICENSE file
14 * at the top of the source tree.
15 */
16
17#include "asterisk.h"
18#include "asterisk/config.h"
19#include "asterisk/cli.h"
21#include "geoloc_private.h"
22
23
24#if 1 //not used yet.
40};
41
44 const char *name;
45 int (*validator)(const char *value);
47};
48
53 { GEOLOC_SHAPE_ATTR_SEMI_MAJOR_AXIS,"semiMajorAxis", NULL, NULL},
54 { GEOLOC_SHAPE_ATTR_SEMI_MINOR_AXIS,"semiMinorAxis", NULL, NULL},
55 { GEOLOC_SHAPE_ATTR_VERTICAL_AXIS,"verticalAxis", NULL, NULL},
57 { GEOLOC_SHAPE_ATTR_ORIENTATION,"orientation", NULL, NULL},
58 { GEOLOC_SHAPE_ATTR_ORIENTATION_UOM,"orientation_uom", NULL, NULL},
59 { GEOLOC_SHAPE_ATTR_INNER_RADIUS,"innerRadius", NULL, NULL},
60 { GEOLOC_SHAPE_ATTR_OUTER_RADIUS,"outerRadius", NULL, NULL},
61 { GEOLOC_SHAPE_ATTR_STARTING_ANGLE,"startingAngle", NULL, NULL},
62 { GEOLOC_SHAPE_ATTR_OPENING_ANGLE,"openingAngle", NULL, NULL},
63 { GEOLOC_SHAPE_ATTR_ANGLE_UOM,"angle_uom", NULL, NULL},
64};
65#endif //not used yet.
66
68 const char *attribute;
71 int (*validator)(const char *value);
72};
73
75 const char *shape_type;
77};
78
79static int pos_validator(const char *value)
80{
81 float lat;
82 float lon;
83 return (sscanf(value, "%f %f", &lat, &lon) == 2);
84}
85
86static int pos3d_validator(const char *value)
87{
88 float lat;
89 float lon;
90 float alt;
91 return (sscanf(value, "%f %f %f", &lat, &lon, &alt) == 3);
92}
93
94static int float_validator(const char *value)
95{
96 float val;
97 return (sscanf(value, "%f", &val) == 1);
98}
99
100static int uom_validator(const char *value)
101{
102 return (ast_strings_equal(value, "degrees") || ast_strings_equal(value, "radians"));
103}
104
105
107 { "Point", { {"pos", 1, 1, pos_validator}, {NULL, -1, -1} }},
108 { "Polygon", { {"pos", 3, -1, pos_validator}, {NULL, -1, -1} }},
109 { "Circle", { {"pos", 1, 1, pos_validator}, {"radius", 1, 1, float_validator},{NULL, -1, -1}}},
110 { "Ellipse", { {"pos", 1, 1, pos_validator}, {"semiMajorAxis", 1, 1, float_validator},
111 {"semiMinorAxis", 1, 1, float_validator}, {"orientation", 1, 1, float_validator},
112 {"orientation_uom", 1, 1, uom_validator}, {NULL, -1, -1} }},
113 { "ArcBand", { {"pos", 1, 1, pos_validator}, {"innerRadius", 1, 1, float_validator},
114 {"outerRadius", 1, 1, float_validator}, {"startAngle", 1, 1, float_validator},
115 {"startAngle_uom", 1, 1, uom_validator}, {"openingAngle", 1, 1, float_validator},
116 {"openingAngle_uom", 1, 1, uom_validator}, {NULL, -1, -1} }},
117 { "Sphere", { {"pos3d", 1, 1, pos3d_validator}, {"radius", 1, 1, float_validator}, {NULL, -1, -1} }},
118 { "Ellipse", { {"pos3d", 1, 1, pos3d_validator}, {"semiMajorAxis", 1, 1, float_validator},
119 {"semiMinorAxis", 1, 1, float_validator}, {"verticalAxis", 1, 1, float_validator},
120 {"orientation", 1, 1, float_validator}, {"orientation_uom", 1, 1, uom_validator}, {NULL, -1, -1} }},
121 { "Prism", { {"pos3d", 3, -1, pos_validator}, {"height", 1, 1, float_validator}, {NULL, -1, -1} }},
122};
123
125 const char **result)
126{
127 int def_index = -1;
128 const struct ast_variable *var;
129 int i;
130 const char *shape_type = ast_variable_find_in_list(varlist, "shape");
131
132 if (!shape_type) {
134 }
135
136 for (i = 0; i < ARRAY_LEN(gml_shape_defs); i++) {
137 if (ast_strings_equal(gml_shape_defs[i].shape_type, shape_type)) {
138 def_index = i;
139 }
140 }
141 if (def_index < 0) {
143 }
144
145 for (var = varlist; var; var = var->next) {
146 int vname_index = -1;
147 if (ast_strings_equal("shape", var->name)) {
148 continue;
149 }
150 for (i = 0; i < ARRAY_LEN(gml_shape_defs[def_index].required_attributes); i++) {
151 if (gml_shape_defs[def_index].required_attributes[i].attribute == NULL) {
152 break;
153 }
154 if (ast_strings_equal(gml_shape_defs[def_index].required_attributes[i].attribute, var->name)) {
155 vname_index = i;
156 break;
157 }
158 }
159 if (vname_index < 0) {
160 *result = var->name;
162 }
163 if (!gml_shape_defs[def_index].required_attributes[vname_index].validator(var->value)) {
164 *result = var->name;
166 }
167 }
168
169 for (i = 0; i < ARRAY_LEN(gml_shape_defs[def_index].required_attributes); i++) {
170 int count = 0;
171 if (gml_shape_defs[def_index].required_attributes[i].attribute == NULL) {
172 break;
173 }
174
175 for (var = varlist; var; var = var->next) {
176 if (ast_strings_equal(gml_shape_defs[def_index].required_attributes[i].attribute, var->name)) {
177 count++;
178 }
179 }
180 if (count < gml_shape_defs[def_index].required_attributes[i].min_required) {
183 }
184 if (gml_shape_defs[def_index].required_attributes[i].max_allowed > 0 &&
185 count > gml_shape_defs[def_index].required_attributes[i].max_allowed) {
188 }
189 }
191}
192
193static char *handle_gml_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
194{
195 int i;
196
197 switch (cmd) {
198 case CLI_INIT:
199 e->command = "geoloc show gml_shape_defs";
200 e->usage =
201 "Usage: geoloc show gml_shape_defs\n"
202 " Show the GML Shape definitions.\n";
203 return NULL;
204 case CLI_GENERATE:
205 return NULL;
206 }
207
208 ast_cli(a->fd, "%-16s %-32s\n", "Shape", "Attributes name(min,max)");
209 ast_cli(a->fd, "================ ===============================\n");
210
211 for (i = 0; i < ARRAY_LEN(gml_shape_defs); i++) {
212 int j;
213 ast_cli(a->fd, "%-16s", gml_shape_defs[i].shape_type);
214 for (j = 0; j < ARRAY_LEN(gml_shape_defs[i].required_attributes); j++) {
215 if (gml_shape_defs[i].required_attributes[j].attribute == NULL) {
216 break;
217 }
218 if (gml_shape_defs[i].required_attributes[j].max_allowed >= 0) {
219 ast_cli(a->fd, " %s(%d,%d)", gml_shape_defs[i].required_attributes[j].attribute,
222 } else {
223 ast_cli(a->fd, " %s(%d,unl)", gml_shape_defs[i].required_attributes[j].attribute,
225 }
226 }
227 ast_cli(a->fd, "\n");
228 }
229 ast_cli(a->fd, "\n");
230
231 return CLI_SUCCESS;
232}
233
234static struct ast_cli_entry geoloc_gml_cli[] = {
235 AST_CLI_DEFINE(handle_gml_show, "Show the GML Shape definitions"),
236};
237
238struct ast_xml_node *geoloc_gml_list_to_xml(const struct ast_variable *resolved_location,
239 const char *ref_string)
240{
241 const char *shape;
242 char *crs;
243 struct ast_variable *var;
244 struct ast_xml_node *gml_node;
245 struct ast_xml_node *child_node;
246 int rc = 0;
247
248 SCOPE_ENTER(3, "%s", ref_string);
249
250 if (!resolved_location) {
251 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: resolved_location was NULL\n",
252 ref_string);
253 }
254
255 shape = ast_variable_find_in_list(resolved_location, "shape");
256 if (ast_strlen_zero(shape)) {
257 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: There's no 'shape' parameter\n",
258 ref_string);
259 }
260 crs = (char *)ast_variable_find_in_list(resolved_location, "crs");
261 if (ast_strlen_zero(crs)) {
262 crs = "2d";
263 }
264
265 gml_node = ast_xml_new_node(shape);
266 if (!gml_node) {
267 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create '%s' XML node\n", shape, ref_string);
268 }
269 rc = ast_xml_set_attribute(gml_node, "crs", crs);
270 if (rc != 0) {
271 ast_xml_free_node(gml_node);
272 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create 'crs' XML attribute\n", ref_string);
273 }
274
275 for (var = (struct ast_variable *)resolved_location; var; var = var->next) {
276 RAII_VAR(char *, value, NULL, ast_free);
277 char *uom = NULL;
278
279 if (ast_strings_equal(var->name, "shape") || ast_strings_equal(var->name, "crs")) {
280 continue;
281 }
282 value = ast_strdup(var->value);
283
284 if (ast_strings_equal(var->name, "orientation") || ast_strings_equal(var->name, "startAngle")
285 || ast_strings_equal(var->name, "openingAngle")) {
286 char *a = NULL;
287 char *junk = NULL;
288 float angle;
289 uom = value;
290
291 /* 'a' should now be the angle and 'uom' should be the uom */
292 a = strsep(&uom, " ");
293 angle = strtof(a, &junk);
294 /*
295 * strtof sets junk to the first non-valid character so if it's
296 * not empty after the conversion, there were unrecognized
297 * characters in the angle. It'll point to the NULL terminator
298 * if angle was completely converted.
299 */
300 if (!ast_strlen_zero(junk)) {
301 ast_xml_free_node(gml_node);
302 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: The angle portion of parameter '%s' ('%s') is malformed\n",
303 ref_string, var->name, var->value);
304 }
305
306 if (ast_strlen_zero(uom)) {
307 uom = "degrees";
308 }
309
310 if (ast_begins_with(uom, "deg")) {
311 if (angle > 360.0) {
312 ast_xml_free_node(gml_node);
313 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Parameter '%s': '%s' is malformed. "
314 "Degrees can't be > 360.0\n",
315 ref_string, var->name, var->value);
316 }
317 } else if (ast_begins_with(uom, "rad")) {
318 if(angle > 100.0) {
319 ast_xml_free_node(gml_node);
320 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Parameter '%s': '%s' is malformed. "
321 "Radians can't be > 100.0\n",
322 ref_string, var->name, var->value);
323 }
324 } else {
325 ast_xml_free_node(gml_node);
326 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Parameter '%s': '%s' is malformed. "
327 "The unit of measure must be 'deg[rees]' or 'rad[ians]'\n",
328 ref_string, var->name, var->value);
329 }
330 }
331
332 child_node = ast_xml_new_child(gml_node, var->name);
333 if (!child_node) {
334 ast_xml_free_node(gml_node);
335 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create '%s' XML node\n", var->name, ref_string);
336 }
337 if (!ast_strlen_zero(uom)) {
338 rc = ast_xml_set_attribute(child_node, "uom", uom);
339 if (rc != 0) {
340 ast_xml_free_node(gml_node);
341 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create 'uom' XML attribute\n", ref_string);
342 }
343 }
344 ast_xml_set_text(child_node, value);
345 }
346
347 SCOPE_EXIT_RTN_VALUE(gml_node, "%s: Done\n", ref_string);
348}
349
351{
353
355}
356
358{
360
362}
363
365{
367}
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
static PGresult * result
Definition: cel_pgsql.c:84
Standard Command Line Interface.
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int float_validator(const char *value)
Definition: geoloc_gml.c:94
static int pos3d_validator(const char *value)
Definition: geoloc_gml.c:86
static int pos_validator(const char *value)
Definition: geoloc_gml.c:79
static struct geoloc_gml_shape_def gml_shape_defs[8]
Definition: geoloc_gml.c:106
struct geoloc_gml_attr_def gml_attr_defs[]
Definition: geoloc_gml.c:49
static struct ast_cli_entry geoloc_gml_cli[]
Definition: geoloc_gml.c:234
static int uom_validator(const char *value)
Definition: geoloc_gml.c:100
int geoloc_gml_reload(void)
Definition: geoloc_gml.c:364
static char * handle_gml_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: geoloc_gml.c:193
geoloc_shape_attrs
Definition: geoloc_gml.c:25
@ GEOLOC_SHAPE_ATTR_INNER_RADIUS
Definition: geoloc_gml.c:35
@ GEOLOC_SHAPE_ATTR_ANGLE_UOM
Definition: geoloc_gml.c:39
@ GEOLOC_SHAPE_ATTR_RADIUS
Definition: geoloc_gml.c:28
@ GEOLOC_SHAPE_ATTR_OPENING_ANGLE
Definition: geoloc_gml.c:38
@ GEOLOC_SHAPE_ATTR_POS
Definition: geoloc_gml.c:26
@ GEOLOC_SHAPE_ATTR_STARTING_ANGLE
Definition: geoloc_gml.c:37
@ GEOLOC_SHAPE_ATTR_OUTER_RADIUS
Definition: geoloc_gml.c:36
@ GEOLOC_SHAPE_ATTR_ORIENTATION
Definition: geoloc_gml.c:33
@ GEOLOC_SHAPE_ATTR_ORIENTATION_UOM
Definition: geoloc_gml.c:34
@ GEOLOC_SHAPE_ATTR_HEIGHT
Definition: geoloc_gml.c:32
@ GEOLOC_SHAPE_ATTR_SEMI_MINOR_AXIS
Definition: geoloc_gml.c:30
@ GEOLOC_SHAPE_ATTR_SEMI_MAJOR_AXIS
Definition: geoloc_gml.c:29
@ GEOLOC_SHAPE_ATTR_VERTICAL_AXIS
Definition: geoloc_gml.c:31
@ GEOLOC_SHAPE_ATTR_POS3D
Definition: geoloc_gml.c:27
enum ast_geoloc_validate_result ast_geoloc_gml_validate_varlist(const struct ast_variable *varlist, const char **result)
Validate that the variables in the list represent a valid GML shape.
Definition: geoloc_gml.c:124
int geoloc_gml_unload(void)
Definition: geoloc_gml.c:350
struct ast_xml_node * geoloc_gml_list_to_xml(const struct ast_variable *resolved_location, const char *ref_string)
Definition: geoloc_gml.c:238
int geoloc_gml_load(void)
Definition: geoloc_gml.c:357
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define SCOPE_ENTER(level,...)
char * strsep(char **str, const char *delims)
Configuration File Parser.
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
Definition: main/config.c:919
#define LOG_ERROR
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
ast_geoloc_validate_result
@ AST_GEOLOC_VALIDATE_TOO_MANY_VARNAMES
@ AST_GEOLOC_VALIDATE_MISSING_SHAPE
@ AST_GEOLOC_VALIDATE_INVALID_VALUE
@ AST_GEOLOC_VALIDATE_SUCCESS
@ AST_GEOLOC_VALIDATE_NOT_ENOUGH_VARNAMES
@ AST_GEOLOC_VALIDATE_INVALID_SHAPE
@ AST_GEOLOC_VALIDATE_INVALID_VARNAME
#define NULL
Definition: resample.c:96
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition: strings.c:238
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Structure for variables, used for configurations and for channel variables.
enum geoloc_shape_attrs attr
Definition: geoloc_gml.c:43
int(* validator)(const char *value)
Definition: geoloc_gml.c:45
const char * name
Definition: geoloc_gml.c:44
int(* transformer)(struct ast_variable *value)
Definition: geoloc_gml.c:46
const char * attribute
Definition: geoloc_gml.c:68
int(* validator)(const char *value)
Definition: geoloc_gml.c:71
const char * shape_type
Definition: geoloc_gml.c:75
struct geoloc_gml_attr required_attributes[8]
Definition: geoloc_gml.c:76
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
static struct test_val a
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ARRAY_LEN(a)
Definition: utils.h:666
struct ast_xml_node * ast_xml_new_child(struct ast_xml_node *parent, const char *child_name)
Add a child node inside a passed parent node.
Definition: xml.c:156
struct ast_xml_node * ast_xml_new_node(const char *name)
Create a XML node.
Definition: xml.c:144
int ast_xml_set_attribute(struct ast_xml_node *node, const char *name, const char *value)
Set an attribute to a node.
Definition: xml.c:284
void ast_xml_set_text(struct ast_xml_node *node, const char *content)
Set an element content string.
Definition: xml.c:362
void ast_xml_free_node(struct ast_xml_node *node)
Free node.
Definition: xml.c:243