sorcery: Prevent SEGV in sorcery_wizard_create when there's no create function
[asterisk/asterisk.git] / main / sorcery.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012 - 2013, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.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 /*! \file
20  *
21  * \brief Sorcery Data Access Layer API
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/logger.h"
35 #include "asterisk/sorcery.h"
36 #include "asterisk/astobj2.h"
37 #include "asterisk/format.h"
38 #include "asterisk/format_cap.h"
39 #include "asterisk/strings.h"
40 #include "asterisk/config_options.h"
41 #include "asterisk/netsock2.h"
42 #include "asterisk/module.h"
43 #include "asterisk/taskprocessor.h"
44 #include "asterisk/threadpool.h"
45 #include "asterisk/json.h"
46
47 /* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
48 #undef open
49 #undef close
50
51 /*! \brief Number of buckets for wizards (should be prime for performance reasons) */
52 #define WIZARD_BUCKETS 7
53
54 /*! \brief Number of buckets for types (should be prime for performance reasons) */
55 #define TYPE_BUCKETS 53
56
57 /*! \brief Number of buckets for instances (should be prime for performance reasons) */
58 #define INSTANCE_BUCKETS 17
59
60 /*! \brief Number of buckets for object fields (should be prime for performance reasons) */
61 #define OBJECT_FIELD_BUCKETS 29
62
63 /*! \brief Thread pool for observers */
64 static struct ast_threadpool *threadpool;
65
66 /*! \brief Structure for internal sorcery object information */
67 struct ast_sorcery_object {
68         /*! \brief Unique identifier of this object */
69         char *id;
70
71         /*! \brief Type of object */
72         char type[MAX_OBJECT_TYPE];
73
74         /*! \brief Optional object destructor */
75         ao2_destructor_fn destructor;
76
77         /*! \brief Extended object fields */
78         struct ast_variable *extended;
79 };
80
81 /*! \brief Structure for registered object type */
82 struct ast_sorcery_object_type {
83         /*! \brief Unique name of the object type */
84         char name[MAX_OBJECT_TYPE];
85
86         /*! \brief Optional transformation callback */
87         sorcery_transform_handler transform;
88
89         /*! \brief Optional object set apply callback */
90         sorcery_apply_handler apply;
91
92         /*! \brief Optional object copy callback */
93         sorcery_copy_handler copy;
94
95         /*! \brief Optional object diff callback */
96         sorcery_diff_handler diff;
97
98         /*! \brief Wizard instances */
99         struct ao2_container *wizards;
100
101         /*! \brief Object fields */
102         struct ao2_container *fields;
103
104         /*! \brief Configuration framework general information */
105         struct aco_info *info;
106
107         /*! \brief Configuration framework file information */
108         struct aco_file *file;
109
110         /*! \brief Type details */
111         struct aco_type type;
112
113         /*! \brief Observers */
114         struct ao2_container *observers;
115
116         /*! \brief Serializer for observers */
117         struct ast_taskprocessor *serializer;
118
119         /*! \brief Specifies if object type is reloadable or not */
120         unsigned int reloadable:1;
121 };
122
123 /*! \brief Structure for registered object type observer */
124 struct ast_sorcery_object_type_observer {
125         /*! \brief Pointer to the observer implementation */
126         const struct ast_sorcery_observer *callbacks;
127 };
128
129 /*! \brief Structure used for observer invocations */
130 struct sorcery_observer_invocation {
131         /*! \brief Pointer to the object type */
132         struct ast_sorcery_object_type *object_type;
133
134         /*! \brief Pointer to the object */
135         void *object;
136 };
137
138 /*! \brief Structure for registered object field */
139 struct ast_sorcery_object_field {
140         /*! \brief Name of the field */
141         char name[MAX_OBJECT_FIELD];
142
143         /*! \brief Callback function for translation of a single value */
144         sorcery_field_handler handler;
145
146         /*! \brief Callback function for translation of multiple values */
147         sorcery_fields_handler multiple_handler;
148
149         /*! \brief Position of the field */
150         intptr_t args[];
151 };
152
153 /*! \brief Structure for a wizard instance which operates on objects */
154 struct ast_sorcery_object_wizard {
155         /*! \brief Wizard interface itself */
156         struct ast_sorcery_wizard *wizard;
157
158         /*! \brief Unique data for the wizard */
159         void *data;
160
161         /*! \brief Wizard is acting as an object cache */
162         unsigned int caching:1;
163 };
164
165 /*! \brief Full structure for sorcery */
166 struct ast_sorcery {
167         /*! \brief Container for known object types */
168         struct ao2_container *types;
169         /*! \brief The name of the module owning this sorcery instance */
170         char module_name[0];
171 };
172
173 /*! \brief Structure for passing load/reload details */
174 struct sorcery_load_details {
175         /*! \brief Sorcery structure in use */
176         const struct ast_sorcery *sorcery;
177
178         /*! \brief Type of object being loaded */
179         const char *type;
180
181         /*! \brief Whether this is a reload or not */
182         unsigned int reload:1;
183 };
184
185 /*! \brief Registered sorcery wizards */
186 static struct ao2_container *wizards;
187
188 /*! \brief Registered sorcery instances */
189 static struct ao2_container *instances;
190
191 static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
192 {
193         int *field = (int *)(obj + args[0]);
194         return (ast_asprintf(buf, "%d", *field) < 0) ? -1 : 0;
195 }
196
197 static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
198 {
199         unsigned int *field = (unsigned int *)(obj + args[0]);
200         return (ast_asprintf(buf, "%u", *field) < 0) ? -1 : 0;
201 }
202
203 static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
204 {
205         double *field = (double *)(obj + args[0]);
206         return (ast_asprintf(buf, "%f", *field) < 0) ? -1 : 0;
207 }
208
209 static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
210 {
211         ast_string_field *field = (const char **)(obj + args[0]);
212         return !(*buf = ast_strdup(*field)) ? -1 : 0;
213 }
214
215 static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
216 {
217         unsigned int *field = (unsigned int *)(obj + args[0]);
218         return !(*buf = ast_strdup(*field ? "true" : "false")) ? -1 : 0;
219 }
220
221 static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
222 {
223         struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
224         return !(*buf = ast_strdup(ast_sockaddr_stringify(field))) ? -1 : 0;
225 }
226
227 static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
228 {
229         char *field = (char *)(obj + args[0]);
230         return !(*buf = ast_strdup(field)) ? -1 : 0;
231 }
232
233 static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
234 {
235         struct ast_str *codec_buf = ast_str_alloca(64);
236         struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[0]);
237         return !(*buf = ast_strdup(ast_format_cap_get_names(*cap, &codec_buf)));
238 }
239
240 static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
241 {
242         switch(type) {
243         case OPT_BOOL_T: return bool_handler_fn;
244         case OPT_CHAR_ARRAY_T: return chararray_handler_fn;
245         case OPT_CODEC_T: return codec_handler_fn;
246         case OPT_DOUBLE_T: return double_handler_fn;
247         case OPT_INT_T: return int_handler_fn;
248         case OPT_SOCKADDR_T: return sockaddr_handler_fn;
249         case OPT_STRINGFIELD_T: return stringfield_handler_fn;
250         case OPT_UINT_T: return uint_handler_fn;
251
252         default:
253         case OPT_CUSTOM_T: return NULL;
254         }
255
256         return NULL;
257 }
258
259 /*! \brief Hashing function for sorcery wizards */
260 static int sorcery_wizard_hash(const void *obj, const int flags)
261 {
262         const struct ast_sorcery_wizard *object;
263         const char *key;
264
265         switch (flags & OBJ_SEARCH_MASK) {
266         case OBJ_SEARCH_KEY:
267                 key = obj;
268                 break;
269         case OBJ_SEARCH_OBJECT:
270                 object = obj;
271                 key = object->name;
272                 break;
273         default:
274                 ast_assert(0);
275                 return 0;
276         }
277         return ast_str_hash(key);
278 }
279
280 /*! \brief Comparator function for sorcery wizards */
281 static int sorcery_wizard_cmp(void *obj, void *arg, int flags)
282 {
283         const struct ast_sorcery_wizard *object_left = obj;
284         const struct ast_sorcery_wizard *object_right = arg;
285         const char *right_key = arg;
286         int cmp;
287
288         switch (flags & OBJ_SEARCH_MASK) {
289         case OBJ_SEARCH_OBJECT:
290                 right_key = object_right->name;
291                 /* Fall through */
292         case OBJ_SEARCH_KEY:
293                 cmp = strcmp(object_left->name, right_key);
294                 break;
295         case OBJ_SEARCH_PARTIAL_KEY:
296                 cmp = strncmp(object_left->name, right_key, strlen(right_key));
297                 break;
298         default:
299                 cmp = 0;
300                 break;
301         }
302         if (cmp) {
303                 return 0;
304         }
305         return CMP_MATCH;
306 }
307
308 /*! \brief Hashing function for sorcery wizards */
309 static int object_type_field_hash(const void *obj, const int flags)
310 {
311         const struct ast_sorcery_object_field *object_field;
312         const char *key;
313
314         switch (flags & OBJ_SEARCH_MASK) {
315         case OBJ_SEARCH_KEY:
316                 key = obj;
317                 break;
318         case OBJ_SEARCH_OBJECT:
319                 object_field = obj;
320                 key = object_field->name;
321                 break;
322         default:
323                 ast_assert(0);
324                 return 0;
325         }
326         return ast_str_hash(key);
327 }
328
329 static int object_type_field_cmp(void *obj, void *arg, int flags)
330 {
331         const struct ast_sorcery_object_field *field_left = obj;
332         const struct ast_sorcery_object_field *field_right = arg;
333         const char *right_key = arg;
334         int cmp;
335
336         switch (flags & OBJ_SEARCH_MASK) {
337         case OBJ_SEARCH_OBJECT:
338                 right_key = field_right->name;
339                 /* Fall through */
340         case OBJ_SEARCH_KEY:
341                 cmp = strcmp(field_left->name, right_key);
342                 break;
343         case OBJ_SEARCH_PARTIAL_KEY:
344                 cmp = strncmp(field_left->name, right_key, strlen(right_key));
345                 break;
346         default:
347                 cmp = 0;
348                 break;
349         }
350         if (cmp) {
351                 return 0;
352         }
353         return CMP_MATCH;
354 }
355
356 /*! \brief Cleanup function */
357 static void sorcery_exit(void)
358 {
359         ast_threadpool_shutdown(threadpool);
360         threadpool = NULL;
361 }
362
363 /*! \brief Cleanup function for graceful shutdowns */
364 static void sorcery_cleanup(void)
365 {
366         ao2_cleanup(wizards);
367         wizards = NULL;
368         ao2_cleanup(instances);
369         instances = NULL;
370 }
371
372 /*! \brief Compare function for sorcery instances */
373 static int sorcery_instance_cmp(void *obj, void *arg, int flags)
374 {
375         const struct ast_sorcery *object_left = obj;
376         const struct ast_sorcery *object_right = arg;
377         const char *right_key = arg;
378         int cmp;
379
380         switch (flags & OBJ_SEARCH_MASK) {
381         case OBJ_SEARCH_OBJECT:
382                 right_key = object_right->module_name;
383                 /* Fall through */
384         case OBJ_SEARCH_KEY:
385                 cmp = strcmp(object_left->module_name, right_key);
386                 break;
387         case OBJ_SEARCH_PARTIAL_KEY:
388                 cmp = strncmp(object_left->module_name, right_key, strlen(right_key));
389                 break;
390         default:
391                 cmp = 0;
392                 break;
393         }
394         if (cmp) {
395                 return 0;
396         }
397         return CMP_MATCH;
398 }
399
400 /*! \brief Hashing function for sorcery instances */
401 static int sorcery_instance_hash(const void *obj, const int flags)
402 {
403         const struct ast_sorcery *object;
404         const char *key;
405
406         switch (flags & OBJ_SEARCH_MASK) {
407         case OBJ_SEARCH_KEY:
408                 key = obj;
409                 break;
410         case OBJ_SEARCH_OBJECT:
411                 object = obj;
412                 key = object->module_name;
413                 break;
414         default:
415                 ast_assert(0);
416                 return 0;
417         }
418         return ast_str_hash(key);
419 }
420
421 int ast_sorcery_init(void)
422 {
423         struct ast_threadpool_options options = {
424                 .version = AST_THREADPOOL_OPTIONS_VERSION,
425                 .auto_increment = 1,
426                 .max_size = 0,
427                 .idle_timeout = 60,
428                 .initial_size = 0,
429         };
430         ast_assert(wizards == NULL);
431
432         if (!(threadpool = ast_threadpool_create("Sorcery", NULL, &options))) {
433                 threadpool = NULL;
434                 return -1;
435         }
436
437         if (!(wizards = ao2_container_alloc(WIZARD_BUCKETS, sorcery_wizard_hash, sorcery_wizard_cmp))) {
438                 ast_threadpool_shutdown(threadpool);
439                 return -1;
440         }
441
442         instances = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, INSTANCE_BUCKETS,
443                 sorcery_instance_hash, sorcery_instance_cmp);
444         if (!instances) {
445                 sorcery_cleanup();
446                 sorcery_exit();
447                 return -1;
448         }
449
450         ast_register_cleanup(sorcery_cleanup);
451         ast_register_atexit(sorcery_exit);
452
453         return 0;
454 }
455
456 int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
457 {
458         struct ast_sorcery_wizard *wizard;
459         int res = -1;
460
461         ast_assert(!ast_strlen_zero(interface->name));
462
463         ao2_lock(wizards);
464
465         if ((wizard = ao2_find(wizards, interface->name, OBJ_KEY | OBJ_NOLOCK))) {
466                 ast_log(LOG_WARNING, "Attempted to register sorcery wizard '%s' twice\n",
467                         interface->name);
468                 goto done;
469         }
470
471         if (!(wizard = ao2_alloc(sizeof(*wizard), NULL))) {
472                 goto done;
473         }
474
475         *wizard = *interface;
476         wizard->module = module;
477
478         ao2_link_flags(wizards, wizard, OBJ_NOLOCK);
479         res = 0;
480
481         ast_verb(2, "Sorcery registered wizard '%s'\n", interface->name);
482
483 done:
484         ao2_cleanup(wizard);
485         ao2_unlock(wizards);
486
487         return res;
488 }
489
490 int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
491 {
492         RAII_VAR(struct ast_sorcery_wizard *, wizard, ao2_find(wizards, interface->name, OBJ_KEY | OBJ_UNLINK), ao2_cleanup);
493
494         if (wizard) {
495                 ast_verb(2, "Sorcery unregistered wizard '%s'\n", interface->name);
496                 return 0;
497         } else {
498                 return -1;
499         }
500 }
501
502 /*! \brief Destructor called when sorcery structure is destroyed */
503 static void sorcery_destructor(void *obj)
504 {
505         struct ast_sorcery *sorcery = obj;
506
507         ao2_cleanup(sorcery->types);
508 }
509
510 /*! \brief Hashing function for sorcery types */
511 static int sorcery_type_hash(const void *obj, const int flags)
512 {
513         const struct ast_sorcery_object_type *object;
514         const char *key;
515
516         switch (flags & OBJ_SEARCH_MASK) {
517         case OBJ_SEARCH_KEY:
518                 key = obj;
519                 break;
520         case OBJ_SEARCH_OBJECT:
521                 object = obj;
522                 key = object->name;
523                 break;
524         default:
525                 ast_assert(0);
526                 return 0;
527         }
528         return ast_str_hash(key);
529 }
530
531 /*! \brief Comparator function for sorcery types */
532 static int sorcery_type_cmp(void *obj, void *arg, int flags)
533 {
534         const struct ast_sorcery_object_type *object_left = obj;
535         const struct ast_sorcery_object_type *object_right = arg;
536         const char *right_key = arg;
537         int cmp;
538
539         switch (flags & OBJ_SEARCH_MASK) {
540         case OBJ_SEARCH_OBJECT:
541                 right_key = object_right->name;
542                 /* Fall through */
543         case OBJ_SEARCH_KEY:
544                 cmp = strcmp(object_left->name, right_key);
545                 break;
546         case OBJ_SEARCH_PARTIAL_KEY:
547                 cmp = strncmp(object_left->name, right_key, strlen(right_key));
548                 break;
549         default:
550                 cmp = 0;
551                 break;
552         }
553         if (cmp) {
554                 return 0;
555         }
556         return CMP_MATCH;
557 }
558
559 struct ast_sorcery *__ast_sorcery_open(const char *module_name)
560 {
561         struct ast_sorcery *sorcery;
562
563         ast_assert(module_name != NULL);
564
565         ao2_wrlock(instances);
566         if ((sorcery = ao2_find(instances, module_name, OBJ_SEARCH_KEY | OBJ_NOLOCK))) {
567                 goto done;
568         }
569
570         if (!(sorcery = ao2_alloc(sizeof(*sorcery) + strlen(module_name) + 1, sorcery_destructor))) {
571                 goto done;
572         }
573
574         if (!(sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, TYPE_BUCKETS, sorcery_type_hash, sorcery_type_cmp))) {
575                 ao2_ref(sorcery, -1);
576                 sorcery = NULL;
577                 goto done;
578         }
579
580         strcpy(sorcery->module_name, module_name); /* Safe */
581
582         if (__ast_sorcery_apply_config(sorcery, module_name, module_name) == AST_SORCERY_APPLY_FAIL) {
583                 ast_log(LOG_ERROR, "Error attempting to apply configuration %s to sorcery.\n", module_name);
584                 ao2_cleanup(sorcery);
585                 sorcery = NULL;
586                 goto done;
587         }
588
589         ao2_link_flags(instances, sorcery, OBJ_NOLOCK);
590
591 done:
592         ao2_unlock(instances);
593         return sorcery;
594 }
595
596 /*! \brief Search function for sorcery instances */
597 struct ast_sorcery *ast_sorcery_retrieve_by_module_name(const char *module_name)
598 {
599         return ao2_find(instances, module_name, OBJ_SEARCH_KEY);
600 }
601
602 /*! \brief Destructor function for object types */
603 static void sorcery_object_type_destructor(void *obj)
604 {
605         struct ast_sorcery_object_type *object_type = obj;
606
607         ao2_cleanup(object_type->wizards);
608         ao2_cleanup(object_type->fields);
609         ao2_cleanup(object_type->observers);
610
611         if (object_type->info) {
612                 aco_info_destroy(object_type->info);
613                 ast_free(object_type->info);
614         }
615
616         ast_free(object_type->file);
617
618         ast_taskprocessor_unreference(object_type->serializer);
619 }
620
621 /*! \brief Internal function which allocates an object type structure */
622 static struct ast_sorcery_object_type *sorcery_object_type_alloc(const char *type, const char *module)
623 {
624         struct ast_sorcery_object_type *object_type;
625         char uuid[AST_UUID_STR_LEN];
626
627         if (!(object_type = ao2_alloc(sizeof(*object_type), sorcery_object_type_destructor))) {
628                 return NULL;
629         }
630
631         /* Order matters for object wizards */
632         if (!(object_type->wizards = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, sorcery_wizard_cmp))) {
633                 ao2_ref(object_type, -1);
634                 return NULL;
635         }
636
637         if (!(object_type->fields = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, OBJECT_FIELD_BUCKETS,
638                                         object_type_field_hash, object_type_field_cmp))) {
639                 ao2_ref(object_type, -1);
640                 return NULL;
641         }
642
643         if (!(object_type->observers = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, 1, NULL, NULL))) {
644                 ao2_ref(object_type, -1);
645                 return NULL;
646         }
647
648         if (!(object_type->info = ast_calloc(1, sizeof(*object_type->info) + 2 * sizeof(object_type->info->files[0])))) {
649                 ao2_ref(object_type, -1);
650                 return NULL;
651         }
652
653         if (!(object_type->file = ast_calloc(1, sizeof(*object_type->file) + 2 * sizeof(object_type->file->types[0])))) {
654                 ao2_ref(object_type, -1);
655                 return NULL;
656         }
657
658         if (!ast_uuid_generate_str(uuid, sizeof(uuid))) {
659                 ao2_ref(object_type, -1);
660                 return NULL;
661         }
662
663         if (!(object_type->serializer = ast_threadpool_serializer(uuid, threadpool))) {
664                 ao2_ref(object_type, -1);
665                 return NULL;
666         }
667
668         object_type->info->files[0] = object_type->file;
669         object_type->info->files[1] = NULL;
670         object_type->info->module = module;
671
672         ast_copy_string(object_type->name, type, sizeof(object_type->name));
673
674         return object_type;
675 }
676
677 /*! \brief Object wizard destructor */
678 static void sorcery_object_wizard_destructor(void *obj)
679 {
680         struct ast_sorcery_object_wizard *object_wizard = obj;
681
682         if (object_wizard->data) {
683                 object_wizard->wizard->close(object_wizard->data);
684         }
685
686         if (object_wizard->wizard) {
687                 ast_module_unref(object_wizard->wizard->module);
688         }
689
690         ao2_cleanup(object_wizard->wizard);
691 }
692
693 /*! \brief Internal function which creates an object type and adds a wizard mapping */
694 static enum ast_sorcery_apply_result sorcery_apply_wizard_mapping(struct ast_sorcery *sorcery,
695                 const char *type, const char *module, const char *name, const char *data, unsigned int caching)
696 {
697         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
698         RAII_VAR(struct ast_sorcery_wizard *, wizard, ao2_find(wizards, name, OBJ_KEY), ao2_cleanup);
699         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, ao2_alloc(sizeof(*object_wizard), sorcery_object_wizard_destructor), ao2_cleanup);
700         int created = 0;
701
702         if (!wizard || !object_wizard) {
703                 return AST_SORCERY_APPLY_FAIL;
704         }
705
706         if (!object_type) {
707                 if (!(object_type = sorcery_object_type_alloc(type, module))) {
708                         return AST_SORCERY_APPLY_FAIL;
709                 }
710                 created = 1;
711         }
712
713         if (!created) {
714                 struct ast_sorcery_wizard *found;
715
716                 found = ao2_find(object_type->wizards, wizard, OBJ_SEARCH_OBJECT);
717                 if (found) {
718                         ast_debug(1, "Wizard %s already applied to object type %s\n",
719                                         wizard->name, object_type->name);
720                         ao2_cleanup(found);
721                         return AST_SORCERY_APPLY_DUPLICATE;
722                 }
723         }
724
725         if (wizard->open && !(object_wizard->data = wizard->open(data))) {
726                 return AST_SORCERY_APPLY_FAIL;
727         }
728
729         ast_module_ref(wizard->module);
730
731         object_wizard->wizard = ao2_bump(wizard);
732         object_wizard->caching = caching;
733
734         ao2_link(object_type->wizards, object_wizard);
735
736         if (created) {
737                 ao2_link(sorcery->types, object_type);
738         }
739
740         return AST_SORCERY_APPLY_SUCCESS;
741 }
742
743 enum ast_sorcery_apply_result  __ast_sorcery_apply_config(struct ast_sorcery *sorcery, const char *name, const char *module)
744 {
745         struct ast_flags flags = { 0 };
746         struct ast_config *config = ast_config_load2("sorcery.conf", "sorcery", flags);
747         struct ast_variable *mapping;
748         int res = AST_SORCERY_APPLY_SUCCESS;
749
750         if (!config) {
751                 return AST_SORCERY_APPLY_NO_CONFIGURATION;
752         }
753
754         if (config == CONFIG_STATUS_FILEINVALID) {
755                 return AST_SORCERY_APPLY_FAIL;
756         }
757
758         for (mapping = ast_variable_browse(config, name); mapping; mapping = mapping->next) {
759                 RAII_VAR(char *, mapping_name, ast_strdup(mapping->name), ast_free);
760                 RAII_VAR(char *, mapping_value, ast_strdup(mapping->value), ast_free);
761                 char *options = mapping_name;
762                 char *type = strsep(&options, "/");
763                 char *data = mapping_value;
764                 char *wizard = strsep(&data, ",");
765                 unsigned int caching = 0;
766
767                 /* If no object type or wizard exists just skip, nothing we can do */
768                 if (ast_strlen_zero(type) || ast_strlen_zero(wizard)) {
769                         continue;
770                 }
771
772                 /* If the wizard is configured as a cache treat it as such */
773                 if (!ast_strlen_zero(options) && strstr(options, "cache")) {
774                         caching = 1;
775                 }
776
777                 /* Any error immediately causes us to stop */
778                 if (sorcery_apply_wizard_mapping(sorcery, type, module, wizard, data, caching) == AST_SORCERY_APPLY_FAIL) {
779                         res = AST_SORCERY_APPLY_FAIL;
780                         break;
781                 }
782         }
783
784         ast_config_destroy(config);
785
786         return res;
787 }
788
789 enum ast_sorcery_apply_result __ast_sorcery_apply_default(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data)
790 {
791         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
792
793         /* Defaults can not be added if any existing mapping exists */
794         if (object_type) {
795                 return AST_SORCERY_APPLY_DEFAULT_UNNECESSARY;
796         }
797
798         return sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0);
799 }
800
801 static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
802 {
803         return ast_sorcery_object_set_extended(obj, var->name, var->value);
804 }
805
806 static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
807 {
808         const struct ast_sorcery_object_details *details = obj;
809
810         if (details->object->extended) {
811                 *fields = ast_variables_dup(details->object->extended);
812         } else {
813                 *fields = NULL;
814         }
815
816         return 0;
817 }
818
819 int __ast_sorcery_object_register(struct ast_sorcery *sorcery, const char *type, unsigned int hidden, unsigned int reloadable, aco_type_item_alloc alloc, sorcery_transform_handler transform, sorcery_apply_handler apply)
820 {
821         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
822
823         if (!object_type || object_type->type.item_alloc) {
824                 return -1;
825         }
826
827         object_type->type.name = object_type->name;
828         object_type->type.type = ACO_ITEM;
829         object_type->type.category = ".?";
830         object_type->type.item_alloc = alloc;
831         object_type->type.hidden = hidden;
832
833         object_type->reloadable = reloadable;
834         object_type->transform = transform;
835         object_type->apply = apply;
836         object_type->file->types[0] = &object_type->type;
837         object_type->file->types[1] = NULL;
838
839         if (aco_info_init(object_type->info)) {
840                 return -1;
841         }
842
843         if (ast_sorcery_object_fields_register(sorcery, type, "^@", sorcery_extended_config_handler, sorcery_extended_fields_handler)) {
844                 return -1;
845         }
846
847         return 0;
848 }
849
850 void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy)
851 {
852         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
853
854         if (!object_type) {
855                 return;
856         }
857
858         object_type->copy = copy;
859 }
860
861 void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff)
862 {
863         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
864
865         if (!object_type) {
866                 return;
867         }
868
869         object_type->diff = diff;
870 }
871
872 int ast_sorcery_object_fields_register(struct ast_sorcery *sorcery, const char *type, const char *regex, aco_option_handler config_handler, sorcery_fields_handler sorcery_handler)
873 {
874         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
875         RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
876
877         if (!object_type || !object_type->type.item_alloc || !config_handler || !(object_field = ao2_alloc(sizeof(*object_field), NULL))) {
878                 return -1;
879         }
880
881         ast_copy_string(object_field->name, regex, sizeof(object_field->name));
882         object_field->multiple_handler = sorcery_handler;
883
884         ao2_link(object_type->fields, object_field);
885         __aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
886
887         return 0;
888 }
889
890 int __ast_sorcery_object_field_register(struct ast_sorcery *sorcery, const char *type, const char *name, const char *default_val, enum aco_option_type opt_type,
891                                         aco_option_handler config_handler, sorcery_field_handler sorcery_handler, sorcery_fields_handler multiple_handler, unsigned int flags, unsigned int no_doc, unsigned int alias, size_t argc, ...)
892 {
893         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
894         RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
895         int pos;
896         va_list args;
897
898         if (!strcmp(type, "id") || !object_type || !object_type->type.item_alloc) {
899                 return -1;
900         }
901
902         if (!sorcery_handler) {
903                 sorcery_handler = sorcery_field_default_handler(opt_type);
904         }
905
906         if (!(object_field = ao2_alloc(sizeof(*object_field) + argc * sizeof(object_field->args[0]), NULL))) {
907                 return -1;
908         }
909
910         ast_copy_string(object_field->name, name, sizeof(object_field->name));
911         object_field->handler = sorcery_handler;
912         object_field->multiple_handler = multiple_handler;
913
914         va_start(args, argc);
915         for (pos = 0; pos < argc; pos++) {
916                 object_field->args[pos] = va_arg(args, size_t);
917         }
918         va_end(args);
919
920         if (!alias) {
921                 ao2_link(object_type->fields, object_field);
922         }
923
924         /* TODO: Improve this hack */
925         if (!argc) {
926                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc);
927         } else if (argc == 1) {
928                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
929                         object_field->args[0]);
930         } else if (argc == 2) {
931                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
932                         object_field->args[0], object_field->args[1]);
933         } else if (argc == 3) {
934                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
935                         object_field->args[0], object_field->args[1], object_field->args[2]);
936         } else {
937                 ast_assert(0); /* The hack... she does us no good for this */
938         }
939
940         return 0;
941 }
942
943 /*! \brief Retrieves whether or not the type is reloadable */
944 static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
945 {
946         RAII_VAR(struct ast_sorcery_object_type *, object_type,
947                  ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
948         return object_type && object_type->reloadable;
949 }
950
951 static int sorcery_wizard_load(void *obj, void *arg, int flags)
952 {
953         struct ast_sorcery_object_wizard *wizard = obj;
954         struct sorcery_load_details *details = arg;
955         void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
956
957         if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
958                 ast_log(LOG_NOTICE, "Type '%s' is not reloadable, "
959                         "maintaining previous values\n", details->type);
960                 return 0;
961         }
962
963         load = !details->reload ? wizard->wizard->load : wizard->wizard->reload;
964
965         if (load) {
966                 load(wizard->data, details->sorcery, details->type);
967         }
968
969         return 0;
970 }
971
972 /*! \brief Destructor for observer invocation */
973 static void sorcery_observer_invocation_destroy(void *obj)
974 {
975         struct sorcery_observer_invocation *invocation = obj;
976
977         ao2_cleanup(invocation->object_type);
978         ao2_cleanup(invocation->object);
979 }
980
981 /*! \brief Allocator function for observer invocation */
982 static struct sorcery_observer_invocation *sorcery_observer_invocation_alloc(struct ast_sorcery_object_type *object_type, void *object)
983 {
984         struct sorcery_observer_invocation *invocation = ao2_alloc(sizeof(*invocation), sorcery_observer_invocation_destroy);
985
986         if (!invocation) {
987                 return NULL;
988         }
989
990         ao2_ref(object_type, +1);
991         invocation->object_type = object_type;
992
993         if (object) {
994                 ao2_ref(object, +1);
995                 invocation->object = object;
996         }
997
998         return invocation;
999 }
1000
1001 /*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
1002 static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
1003 {
1004         const struct ast_sorcery_object_type_observer *observer = obj;
1005
1006         if (observer->callbacks->loaded) {
1007                 observer->callbacks->loaded(arg);
1008         }
1009
1010         return 0;
1011 }
1012
1013 /*! \brief Internal callback function which notifies observers that an object type has been loaded */
1014 static int sorcery_observers_notify_loaded(void *data)
1015 {
1016         struct sorcery_observer_invocation *invocation = data;
1017
1018         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_loaded, invocation->object_type->name);
1019         ao2_cleanup(invocation);
1020
1021         return 0;
1022 }
1023
1024 static int sorcery_object_load(void *obj, void *arg, int flags)
1025 {
1026         struct ast_sorcery_object_type *type = obj;
1027         struct sorcery_load_details *details = arg;
1028
1029         details->type = type->name;
1030         ao2_callback(type->wizards, OBJ_NODATA, sorcery_wizard_load, details);
1031
1032         if (ao2_container_count(type->observers)) {
1033                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(type, NULL);
1034
1035                 if (invocation && ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded, invocation)) {
1036                         ao2_cleanup(invocation);
1037                 }
1038         }
1039
1040         return 0;
1041 }
1042
1043 void ast_sorcery_load(const struct ast_sorcery *sorcery)
1044 {
1045         struct sorcery_load_details details = {
1046                 .sorcery = sorcery,
1047                 .reload = 0,
1048         };
1049
1050         ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
1051 }
1052
1053 void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
1054 {
1055         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1056         struct sorcery_load_details details = {
1057                 .sorcery = sorcery,
1058                 .reload = 0,
1059         };
1060
1061         if (!object_type) {
1062                 return;
1063         }
1064
1065         sorcery_object_load(object_type, &details, 0);
1066 }
1067
1068 void ast_sorcery_reload(const struct ast_sorcery *sorcery)
1069 {
1070         struct sorcery_load_details details = {
1071                 .sorcery = sorcery,
1072                 .reload = 1,
1073         };
1074
1075         ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
1076 }
1077
1078 void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
1079 {
1080         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1081         struct sorcery_load_details details = {
1082                 .sorcery = sorcery,
1083                 .reload = 1,
1084         };
1085
1086         if (!object_type) {
1087                 return;
1088         }
1089
1090         sorcery_object_load(object_type, &details, 0);
1091 }
1092
1093 void ast_sorcery_ref(struct ast_sorcery *sorcery)
1094 {
1095         ao2_ref(sorcery, +1);
1096 }
1097
1098 static struct ast_variable *get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1099 {
1100         struct ast_variable *tmp = NULL;
1101         char *buf = NULL;
1102
1103         if (!object_field->handler) {
1104                 return NULL;
1105         }
1106
1107         if (!(object_field->handler(object, object_field->args, &buf))) {
1108                 tmp = ast_variable_new(object_field->name, S_OR(buf, ""), "");
1109         }
1110         ast_free(buf);
1111
1112         return tmp;
1113 }
1114
1115 static struct ast_variable *get_multiple_fields_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1116 {
1117         struct ast_variable *tmp = NULL;
1118
1119         if (!object_field->multiple_handler) {
1120                 return NULL;
1121         }
1122
1123         if (object_field->multiple_handler(object, &tmp)) {
1124                 ast_variables_destroy(tmp);
1125                 tmp = NULL;
1126         }
1127
1128         return tmp;
1129 }
1130
1131 struct ast_variable *ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery,
1132         const void *object,     enum ast_sorcery_field_handler_flags flags)
1133 {
1134         const struct ast_sorcery_object_details *details = object;
1135         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1136         struct ao2_iterator i;
1137         struct ast_sorcery_object_field *object_field;
1138         struct ast_variable *head = NULL;
1139         struct ast_variable *tail = NULL;
1140
1141         if (!object_type) {
1142                 return NULL;
1143         }
1144
1145         i = ao2_iterator_init(object_type->fields, 0);
1146
1147         for (; (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1148                 struct ast_variable *tmp;
1149
1150                 switch (flags) {
1151                 case AST_HANDLER_PREFER_LIST:
1152                         if ((tmp = get_multiple_fields_as_var_list(object, object_field)) ||
1153                                 (tmp = get_single_field_as_var_list(object, object_field))) {
1154                                 break;
1155                         }
1156                         continue;
1157                 case AST_HANDLER_PREFER_STRING:
1158                         if ((tmp = get_single_field_as_var_list(object, object_field)) ||
1159                                 (tmp = get_multiple_fields_as_var_list(object, object_field))) {
1160                                 break;
1161                         }
1162                         continue;
1163                 case AST_HANDLER_ONLY_LIST:
1164                         if ((tmp = get_multiple_fields_as_var_list(object, object_field))) {
1165                                 break;
1166                         }
1167                         continue;
1168                 case AST_HANDLER_ONLY_STRING:
1169                         if ((tmp = get_single_field_as_var_list(object, object_field))) {
1170                                 break;
1171                         }
1172                         continue;
1173                 default:
1174                         continue;
1175                 }
1176
1177                 tail = ast_variable_list_append_hint(&head, tail, tmp);
1178         }
1179
1180         ao2_iterator_destroy(&i);
1181
1182         return head;
1183 }
1184
1185 struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
1186 {
1187         const struct ast_sorcery_object_details *details = object;
1188         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1189         struct ao2_iterator i;
1190         struct ast_sorcery_object_field *object_field;
1191         struct ast_json *json = ast_json_object_create();
1192         int res = 0;
1193
1194         if (!object_type || !json) {
1195                 return NULL;
1196         }
1197
1198         i = ao2_iterator_init(object_type->fields, 0);
1199
1200         for (; !res && (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1201                 if (object_field->multiple_handler) {
1202                         struct ast_variable *tmp = NULL;
1203                         struct ast_variable *field;
1204
1205                         if ((res = object_field->multiple_handler(object, &tmp))) {
1206                                 ast_variables_destroy(tmp);
1207                                 ao2_ref(object_field, -1);
1208                                 break;
1209                         }
1210
1211                         for (field = tmp; field; field = field->next) {
1212                                 struct ast_json *value = ast_json_string_create(field->value);
1213
1214                                 if (!value || ast_json_object_set(json, field->name, value)) {
1215                                         res = -1;
1216                                         break;
1217                                 }
1218                         }
1219
1220                         ast_variables_destroy(tmp);
1221                 } else if (object_field->handler) {
1222                         char *buf = NULL;
1223                         struct ast_json *value = NULL;
1224
1225                         if ((res = object_field->handler(object, object_field->args, &buf))
1226                                 || !(value = ast_json_string_create(buf))
1227                                 || ast_json_object_set(json, object_field->name, value)) {
1228                                 res = -1;
1229                         }
1230
1231                         ast_free(buf);
1232                 } else {
1233                         continue;
1234                 }
1235         }
1236
1237         ao2_iterator_destroy(&i);
1238
1239         /* If any error occurs we destroy the JSON object so a partial objectset is not returned */
1240         if (res) {
1241                 ast_json_unref(json);
1242                 json = NULL;
1243         }
1244
1245         return json;
1246 }
1247
1248 int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
1249 {
1250         const struct ast_sorcery_object_details *details = object;
1251         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1252         RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy);
1253         struct ast_variable *field;
1254         int res = 0;
1255
1256         if (!object_type) {
1257                 return -1;
1258         }
1259
1260         if (object_type->transform && (transformed = object_type->transform(objectset))) {
1261                 field = transformed;
1262         } else {
1263                 field = objectset;
1264         }
1265
1266         for (; field; field = field->next) {
1267                 if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) {
1268                         break;
1269                 }
1270         }
1271
1272         if (!res && object_type->apply) {
1273                 res = object_type->apply(sorcery, object);
1274         }
1275
1276         return res;
1277 }
1278
1279 static const struct ast_variable *sorcery_find_field(const struct ast_variable *fields, const char *name)
1280 {
1281         const struct ast_variable *field;
1282
1283         /* Search the linked list of fields to find the correct one */
1284         for (field = fields; field; field = field->next) {
1285                 if (!strcmp(field->name, name)) {
1286                         return field;
1287                 }
1288         }
1289
1290         return NULL;
1291 }
1292
1293 int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
1294 {
1295         const struct ast_variable *field;
1296         int res = 0;
1297
1298         *changes = NULL;
1299
1300         /* Unless the ast_variable list changes when examined... it can't differ from itself */
1301         if (original == modified) {
1302                 return 0;
1303         }
1304
1305         for (field = modified; field; field = field->next) {
1306                 const struct ast_variable *old = sorcery_find_field(original, field->name);
1307
1308                 if (!old || strcmp(old->value, field->value)) {
1309                         struct ast_variable *tmp;
1310
1311                         if (!(tmp = ast_variable_new(field->name, field->value, ""))) {
1312                                 res = -1;
1313                                 break;
1314                         }
1315
1316                         tmp->next = *changes;
1317                         *changes = tmp;
1318                 }
1319         }
1320
1321         /* If an error occurred do not return a partial changeset */
1322         if (res) {
1323                 ast_variables_destroy(*changes);
1324                 *changes = NULL;
1325         }
1326
1327         return res;
1328 }
1329
1330 static void sorcery_object_destructor(void *object)
1331 {
1332         struct ast_sorcery_object_details *details = object;
1333
1334         if (details->object->destructor) {
1335                 details->object->destructor(object);
1336         }
1337
1338         ast_variables_destroy(details->object->extended);
1339         ast_free(details->object->id);
1340 }
1341
1342 void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
1343 {
1344         void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
1345         struct ast_sorcery_object_details *details = object;
1346
1347         if (!object) {
1348                 return NULL;
1349         }
1350
1351         details->object = object + size;
1352         details->object->destructor = destructor;
1353
1354         return object;
1355 }
1356
1357 void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
1358 {
1359         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1360         struct ast_sorcery_object_details *details;
1361
1362         if (!object_type || !object_type->type.item_alloc ||
1363                 !(details = object_type->type.item_alloc(id))) {
1364                 return NULL;
1365         }
1366
1367         if (ast_strlen_zero(id)) {
1368                 char uuid[AST_UUID_STR_LEN];
1369
1370                 ast_uuid_generate_str(uuid, sizeof(uuid));
1371                 details->object->id = ast_strdup(uuid);
1372         } else {
1373                 details->object->id = ast_strdup(id);
1374         }
1375
1376         ast_copy_string(details->object->type, type, sizeof(details->object->type));
1377
1378         if (aco_set_defaults(&object_type->type, id, details)) {
1379                 ao2_ref(details, -1);
1380                 return NULL;
1381         }
1382
1383         return details;
1384 }
1385
1386 void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
1387 {
1388         const struct ast_sorcery_object_details *details = object;
1389         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1390         struct ast_sorcery_object_details *copy = ast_sorcery_alloc(sorcery, details->object->type, details->object->id);
1391         RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
1392         int res = 0;
1393
1394         if (!copy) {
1395                 return NULL;
1396         } else if (object_type->copy) {
1397                 res = object_type->copy(object, copy);
1398         } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
1399                 res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
1400         } else {
1401                 /* No native copy available and could not create an objectset, this copy has failed */
1402                 res = -1;
1403         }
1404
1405         if (res) {
1406                 ao2_cleanup(copy);
1407                 copy = NULL;
1408         }
1409
1410         return copy;
1411 }
1412
1413 int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
1414 {
1415         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, ast_sorcery_object_get_type(original), OBJ_KEY), ao2_cleanup);
1416
1417         *changes = NULL;
1418
1419         if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
1420                 return -1;
1421         }
1422
1423         if (original == modified) {
1424                 return 0;
1425         } else if (!object_type->diff) {
1426                 RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
1427                 RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
1428
1429                 objectset1 = ast_sorcery_objectset_create(sorcery, original);
1430                 objectset2 = ast_sorcery_objectset_create(sorcery, modified);
1431
1432                 return ast_sorcery_changeset_create(objectset1, objectset2, changes);
1433         } else {
1434                 return object_type->diff(original, modified, changes);
1435         }
1436 }
1437
1438 /*! \brief Structure used when calling create, update, or delete */
1439 struct sorcery_details {
1440         /*! \brief Pointer to the sorcery instance */
1441         const struct ast_sorcery *sorcery;
1442         /*! \brief Pointer to the object itself */
1443         void *obj;
1444 };
1445
1446 /*! \brief Internal function used to create an object in caching wizards */
1447 static int sorcery_cache_create(void *obj, void *arg, int flags)
1448 {
1449         const struct ast_sorcery_object_wizard *object_wizard = obj;
1450         const struct sorcery_details *details = arg;
1451
1452         if (!object_wizard->caching || !object_wizard->wizard->create) {
1453                 return 0;
1454         }
1455
1456         object_wizard->wizard->create(details->sorcery, object_wizard->data, details->obj);
1457
1458         return 0;
1459 }
1460
1461 void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
1462 {
1463         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1464         void *object = NULL;
1465         struct ao2_iterator i;
1466         struct ast_sorcery_object_wizard *wizard;
1467         unsigned int cached = 0;
1468
1469         if (!object_type || ast_strlen_zero(id)) {
1470                 return NULL;
1471         }
1472
1473         i = ao2_iterator_init(object_type->wizards, 0);
1474         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1475                 if (wizard->wizard->retrieve_id &&
1476                         !(object = wizard->wizard->retrieve_id(sorcery, wizard->data, object_type->name, id))) {
1477                         continue;
1478                 }
1479
1480                 cached = wizard->caching;
1481
1482                 ao2_ref(wizard, -1);
1483                 break;
1484         }
1485         ao2_iterator_destroy(&i);
1486
1487         if (!cached && object) {
1488                 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1489         }
1490
1491         return object;
1492 }
1493
1494 void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
1495 {
1496         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1497         void *object = NULL;
1498         struct ao2_iterator i;
1499         struct ast_sorcery_object_wizard *wizard;
1500         unsigned int cached = 0;
1501
1502         if (!object_type) {
1503                 return NULL;
1504         }
1505
1506         /* If returning multiple objects create a container to store them in */
1507         if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1508                 if (!(object = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1509                         return NULL;
1510                 }
1511         }
1512
1513         /* Inquire with the available wizards for retrieval */
1514         i = ao2_iterator_init(object_type->wizards, 0);
1515         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1516                 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1517                         if (wizard->wizard->retrieve_multiple) {
1518                                 wizard->wizard->retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
1519                         }
1520                 } else if (fields && wizard->wizard->retrieve_fields) {
1521                         if (wizard->wizard->retrieve_fields) {
1522                                 object = wizard->wizard->retrieve_fields(sorcery, wizard->data, object_type->name, fields);
1523                         }
1524                 }
1525
1526                 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE) || !object) {
1527                         continue;
1528                 }
1529
1530                 cached = wizard->caching;
1531
1532                 ao2_ref(wizard, -1);
1533                 break;
1534         }
1535         ao2_iterator_destroy(&i);
1536
1537         /* If we are returning a single object and it came from a non-cache source create it in any caches */
1538         if (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) && !cached && object) {
1539                 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1540         }
1541
1542         return object;
1543 }
1544
1545 struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
1546 {
1547         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1548         struct ao2_container *objects;
1549         struct ao2_iterator i;
1550         struct ast_sorcery_object_wizard *wizard;
1551
1552         if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1553                 return NULL;
1554         }
1555
1556         i = ao2_iterator_init(object_type->wizards, 0);
1557         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1558                 if (!wizard->wizard->retrieve_regex) {
1559                         continue;
1560                 }
1561
1562                 wizard->wizard->retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
1563         }
1564         ao2_iterator_destroy(&i);
1565
1566         return objects;
1567 }
1568
1569 /*! \brief Internal function which returns if the wizard has created the object */
1570 static int sorcery_wizard_create(void *obj, void *arg, int flags)
1571 {
1572         const struct ast_sorcery_object_wizard *object_wizard = obj;
1573         const struct sorcery_details *details = arg;
1574
1575         if (!object_wizard->wizard->create) {
1576                 ast_assert(0);
1577                 ast_log(LOG_ERROR, "Sorcery wizard '%s' doesn't contain a 'create' virtual function.\n",
1578                         object_wizard->wizard->name);
1579                 return 0;
1580         }
1581         return (!object_wizard->caching && !object_wizard->wizard->create(details->sorcery, object_wizard->data, details->obj)) ? CMP_MATCH | CMP_STOP : 0;
1582 }
1583
1584 /*! \brief Internal callback function which notifies an individual observer that an object has been created */
1585 static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
1586 {
1587         const struct ast_sorcery_object_type_observer *observer = obj;
1588
1589         if (observer->callbacks->created) {
1590                 observer->callbacks->created(arg);
1591         }
1592
1593         return 0;
1594 }
1595
1596 /*! \brief Internal callback function which notifies observers that an object has been created */
1597 static int sorcery_observers_notify_create(void *data)
1598 {
1599         struct sorcery_observer_invocation *invocation = data;
1600
1601         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_create, invocation->object);
1602         ao2_cleanup(invocation);
1603
1604         return 0;
1605 }
1606
1607 int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
1608 {
1609         const struct ast_sorcery_object_details *details = object;
1610         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1611         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1612         struct sorcery_details sdetails = {
1613                 .sorcery = sorcery,
1614                 .obj = object,
1615         };
1616
1617         if (!object_type) {
1618                 return -1;
1619         }
1620
1621         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_create, &sdetails)) &&
1622                 ao2_container_count(object_type->observers)) {
1623                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1624
1625                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create, invocation)) {
1626                         ao2_cleanup(invocation);
1627                 }
1628         }
1629
1630         return object_wizard ? 0 : -1;
1631 }
1632
1633 /*! \brief Internal callback function which notifies an individual observer that an object has been updated */
1634 static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
1635 {
1636         const struct ast_sorcery_object_type_observer *observer = obj;
1637
1638         if (observer->callbacks->updated) {
1639                 observer->callbacks->updated(arg);
1640         }
1641
1642         return 0;
1643 }
1644
1645 /*! \brief Internal callback function which notifies observers that an object has been updated */
1646 static int sorcery_observers_notify_update(void *data)
1647 {
1648         struct sorcery_observer_invocation *invocation = data;
1649
1650         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_update, invocation->object);
1651         ao2_cleanup(invocation);
1652
1653         return 0;
1654 }
1655
1656 /*! \brief Internal function which returns if a wizard has updated the object */
1657 static int sorcery_wizard_update(void *obj, void *arg, int flags)
1658 {
1659         const struct ast_sorcery_object_wizard *object_wizard = obj;
1660         const struct sorcery_details *details = arg;
1661
1662         return (object_wizard->wizard->update && !object_wizard->wizard->update(details->sorcery, object_wizard->data, details->obj) &&
1663                 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1664 }
1665
1666 int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
1667 {
1668         const struct ast_sorcery_object_details *details = object;
1669         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1670         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1671         struct sorcery_details sdetails = {
1672                 .sorcery = sorcery,
1673                 .obj = object,
1674         };
1675
1676         if (!object_type) {
1677                 return -1;
1678         }
1679
1680         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_update, &sdetails)) &&
1681                 ao2_container_count(object_type->observers)) {
1682                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1683
1684                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update, invocation)) {
1685                         ao2_cleanup(invocation);
1686                 }
1687         }
1688
1689         return object_wizard ? 0 : -1;
1690 }
1691
1692 /*! \brief Internal callback function which notifies an individual observer that an object has been deleted */
1693 static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
1694 {
1695         const struct ast_sorcery_object_type_observer *observer = obj;
1696
1697         if (observer->callbacks->deleted) {
1698                 observer->callbacks->deleted(arg);
1699         }
1700
1701         return 0;
1702 }
1703
1704 /*! \brief Internal callback function which notifies observers that an object has been deleted */
1705 static int sorcery_observers_notify_delete(void *data)
1706 {
1707         struct sorcery_observer_invocation *invocation = data;
1708
1709         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_delete, invocation->object);
1710         ao2_cleanup(invocation);
1711
1712         return 0;
1713 }
1714
1715 /*! \brief Internal function which returns if a wizard has deleted the object */
1716 static int sorcery_wizard_delete(void *obj, void *arg, int flags)
1717 {
1718         const struct ast_sorcery_object_wizard *object_wizard = obj;
1719         const struct sorcery_details *details = arg;
1720
1721         return (object_wizard->wizard->delete && !object_wizard->wizard->delete(details->sorcery, object_wizard->data, details->obj) &&
1722                 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1723 }
1724
1725 int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
1726 {
1727         const struct ast_sorcery_object_details *details = object;
1728         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1729         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1730         struct sorcery_details sdetails = {
1731                 .sorcery = sorcery,
1732                 .obj = object,
1733         };
1734
1735         if (!object_type) {
1736                 return -1;
1737         }
1738
1739         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_delete, &sdetails)) &&
1740                 ao2_container_count(object_type->observers)) {
1741                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1742
1743                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete, invocation)) {
1744                         ao2_cleanup(invocation);
1745                 }
1746         }
1747
1748         return object_wizard ? 0 : -1;
1749 }
1750
1751 void ast_sorcery_unref(struct ast_sorcery *sorcery)
1752 {
1753         if (sorcery) {
1754                 /* One ref for what we just released, the other for the instances container. */
1755                 ao2_wrlock(instances);
1756                 if (ao2_ref(sorcery, -1) == 2) {
1757                         ao2_unlink_flags(instances, sorcery, OBJ_NOLOCK);
1758                 }
1759                 ao2_unlock(instances);
1760         }
1761 }
1762
1763 const char *ast_sorcery_object_get_id(const void *object)
1764 {
1765         const struct ast_sorcery_object_details *details = object;
1766         return details->object->id;
1767 }
1768
1769 const char *ast_sorcery_object_get_type(const void *object)
1770 {
1771         const struct ast_sorcery_object_details *details = object;
1772         return details->object->type;
1773 }
1774
1775 const char *ast_sorcery_object_get_extended(const void *object, const char *name)
1776 {
1777         const struct ast_sorcery_object_details *details = object;
1778         struct ast_variable *field;
1779
1780         for (field = details->object->extended; field; field = field->next) {
1781                 if (!strcmp(field->name + 1, name)) {
1782                         return field->value;
1783                 }
1784         }
1785
1786         return NULL;
1787 }
1788
1789 int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
1790 {
1791         RAII_VAR(struct ast_variable *, field, NULL, ast_variables_destroy);
1792         struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL;
1793         const struct ast_sorcery_object_details *details = object;
1794
1795         if (!extended) {
1796                 return -1;
1797         }
1798
1799         for (field = details->object->extended; field; previous = field, field = field->next) {
1800                 if (!strcmp(field->name, name)) {
1801                         if (previous) {
1802                                 previous->next = field->next;
1803                         } else {
1804                                 details->object->extended = field->next;
1805                         }
1806                         field->next = NULL;
1807                         break;
1808                 }
1809         }
1810
1811         extended->next = details->object->extended;
1812         details->object->extended = extended;
1813
1814         return 0;
1815 }
1816
1817 int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
1818 {
1819         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1820         struct ast_sorcery_object_type_observer *observer;
1821         int res;
1822
1823         if (!object_type || !callbacks) {
1824                 return -1;
1825         }
1826
1827         if (!(observer = ao2_alloc(sizeof(*observer), NULL))) {
1828                 return -1;
1829         }
1830
1831         observer->callbacks = callbacks;
1832         res = 0;
1833         if (!ao2_link(object_type->observers, observer)) {
1834                 res = -1;
1835         }
1836         ao2_ref(observer, -1);
1837
1838         return res;
1839 }
1840
1841 /*! \brief Internal callback function for removing an observer */
1842 static int sorcery_observer_remove(void *obj, void *arg, int flags)
1843 {
1844         const struct ast_sorcery_object_type_observer *observer = obj;
1845
1846         return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
1847 }
1848
1849 void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
1850 {
1851         RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
1852         struct ast_sorcery_observer *cbs = (struct ast_sorcery_observer *) callbacks;/* Remove const for traversal. */
1853
1854         if (!sorcery) {
1855                 return;
1856         }
1857         object_type = ao2_find(sorcery->types, type, OBJ_KEY);
1858         if (!object_type) {
1859                 return;
1860         }
1861
1862         ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
1863                 sorcery_observer_remove, cbs);
1864 }
1865
1866 int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
1867 {
1868         const char *right_key = arg;
1869         int cmp;
1870
1871         switch (flags & OBJ_SEARCH_MASK) {
1872         case OBJ_SEARCH_OBJECT:
1873                 right_key = ast_sorcery_object_get_id(arg);
1874                 /* Fall through */
1875         case OBJ_SEARCH_KEY:
1876                 cmp = strcmp(ast_sorcery_object_get_id(obj), right_key);
1877                 break;
1878         case OBJ_SEARCH_PARTIAL_KEY:
1879                 cmp = strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key));
1880                 break;
1881         default:
1882                 cmp = 0;
1883                 break;
1884         }
1885         return cmp;
1886 }
1887
1888 int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
1889 {
1890         const char *right_key = arg;
1891         int cmp = 0;
1892
1893         switch (flags & OBJ_SEARCH_MASK) {
1894         case OBJ_SEARCH_OBJECT:
1895                 right_key = ast_sorcery_object_get_id(arg);
1896                 /* Fall through */
1897         case OBJ_SEARCH_KEY:
1898                 if (strcmp(ast_sorcery_object_get_id(obj), right_key) == 0) {
1899                         cmp = CMP_MATCH | CMP_STOP;
1900                 }
1901                 break;
1902         case OBJ_SEARCH_PARTIAL_KEY:
1903                 if (strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key)) == 0) {
1904                         cmp = CMP_MATCH;
1905                 }
1906                 break;
1907         default:
1908                 cmp = 0;
1909                 break;
1910         }
1911         return cmp;
1912 }
1913
1914 int ast_sorcery_object_id_hash(const void *obj, int flags) {
1915         if (flags & OBJ_SEARCH_OBJECT) {
1916                 return ast_str_hash(ast_sorcery_object_get_id(obj));
1917         } else if (flags & OBJ_SEARCH_KEY) {
1918                 return ast_str_hash(obj);
1919         }
1920         return -1;
1921 }
1922
1923 struct ast_sorcery_object_type *ast_sorcery_get_object_type(const struct ast_sorcery *sorcery,
1924                 const char *type)
1925 {
1926         return ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
1927 }
1928
1929 int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type *object_type,
1930                 const char *field_name)
1931 {
1932         struct ast_sorcery_object_field *object_field;
1933         int res = 1;
1934
1935         ast_assert(object_type != NULL);
1936
1937         object_field = ao2_find(object_type->fields, field_name, OBJ_SEARCH_KEY);
1938         if (!object_field) {
1939                 res = 0;
1940         }
1941
1942         ao2_cleanup(object_field);
1943         return res;
1944 }