Asterisk - The Open Source Telephony Project  21.4.1
geoloc_datastore.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2022, Sangoma Technologies Corporation
5  *
6  * George Joseph <gjoseph@sangoma.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 #include "asterisk.h"
20 #include "asterisk/astobj2.h"
21 #include "asterisk/datastore.h"
22 #include "asterisk/channel.h"
23 #include "asterisk/res_geolocation.h"
24 #include "asterisk/vector.h"
25 #include "geoloc_private.h"
26 
27 #define GEOLOC_DS_TYPE "geoloc_eprofiles"
28 
29 struct ast_sorcery *geoloc_sorcery;
30 
32  const char *id;
34 };
35 
36 static void geoloc_datastore_free(void *obj)
37 {
38  struct eprofiles_datastore *eds = obj;
39 
40  AST_VECTOR_RESET(&eds->eprofiles, ao2_cleanup);
41  AST_VECTOR_FREE(&eds->eprofiles);
42  ast_free(eds);
43 }
44 
45 static void *geoloc_datastore_duplicate(void *obj)
46 {
47  struct eprofiles_datastore *in_eds = obj;
48  struct eprofiles_datastore *out_eds;
49  int rc = 0;
50  int i = 0;
51  int eprofile_count = 0;
52 
53  out_eds = ast_calloc(1, sizeof(*out_eds));
54  if (!out_eds) {
55  return NULL;
56  }
57 
58  rc = AST_VECTOR_INIT(&out_eds->eprofiles, 2);
59  if (rc != 0) {
60  ast_free(out_eds);
61  return NULL;
62  }
63 
64  eprofile_count = AST_VECTOR_SIZE(&in_eds->eprofiles);
65  for (i = 0; i < eprofile_count; i++) {
66  struct ast_geoloc_eprofile *ep = AST_VECTOR_GET(&in_eds->eprofiles, i);
67  rc = AST_VECTOR_APPEND(&out_eds->eprofiles, ao2_bump(ep));
68  if (rc != 0) {
69  /* This will clean up the bumped reference to the eprofile */
70  geoloc_datastore_free(out_eds);
71  return NULL;
72  }
73  }
74 
75  return out_eds;
76 }
77 
78 static const struct ast_datastore_info geoloc_datastore_info = {
79  .type = GEOLOC_DS_TYPE,
80  .destroy = geoloc_datastore_free,
81  .duplicate = geoloc_datastore_duplicate,
82 };
83 
84 #define IS_GEOLOC_DS(_ds) (_ds && _ds->data && ast_strings_equal(_ds->info->type, GEOLOC_DS_TYPE))
85 
86 const char *ast_geoloc_datastore_get_id(struct ast_datastore *ds)
87 {
88  struct eprofiles_datastore *eds = NULL;
89 
90  if (!IS_GEOLOC_DS(ds)) {
91  return NULL;
92  }
93 
94  eds = (struct eprofiles_datastore *)ds->data;
95 
96  return eds->id;
97 }
98 
99 struct ast_datastore *ast_geoloc_datastore_create(const char *id)
100 {
101  struct ast_datastore *ds = NULL;
102  struct eprofiles_datastore *eds = NULL;
103  int rc = 0;
104 
105  if (ast_strlen_zero(id)) {
106  ast_log(LOG_ERROR, "A geoloc datastore can't be allocated with a NULL or empty id\n");
107  return NULL;
108  }
109 
110  ds = ast_datastore_alloc(&geoloc_datastore_info, NULL);
111  if (!ds) {
112  ast_log(LOG_ERROR, "Geoloc datastore '%s' couldn't be allocated\n", id);
113  return NULL;
114  }
115 
116  eds = ast_calloc(1, sizeof(*eds));
117  if (!eds) {
118  ast_datastore_free(ds);
119  ast_log(LOG_ERROR, "Private structure for geoloc datastore '%s' couldn't be allocated\n", id);
120  return NULL;
121  }
122  ds->data = eds;
123 
124 
125  rc = AST_VECTOR_INIT(&eds->eprofiles, 2);
126  if (rc != 0) {
127  ast_datastore_free(ds);
128  ast_log(LOG_ERROR, "Vector for geoloc datastore '%s' couldn't be initialized\n", id);
129  return NULL;
130  }
131 
132  return ds;
133 }
134 
135 int ast_geoloc_datastore_add_eprofile(struct ast_datastore *ds,
136  struct ast_geoloc_eprofile *eprofile)
137 {
138  struct eprofiles_datastore *eds = NULL;
139  int rc = 0;
140 
141  if (!IS_GEOLOC_DS(ds) || !eprofile) {
142  return -1;
143  }
144 
145  eds = ds->data;
146  rc = AST_VECTOR_APPEND(&eds->eprofiles, ao2_bump(eprofile));
147  if (rc != 0) {
148  ao2_ref(eprofile, -1);
149  ast_log(LOG_ERROR, "Couldn't add eprofile '%s' to geoloc datastore '%s'\n", eprofile->id, eds->id);
150  return -1;
151  }
152 
153  return AST_VECTOR_SIZE(&eds->eprofiles);
154 }
155 
156 int ast_geoloc_datastore_insert_eprofile(struct ast_datastore *ds,
157  struct ast_geoloc_eprofile *eprofile, int index)
158 {
159  struct eprofiles_datastore *eds = NULL;
160  int rc = 0;
161 
162  if (!IS_GEOLOC_DS(ds) || !eprofile) {
163  return -1;
164  }
165 
166  eds = ds->data;
167  rc = AST_VECTOR_INSERT_AT(&eds->eprofiles, index, ao2_bump(eprofile));
168  if (rc != 0) {
169  ao2_ref(eprofile, -1);
170  ast_log(LOG_ERROR, "Couldn't add eprofile '%s' to geoloc datastore '%s' in position '%d'\n",
171  eprofile->id, eds->id, index);
172  return -1;
173  }
174 
175  return AST_VECTOR_SIZE(&eds->eprofiles);
176 }
177 
178 int ast_geoloc_datastore_size(struct ast_datastore *ds)
179 {
180  struct eprofiles_datastore *eds = NULL;
181 
182  if (!IS_GEOLOC_DS(ds)) {
183  return -1;
184  }
185 
186  eds = ds->data;
187 
188  return AST_VECTOR_SIZE(&eds->eprofiles);
189 }
190 
191 int ast_geoloc_datastore_set_inheritance(struct ast_datastore *ds, int inherit)
192 {
193  if (!IS_GEOLOC_DS(ds)) {
194  return -1;
195  }
196  ds->inheritance = inherit ? DATASTORE_INHERIT_FOREVER : 0;
197  return 0;
198 }
199 
200 struct ast_geoloc_eprofile *ast_geoloc_datastore_get_eprofile(struct ast_datastore *ds, int ix)
201 {
202  struct eprofiles_datastore *eds = NULL;
203  struct ast_geoloc_eprofile *eprofile;
204 
205  if (!IS_GEOLOC_DS(ds)) {
206  return NULL;
207  }
208 
209  eds = ds->data;
210 
211  if (ix >= AST_VECTOR_SIZE(&eds->eprofiles)) {
212  return NULL;
213  }
214 
215  eprofile = AST_VECTOR_GET(&eds->eprofiles, ix);
216  return ao2_bump(eprofile);
217 }
218 
219 struct ast_datastore *ast_geoloc_datastore_find(struct ast_channel *chan)
220 {
221  return ast_channel_datastore_find(chan, &geoloc_datastore_info, NULL);
222 }
223 
224 int ast_geoloc_datastore_delete_eprofile(struct ast_datastore *ds, int ix)
225 {
226  struct eprofiles_datastore *eds = NULL;
227 
228  if (!IS_GEOLOC_DS(ds)) {
229  return -1;
230  }
231 
232  eds = ds->data;
233 
234  if (ix >= AST_VECTOR_SIZE(&eds->eprofiles)) {
235  return -1;
236  }
237 
238  ao2_ref(AST_VECTOR_REMOVE(&eds->eprofiles, ix, 1), -1);
239  return 0;
240 }
241 
242 struct ast_datastore *ast_geoloc_datastore_create_from_eprofile(
243  struct ast_geoloc_eprofile *eprofile)
244 {
245  struct ast_datastore *ds;
246  int rc = 0;
247 
248  if (!eprofile) {
249  return NULL;
250  }
251 
252  ds = ast_geoloc_datastore_create(eprofile->id);
253  if (!ds) {
254  return NULL;
255  }
256 
257  rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);
258  if (rc <= 0) {
259  ast_datastore_free(ds);
260  ds = NULL;
261  }
262 
263  return ds;
264 }
265 
266 struct ast_datastore *ast_geoloc_datastore_create_from_profile_name(const char *profile_name)
267 {
268  struct ast_datastore *ds = NULL;
269  struct ast_geoloc_eprofile *eprofile = NULL;
270  struct ast_geoloc_profile *profile = NULL;
271  int rc = 0;
272 
273  if (ast_strlen_zero(profile_name)) {
274  return NULL;
275  }
276 
277  profile = ast_sorcery_retrieve_by_id(geoloc_sorcery, "profile", profile_name);
278  if (!profile) {
279  ast_log(LOG_ERROR, "A profile with the name '%s' was not found\n", profile_name);
280  return NULL;
281  }
282 
283  ds = ast_geoloc_datastore_create(profile_name);
284  if (!ds) {
285  ast_log(LOG_ERROR, "A datastore couldn't be allocated for profile '%s'\n", profile_name);
286  ao2_ref(profile, -1);
287  return NULL;
288  }
289 
290  eprofile = ast_geoloc_eprofile_create_from_profile(profile);
291  ao2_ref(profile, -1);
292  if (!eprofile) {
293  ast_datastore_free(ds);
294  ast_log(LOG_ERROR, "An effective profile with the name '%s' couldn't be allocated\n", profile_name);
295  return NULL;
296  }
297 
298  rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);
299  ao2_ref(eprofile, -1);
300  if (rc <= 0) {
301  ast_datastore_free(ds);
302  ds = NULL;
303  }
304 
305  return ds;
306 }
307 
308 int geoloc_channel_unload(void)
309 {
310  if (geoloc_sorcery) {
311  ast_sorcery_unref(geoloc_sorcery);
312  }
314 }
315 
316 int geoloc_channel_load(void)
317 {
318  geoloc_sorcery = geoloc_get_sorcery();
320 }
321 
322 int geoloc_channel_reload(void)
323 {
325 }
const char * type
Definition: datastore.h:32
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
Full structure for sorcery.
Definition: sorcery.c:230
Structure for a data store type.
Definition: datastore.h:31
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
Definition: sorcery.h:1500
Asterisk datastore objects.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
General Asterisk PBX channel definitions.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
Vector container support.
unsigned int inheritance
Definition: datastore.h:69
void * data
Definition: datastore.h:66
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
#define AST_VECTOR_INSERT_AT(vec, idx, elem)
Insert an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:338
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609