Asterisk - The Open Source Telephony Project GIT-master-c753fe4
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
res/ari/config.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * David M. Lee, II <dlee@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 Config framework stuffz for ARI.
22 * \author David M. Lee, II <dlee@digium.com>
23 */
24
25#include <limits.h>
26
27#include "asterisk.h"
28
29#include "asterisk/sorcery.h"
33#include "asterisk/app.h"
34#include "asterisk/channel.h"
35#include "asterisk/vector.h"
36#include "internal.h"
37
38static struct ast_sorcery *sorcery;
39
42 char id[0];
43};
44
45#define OWC_STATES_BUCKETS 13
47
48static void outbound_websocket_dtor(void *obj)
49{
50 struct ari_conf_outbound_websocket *owc = obj;
51
52 ast_debug(3, "%s: Disposing of outbound websocket config\n",
57}
58
59static void *outbound_websocket_alloc(const char *id)
60{
62
64 if (!owc) {
65 return NULL;
66 }
67
68 if (ast_string_field_init(owc, 1024) != 0) {
69 ao2_cleanup(owc);
70 return NULL;
71 }
72
73 ast_debug(2, "%s: Allocated outbound websocket config\n", id);
74 return owc;
75}
76
78 struct ast_variable *var, void *obj)
79{
80 struct ari_conf_outbound_websocket *owc = obj;
81
82 if (ast_strlen_zero(var->value)) {
83 ast_log(LOG_ERROR, "%s: Outbound websocket missing websocket client id\n",
85 return -1;
86 }
88 if (!owc->websocket_client) {
89 ast_log(LOG_ERROR, "%s: Outbound websocket invalid websocket client id '%s'\n",
90 ast_sorcery_object_get_id(owc), var->value);
91 return -1;
92 }
93 if (ast_string_field_set(owc, websocket_client_id, var->value) != 0) {
94 return -1;
95 }
96 return 0;
97}
98
99static int outbound_websocket_websocket_client_id_to_str(const void *obj, const intptr_t *args, char **buf)
100{
101 const struct ari_conf_outbound_websocket *owc = obj;
102 if (!owc->websocket_client) {
103 return -1;
104 }
106 return 0;
107}
108
109/*!
110 * \brief Callback to initialize an outbound websocket object
111 * \retval 0 on success
112 * \retval CMP_MATCH on error which will cause the object to be removed
113 */
114static int outbound_websocket_apply(const struct ast_sorcery *sorcery, void *obj)
115{
116 struct ari_conf_outbound_websocket *owc = obj;
117 const char *id = ast_sorcery_object_get_id(owc);
118 int res = 0;
119
120 ast_debug(3, "%s: Initializing outbound websocket\n", id);
121
122 if (ast_strlen_zero(owc->apps)) {
123 ast_log(LOG_WARNING, "%s: Outbound websocket missing apps\n", id);
124 res = -1;
125 } else {
126 char *apps = ast_strdupa(owc->apps);
127 char *app;
128 while ((app = ast_strsep(&apps, ',', AST_STRSEP_STRIP))) {
129
130 if (ast_strlen_zero(app)) {
131 ast_log(LOG_WARNING, "%s: Outbound websocket has empty app\n", id);
132 res = -1;
133 }
134 if (strlen(app) > ARI_MAX_APP_NAME_LEN) {
135 ast_log(LOG_WARNING, "%s: Outbound websocket app '%s' > %d characters\n",
136 id, app, (int)ARI_MAX_APP_NAME_LEN);
137 res = -1;
138 }
139
140 }
141 }
142
144 ast_log(LOG_WARNING, "%s: Outbound websocket missing local_ari_user\n", id);
145 res = -1;
146 }
147
148 if (res != 0) {
149 ast_log(LOG_WARNING, "%s: Outbound websocket configuration failed\n", id);
150 } else {
151 ast_debug(3, "%s: Outbound websocket configuration succeeded\n", id);
152 }
153
154 /* Reminder: If res is -1, the config will be discarded. */
155 return res;
156}
157
159{
161
163 return state ? state->invalid_fields : ARI_OWC_FIELD_NONE;
164}
165
166static int outbound_websocket_validate_cb(void *obj, void *args, int flags)
167{
168 struct ari_conf_outbound_websocket *owc = obj;
169 struct ari_conf_outbound_websocket *other_owc = NULL;
170 RAII_VAR(struct ao2_container *, owcs, NULL, ao2_cleanup);
171 struct ao2_iterator it;
172 const char *id = ast_sorcery_object_get_id(owc);
173 struct ast_vector_string apps = { 0, };
174 struct ari_conf_user *user = NULL;
176 int res = 0;
177
178 ast_debug(2, "%s: Validating outbound websocket\n", id);
179
180 owcs = ari_conf_get_owcs();
181 if (!owcs || ao2_container_count(owcs) == 0) {
182 return 0;
183 }
184
185 if (AST_VECTOR_INIT(&apps, 5) != 0) {
186 return 0;
187 }
188
189 res = ast_vector_string_split(&apps, owc->apps, ",", 0, NULL);
190 if (res != 0) {
191 ast_log(LOG_WARNING, "%s: Outbound websocket apps '%s' failed to split\n",
192 id, owc->apps);
195 return 0;
196 }
197
199 if (!state) {
200 state = ao2_alloc(sizeof(*state) + strlen(id) + 1, NULL);
201 if (!state) {
202 ast_log(LOG_WARNING, "%s: Outbound websocket state allocation failed\n", id);
205 return 0;
206 }
207 strcpy(state->id, id); /* Safe */
208 ast_debug(3, "%s: Created new outbound websocket state\n", id);
209 } else {
210 ast_debug(3, "%s: Outbound websocket state already exists\n", id);
211 }
212 state->invalid_fields = ARI_OWC_FIELD_NONE;
213
214 /*
215 * Check all other owcs to make sure we don't have
216 * duplicate apps.
217 */
218 it = ao2_iterator_init(owcs, 0);
219 while ((other_owc = ao2_iterator_next(&it))) {
220 const char *other_id = ast_sorcery_object_get_id(other_owc);
221 if (!ast_strings_equal(other_id, id)) {
222 int i = 0;
223 for (i = 0; i < AST_VECTOR_SIZE(&apps); i++) {
224 const char *app = AST_VECTOR_GET(&apps, i);
225 if (ast_in_delimited_string(app, other_owc->apps, ',')) {
227 "%s: Outbound websocket '%s' is also trying to register app '%s'\n",
228 id, other_id, app);
229 state->invalid_fields |= ARI_OWC_FIELD_APPS;
230 }
231 }
232 }
233 ao2_cleanup(other_owc);
234 if (owc->invalid) {
235 break;
236 }
237 }
241
242 /*
243 * Check that the local_ari_user is valid and has
244 * a plain text password.
245 */
247 if (!user) {
248 ast_log(LOG_WARNING, "%s: Outbound websocket ARI user '%s' not found\n",
249 id, owc->local_ari_user);
250 state->invalid_fields |= ARI_OWC_FIELD_LOCAL_ARI_USER;
251 } else {
252 if (user->password_format != ARI_PASSWORD_FORMAT_PLAIN) {
253 ast_log(LOG_WARNING, "%s: Outbound websocket ARI user '%s' password MUST be plain text\n",
254 id, owc->local_ari_user);
255 state->invalid_fields |= ARI_OWC_FIELD_LOCAL_ARI_USER;
256 }
257 if (ast_string_field_set(owc, local_ari_password, user->password) != 0) {
258 state->invalid_fields |= ARI_OWC_FIELD_LOCAL_ARI_USER;
259 }
260 }
262
263 /*
264 * The container has AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE set so
265 * this is an insert or replace operation.
266 */
269
270 return 0;
271}
272
273static int outbound_websocket_state_cleanup(void *obj, void *arg, int flags)
274{
275 struct outbound_websocket_state *state = obj;
277 int res = 0;
278
279 if (!owc) {
280 ast_debug(3, "%s: Cleaning up orphaned outbound websocket state\n", state->id);
281 res = CMP_MATCH;
282 }
283 ao2_cleanup(owc);
284
285 return res;
286}
287
288static void outbound_websockets_validate(const char *name)
289{
291
293 /* Clean up any states whose configs have disappeared. */
296}
297
299{
300 if (!sorcery) {
301 return NULL;
302 }
303
304 return ast_sorcery_retrieve_by_fields(sorcery, "outbound_websocket",
306}
307
309{
310 if (!sorcery) {
311 return NULL;
312 }
313
314 return ast_sorcery_retrieve_by_id(sorcery, "outbound_websocket", id);
315}
316
318 const char *app_name, unsigned int ws_type)
319{
320 struct ari_conf_outbound_websocket *owc = NULL;
321 struct ao2_container *owcs = NULL;
322 struct ao2_iterator i;
323
325 return NULL;
326 }
327
328 ast_debug(3, "Checking outbound websockets for app '%s'\n", app_name);
329
330 owcs = ari_conf_get_owcs();
331 if (!owcs || ao2_container_count(owcs) == 0) {
332 ast_debug(3, "No outbound websockets found\n");
333 return NULL;
334 }
335
336 i = ao2_iterator_init(owcs, 0);
337 while ((owc = ao2_iterator_next(&i))) {
338 const char *id = ast_sorcery_object_get_id(owc);
339
340 ast_debug(3, "%s: Checking outbound websocket apps '%s' for app '%s'\n",
341 id, owc->apps, app_name);
342 if (owc->websocket_client->connection_type & ws_type
343 && ast_in_delimited_string(app_name, owc->apps, ',')) {
344 ast_debug(3, "%s: Found correct websocket type for apps '%s' for app '%s'\n",
345 id, owc->apps, app_name);
346 break;
347 }
348 ao2_cleanup(owc);
349 }
351 ao2_cleanup(owcs);
352 if (!owc) {
353 ast_debug(3, "No outbound websocket found for app '%s'\n", app_name);
354 }
355
356 return owc;
357}
358
360{
361 switch (type) {
363 return "persistent";
365 return "per_call";
367 return "per_call_config";
369 return "inbound";
370 case AST_WS_TYPE_ANY:
371 return "any";
372 default:
373 return "unknown";
374 }
375}
376
378 struct ari_conf_outbound_websocket *old_owc,
379 struct ari_conf_outbound_websocket *new_owc)
380{
382 const char *new_id = ast_sorcery_object_get_id(new_owc);
383 RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
384 struct ast_variable *v = NULL;
385 int res = 0;
386 int changes_found = 0;
387
388 ast_debug(2, "%s: Detecting changes\n", new_id);
389
390 res = ast_sorcery_diff(sorcery, old_owc, new_owc, &changes);
391 if (res != 0) {
392 ast_log(LOG_WARNING, "%s: Failed to create changeset\n", new_id);
393 return ARI_OWC_FIELD_NONE;
394 }
395
396 for (v = changes; v; v = v->next) {
397 changes_found = 1;
398 ast_debug(2, "%s: %s changed to %s\n", new_id, v->name, v->value);
399 if (ast_strings_equal(v->name, "apps")) {
400 changed |= ARI_OWC_FIELD_APPS;
401 } else if (ast_strings_equal(v->name, "subscribe_all")) {
403 } else if (ast_strings_equal(v->name, "local_ari_user")) {
405 } else if (ast_strings_equal(v->name, "local_ari_password")) {
407 } else {
408 ast_debug(2, "%s: Unknown change %s\n", new_id, v->name);
409 }
410 }
411 if (!changes_found) {
412 ast_debug(2, "%s: No changes found %p %p\n", new_id,
413 old_owc->websocket_client,new_owc->websocket_client);
414 }
415
417 old_owc->websocket_client, new_owc->websocket_client);
418
419 return changed;
420
421}
422
423/*! \brief \ref ast_ari_conf destructor. */
424static void general_dtor(void *obj)
425{
426 struct ari_conf_general *cfg = obj;
427
429}
430
431static void *general_alloc(const char *name)
432{
434 sizeof(*general), general_dtor);
435
436 if (!general) {
437 return NULL;
438 }
439
440 if (ast_string_field_init(general, 64) != 0) {
441 return NULL;
442 }
443
444 return general;
445}
446
447#define MAX_VARS 128
448
449static int general_apply(const struct ast_sorcery *sorcery, void *obj)
450{
451 struct ari_conf_general *general = obj;
452 char *parse = NULL;
454 AST_APP_ARG(vars)[MAX_VARS];
455 );
456
457 ast_debug(2, "Initializing general config\n");
458
459 parse = ast_strdupa(general->channelvars);
461
463 return 0;
464}
465
466/*! \brief Encoding format handler converts from boolean to enum. */
467static int general_pretty_from_str(const struct aco_option *opt,
468 struct ast_variable *var, void *obj)
469{
470 struct ari_conf_general *general = obj;
471
472 general->format = ast_true(var->value) ? AST_JSON_PRETTY : AST_JSON_COMPACT;
473
474 return 0;
475}
476
478{
479 if (!sorcery) {
480 return NULL;
481 }
482
483 return ast_sorcery_retrieve_by_id(sorcery, "general", "general");
484}
485
486static int general_pretty_to_str(const void *obj, const intptr_t *args, char **buf)
487{
488 const struct ari_conf_general *general = obj;
489
490 if (general->format == AST_JSON_PRETTY) {
491 *buf = ast_strdup("yes");
492 } else {
493 *buf = ast_strdup("no");
494 }
495 return 0;
496}
497
498/*! \brief Destructor for \ref ast_ari_conf_user */
499static void user_dtor(void *obj)
500{
501 struct ari_conf_user *user = obj;
503 ast_debug(3, "%s: Disposing of user\n", ast_sorcery_object_get_id(user));
504}
505
506/*! \brief Allocate an \ref ast_ari_conf_user for config parsing */
507static void *user_alloc(const char *cat)
508{
510 sizeof(*user), user_dtor);
511
512 if (!user) {
513 return NULL;
514 }
515
516 if (ast_string_field_init(user, 64) != 0) {
518 user = NULL;
519 }
520
521 return user;
522}
523
524static int user_apply(const struct ast_sorcery *sorcery, void *obj)
525{
526 struct ari_conf_user *user = obj;
527 const char *id = ast_sorcery_object_get_id(user);
528
529 ast_debug(2, "%s: Initializing user\n", id);
530
531 if (ast_strlen_zero(user->password)) {
532 ast_log(LOG_WARNING, "%s: User missing password\n", id);
533 return -1;
534 }
535
536 return 0;
537}
538
539/*! \brief Parses the ast_ari_password_format enum from a config file */
540static int user_password_format_from_str(const struct aco_option *opt,
541 struct ast_variable *var, void *obj)
542{
543 struct ari_conf_user *user = obj;
544
545 if (strcasecmp(var->value, "plain") == 0) {
546 user->password_format = ARI_PASSWORD_FORMAT_PLAIN;
547 } else if (strcasecmp(var->value, "crypt") == 0) {
548 user->password_format = ARI_PASSWORD_FORMAT_CRYPT;
549 } else {
550 return -1;
551 }
552
553 return 0;
554}
555
556static int user_password_format_to_str(const void *obj, const intptr_t *args, char **buf)
557{
558 const struct ari_conf_user *user = obj;
559
560 if (user->password_format == ARI_PASSWORD_FORMAT_CRYPT) {
561 *buf = ast_strdup("crypt");
562 } else {
563 *buf = ast_strdup("plain");
564 }
565 return 0;
566}
567
569{
570 if (!sorcery) {
571 return NULL;
572 }
573
576}
577
578struct ari_conf_user *ari_conf_get_user(const char *username)
579{
580 if (!sorcery) {
581 return NULL;
582 }
583
584 return ast_sorcery_retrieve_by_id(sorcery, "user", username);
585}
586
587/*
588 * This is called by res_ari.c to validate the user and password
589 * for the websocket connection.
590 */
591struct ari_conf_user *ari_conf_validate_user(const char *username,
592 const char *password)
593{
594 struct ari_conf_user *user = NULL;
595 int is_valid = 0;
596
597 if (ast_strlen_zero(username) || ast_strlen_zero(password)) {
598 return NULL;
599 }
600
601 user = ast_sorcery_retrieve_by_id(sorcery, "user", username);
602 if (!user) {
603 return NULL;
604 }
605
606 switch (user->password_format) {
608 is_valid = strcmp(password, user->password) == 0;
609 break;
611 is_valid = ast_crypt_validate(password, user->password);
612 break;
613 }
614
615 if (!is_valid) {
617 user = NULL;
618 }
619
620 return user;
621}
622
623int ari_sorcery_observer_add(const char *object_type,
624 const struct ast_sorcery_observer *callbacks)
625{
626 if (!sorcery) {
627 return -1;
628 }
629 return ast_sorcery_observer_add(sorcery, object_type, callbacks);
630}
631
632int ari_sorcery_observer_remove(const char *object_type,
633 const struct ast_sorcery_observer *callbacks)
634{
635 if (!sorcery) {
636 return -1;
637 }
639 return 0;
640}
641
644};
645
646static void ws_client_load(const char *name)
647{
648 ast_sorcery_force_reload_object(sorcery, "outbound_websocket");
649}
650
653};
654
657
658static int ari_conf_init(void)
659{
660 int res = 0;
661 ast_debug(2, "Initializing ARI configuration\n");
662
665 outbound_websocket_state_hash_fn, NULL,
666 outbound_websocket_state_cmp_fn);
667 if (!owc_states) {
668 ast_log(LOG_ERROR, "Failed to allocate outbound websocket states\n");
669 return -1;
670 }
671
672 if (!(sorcery = ast_sorcery_open())) {
673 ast_log(LOG_ERROR, "Failed to open sorcery\n");
674 return -1;
675 }
676
677 ast_sorcery_apply_default(sorcery, "general", "config",
678 "ari.conf,criteria=type=general,single_object=yes,explicit_name=general");
679 ast_sorcery_apply_default(sorcery, "user", "config",
680 "ari.conf,criteria=type=user");
681 ast_sorcery_apply_default(sorcery, "outbound_websocket", "config",
682 "ari.conf,criteria=type=outbound_websocket");
683
685 ast_log(LOG_ERROR, "Failed to register ARI general object with sorcery\n");
687 sorcery = NULL;
688 return -1;
689 }
690
692 ast_log(LOG_ERROR, "Failed to register ARI user object with sorcery\n");
694 sorcery = NULL;
695 return -1;
696 }
697
700 ast_log(LOG_ERROR, "Failed to register ARI outbound_websocket object with sorcery\n");
702 sorcery = NULL;
703 return -1;
704 }
705
706 if (ast_sorcery_observer_add(sorcery, "outbound_websocket", &observer_callbacks)) {
707 ast_log(LOG_ERROR, "Failed to register ARI outbound_websocket observer with sorcery\n");
709 sorcery = NULL;
710 return -1;
711 }
712
713 ast_sorcery_object_field_register_nodoc(sorcery, "general", "type", "", OPT_NOOP_T, 0, 0);
714 ast_sorcery_register_sf(general, ari_conf_general, auth_realm, auth_realm, "Asterisk REST Interface");
715 ast_sorcery_register_sf(general, ari_conf_general, allowed_origins, allowed_origins, "");
716 ast_sorcery_register_sf(general, ari_conf_general, channelvars, channelvars, "");
718 ast_sorcery_register_cust(general, pretty, "no");
719 ast_sorcery_register_int(general, ari_conf_general, websocket_write_timeout, write_timeout,
721
722
723 ast_sorcery_object_field_register(sorcery, "user", "type", "", OPT_NOOP_T, 0, 0);
724 ast_sorcery_register_sf(user, ari_conf_user, password, password, "");
725 ast_sorcery_register_bool(user, ari_conf_user, read_only, read_only, "no");
726 ast_sorcery_register_cust(user, password_format, "plain");
727
728 ast_sorcery_object_field_register(sorcery, "outbound_websocket", "type", "", OPT_NOOP_T, 0, 0);
729 ast_sorcery_register_cust(outbound_websocket, websocket_client_id, "");
731 ast_sorcery_register_sf(outbound_websocket, ari_conf_outbound_websocket, local_ari_user, local_ari_user, "");
733
735 if (res < 0) {
736 ast_log(LOG_WARNING, "Failed to register websocket client observer\n");
738 sorcery = NULL;
739 return -1;
740 }
741
742 return 0;
743}
744
746{
747 void (*loader)(const struct ast_sorcery *sorcery, const char *type);
748 const char *msg_prefix;
749
750 if (flags & ARI_CONF_RELOAD) {
752 msg_prefix= "Reloading";
754 } else {
756 msg_prefix= "Loading";
757 }
758
759 if (flags & ARI_CONF_INIT) {
760 if (ari_conf_init() != 0) {
761 ast_log(LOG_ERROR, "Failed to initialize ARI configuration\n");
762 return -1;
763 }
764 }
765
766 if (!sorcery) {
767 ast_log(LOG_ERROR, "ARI configuration not initialized\n");
768 return -1;
769 }
770
771 if (flags & ARI_CONF_LOAD_GENERAL) {
772 ast_debug(2, "%s ARI '%s' configuration\n", msg_prefix, "general");
773 loader(sorcery, "general");
774 }
775
776 if (flags & ARI_CONF_LOAD_USER) {
777 ast_debug(2, "%s ARI '%s' configuration\n", msg_prefix, "user");
778 loader(sorcery, "user");
779 }
780
781 if (flags & ARI_CONF_LOAD_OWC) {
782 ast_debug(2, "%s ARI '%s' configuration\n", msg_prefix, "outbound_websocket");
783 loader(sorcery, "outbound_websocket");
784 }
785
786 return 0;
787}
788
790{
792
794 sorcery = NULL;
796}
static const char app[]
Definition: app_adsiprog.c:56
#define ARI_MAX_APP_NAME_LEN
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define AO2_STRING_FIELD_CMP_FN(stype, field)
Creates a compare function for a structure string field.
Definition: astobj2.h:2048
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define AO2_STRING_FIELD_HASH_FN(stype, field)
Creates a hash function for a structure string field.
Definition: astobj2.h:2032
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_UNLINK
Definition: astobj2.h:1039
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE
Replace objects with duplicate keys in container.
Definition: astobj2.h:1211
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
void ast_channel_set_ari_vars(size_t varc, char **vars)
Sets the variables to be stored in the ari_vars field of all snapshots.
Definition: channel.c:7838
Configuration option-handling.
@ OPT_NOOP_T
Type for a default handler that should do nothing.
static int enabled
Definition: dnsmgr.c:91
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const char name[]
Definition: format_mp3.c:68
Support for WebSocket connections within the Asterisk HTTP server and client WebSocket connections to...
#define AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT
Default websocket write timeout, in ms.
ast_websocket_type
WebSocket connection/configuration types.
@ AST_WS_TYPE_ANY
@ AST_WS_TYPE_INBOUND
@ AST_WS_TYPE_CLIENT_PER_CALL_CONFIG
@ AST_WS_TYPE_CLIENT_PERSISTENT
@ AST_WS_TYPE_CLIENT_PER_CALL
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_WARNING
Internal API's for res_ari.
ari_conf_load_flags
Definition: internal.h:145
@ ARI_CONF_RELOAD
Definition: internal.h:147
@ ARI_CONF_INIT
Definition: internal.h:146
@ ARI_CONF_LOAD_OWC
Definition: internal.h:150
@ ARI_CONF_LOAD_USER
Definition: internal.h:149
@ ARI_CONF_LOAD_GENERAL
Definition: internal.h:148
@ ARI_PASSWORD_FORMAT_CRYPT
Definition: internal.h:80
@ ARI_PASSWORD_FORMAT_PLAIN
Plaintext password.
Definition: internal.h:78
ari_conf_owc_fields
Definition: internal.h:96
@ ARI_OWC_FIELD_APPS
Definition: internal.h:99
@ ARI_OWC_FIELD_LOCAL_ARI_PASSWORD
Definition: internal.h:101
@ ARI_OWC_FIELD_NONE
Definition: internal.h:97
@ ARI_OWC_FIELD_LOCAL_ARI_USER
Definition: internal.h:100
@ ARI_OWC_FIELD_SUBSCRIBE_ALL
Definition: internal.h:102
@ AST_JSON_COMPACT
Definition: json.h:793
@ AST_JSON_PRETTY
Definition: json.h:795
static int subscribe_all(void)
Definition: manager.c:9588
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
struct ari_conf_outbound_websocket * ari_conf_get_owc_for_app(const char *app_name, unsigned int ws_type)
Get the outbound websocket configuration for a Stasis app.
static struct ast_sorcery_observer observer_callbacks
static void outbound_websockets_validate(const char *name)
static int outbound_websocket_apply(const struct ast_sorcery *sorcery, void *obj)
Callback to initialize an outbound websocket object.
int ari_sorcery_observer_remove(const char *object_type, const struct ast_sorcery_observer *callbacks)
static int ari_conf_init(void)
static int user_apply(const struct ast_sorcery *sorcery, void *obj)
enum ari_conf_owc_fields ari_conf_owc_get_invalid_fields(const char *id)
struct ao2_container * ari_conf_get_owcs(void)
static void * general_alloc(const char *name)
static void * user_alloc(const char *cat)
Allocate an ast_ari_conf_user for config parsing.
struct ao2_container * ari_conf_get_users(void)
enum ari_conf_owc_fields ari_conf_owc_detect_changes(struct ari_conf_outbound_websocket *old_owc, struct ari_conf_outbound_websocket *new_owc)
Detect changes between two outbound websocket configurations.
static void * outbound_websocket_alloc(const char *id)
#define MAX_VARS
int ari_conf_load(enum ari_conf_load_flags flags)
(Re)load the ARI configuration
static void general_dtor(void *obj)
ast_ari_conf destructor.
static int general_pretty_from_str(const struct aco_option *opt, struct ast_variable *var, void *obj)
Encoding format handler converts from boolean to enum.
static int user_password_format_to_str(const void *obj, const intptr_t *args, char **buf)
static int outbound_websocket_validate_cb(void *obj, void *args, int flags)
static int general_pretty_to_str(const void *obj, const intptr_t *args, char **buf)
#define OWC_STATES_BUCKETS
static int general_apply(const struct ast_sorcery *sorcery, void *obj)
static struct ast_sorcery_observer ws_client_observer_callbacks
static struct ast_sorcery * sorcery
static int outbound_websocket_websocket_client_id_from_str(const struct aco_option *opt, struct ast_variable *var, void *obj)
struct ao2_container * owc_states
static int outbound_websocket_state_cleanup(void *obj, void *arg, int flags)
const char * ari_websocket_type_to_str(enum ast_websocket_type type)
int ari_sorcery_observer_add(const char *object_type, const struct ast_sorcery_observer *callbacks)
static void ws_client_load(const char *name)
struct ari_conf_general * ari_conf_get_general(void)
static int user_password_format_from_str(const struct aco_option *opt, struct ast_variable *var, void *obj)
Parses the ast_ari_password_format enum from a config file.
static void user_dtor(void *obj)
Destructor for ast_ari_conf_user.
static void outbound_websocket_dtor(void *obj)
struct ari_conf_outbound_websocket * ari_conf_get_owc(const char *id)
struct ari_conf_user * ari_conf_get_user(const char *username)
struct ari_conf_user * ari_conf_validate_user(const char *username, const char *password)
Validated a user's credentials.
static int outbound_websocket_websocket_client_id_to_str(const void *obj, const intptr_t *args, char **buf)
void ari_conf_destroy(void)
Destroy the ARI configuration.
static char user[512]
struct @471 callbacks
#define NULL
Definition: resample.c:96
Sorcery Data Access Layer API.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
Definition: sorcery.h:1500
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
#define ast_sorcery_object_field_register_nodoc(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object without documentation.
Definition: sorcery.h:987
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2423
#define ast_sorcery_register_cust(object, option, def_value)
Register a custom field within an object.
Definition: sorcery.h:1749
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition: sorcery.h:123
int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
Create a changeset of two objects.
Definition: sorcery.c:1805
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_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:837
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2391
void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to load persistent objects.
Definition: sorcery.c:1393
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
#define ast_sorcery_register_int(object, structure, option, field, def_value)
Register an int field as type OPT_INT_T within an object.
Definition: sorcery.h:1692
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects even if no changes determin...
Definition: sorcery.c:1457
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:476
#define ast_sorcery_register_bool(object, structure, option, field, def_value)
Register a boolean field as type OPT_YESNO_T within an object.
Definition: sorcery.h:1666
#define ast_sorcery_open()
Open a new sorcery structure.
Definition: sorcery.h:406
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects.
Definition: sorcery.c:1442
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
#define ast_sorcery_register_sf(object, structure, option, field, def_value)
Register a stringfield field as type OPT_STRINGFIELD_T within an object.
Definition: sorcery.h:1728
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition: strings.c:238
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
@ AST_STRSEP_STRIP
Definition: strings.h:255
int ast_in_delimited_string(const char *needle, const char *haystack, char delim)
Check if there is an exact match for 'needle' between delimiters in 'haystack'.
Definition: strings.c:466
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1835
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Registered applications container.
Definition: pbx_app.c:68
Global configuration options for ARI.
Definition: internal.h:57
const ast_string_field channelvars
Definition: internal.h:66
enum ast_json_encoding_format format
Definition: internal.h:72
const ast_string_field apps
Definition: internal.h:116
struct ast_websocket_client * websocket_client
Definition: internal.h:119
const ast_string_field local_ari_user
Definition: internal.h:116
const ast_string_field websocket_client_id
Definition: internal.h:116
Per-user configuration options.
Definition: internal.h:84
const ast_string_field password
Definition: internal.h:89
Interface for a sorcery object type observer.
Definition: sorcery.h:332
void(* loaded)(const char *object_type)
Callback for when an object type is loaded/reloaded.
Definition: sorcery.h:343
Full structure for sorcery.
Definition: sorcery.c:230
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
String vector definitions.
Definition: vector.h:55
enum ast_websocket_type connection_type
enum ari_conf_owc_fields invalid_fields
structure to hold users read from users.conf
const char * args
#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
int ast_crypt_validate(const char *key, const char *expected)
Asterisk wrapper around crypt(3) for validating passwords.
Definition: crypt.c:136
Vector container support.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:636
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:620
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:185
int ast_vector_string_split(struct ast_vector_string *dest, const char *input, const char *delim, int flags, int(*excludes_cmp)(const char *s1, const char *s2))
Append a string vector by splitting a string.
Definition: strings.c:425
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:124
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:691
int ast_websocket_client_reload(void)
Force res_websocket_client to reload its configuration.
enum ast_ws_client_fields ast_websocket_client_get_field_diff(struct ast_websocket_client *old_wc, struct ast_websocket_client *new_wc)
Detect changes between two websocket client configurations.
struct ast_websocket_client * ast_websocket_client_retrieve_by_id(const char *id)
Retrieve a websocket client object by ID.
void ast_websocket_client_observer_remove(const struct ast_sorcery_observer *callbacks)
Remove sorcery observers for websocket client events.
int ast_websocket_client_observer_add(const struct ast_sorcery_observer *callbacks)
Add sorcery observers for websocket client events.