Asterisk - The Open Source Telephony Project GIT-master-77d630f
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 (!owc->websocket_client) {
123 ast_log(LOG_WARNING, "%s: Outbound websocket missing websocket_client_id\n", id);
124 res = -1;
125 }
126
127 if (ast_strlen_zero(owc->apps)) {
128 ast_log(LOG_WARNING, "%s: Outbound websocket missing apps\n", id);
129 res = -1;
130 } else {
131 char *apps = ast_strdupa(owc->apps);
132 char *app;
133 while ((app = ast_strsep(&apps, ',', AST_STRSEP_STRIP))) {
134
135 if (ast_strlen_zero(app)) {
136 ast_log(LOG_WARNING, "%s: Outbound websocket has empty app\n", id);
137 res = -1;
138 }
139 if (strlen(app) > ARI_MAX_APP_NAME_LEN) {
140 ast_log(LOG_WARNING, "%s: Outbound websocket app '%s' > %d characters\n",
141 id, app, (int)ARI_MAX_APP_NAME_LEN);
142 res = -1;
143 }
144
145 }
146 }
147
149 ast_log(LOG_WARNING, "%s: Outbound websocket missing local_ari_user\n", id);
150 res = -1;
151 }
152
153 if (res != 0) {
154 ast_log(LOG_WARNING, "%s: Outbound websocket configuration failed\n", id);
155 } else {
156 ast_debug(3, "%s: Outbound websocket configuration succeeded\n", id);
157 }
158
159 /* Reminder: If res is -1, the config will be discarded. */
160 return res;
161}
162
164{
166
168 return state ? state->invalid_fields : ARI_OWC_FIELD_NONE;
169}
170
171static int outbound_websocket_validate_cb(void *obj, void *args, int flags)
172{
173 struct ari_conf_outbound_websocket *owc = obj;
174 struct ari_conf_outbound_websocket *other_owc = NULL;
175 RAII_VAR(struct ao2_container *, owcs, NULL, ao2_cleanup);
176 struct ao2_iterator it;
177 const char *id = ast_sorcery_object_get_id(owc);
178 struct ast_vector_string apps = { 0, };
179 struct ari_conf_user *user = NULL;
181 int res = 0;
182
183 ast_debug(2, "%s: Validating outbound websocket\n", id);
184
185 owcs = ari_conf_get_owcs();
186 if (!owcs || ao2_container_count(owcs) == 0) {
187 return 0;
188 }
189
190 if (AST_VECTOR_INIT(&apps, 5) != 0) {
191 return 0;
192 }
193
194 res = ast_vector_string_split(&apps, owc->apps, ",", 0, NULL);
195 if (res != 0) {
196 ast_log(LOG_WARNING, "%s: Outbound websocket apps '%s' failed to split\n",
197 id, owc->apps);
200 return 0;
201 }
202
204 if (!state) {
205 state = ao2_alloc(sizeof(*state) + strlen(id) + 1, NULL);
206 if (!state) {
207 ast_log(LOG_WARNING, "%s: Outbound websocket state allocation failed\n", id);
210 return 0;
211 }
212 strcpy(state->id, id); /* Safe */
213 ast_debug(3, "%s: Created new outbound websocket state\n", id);
214 } else {
215 ast_debug(3, "%s: Outbound websocket state already exists\n", id);
216 }
217 state->invalid_fields = ARI_OWC_FIELD_NONE;
218
219 /*
220 * Check all other owcs to make sure we don't have
221 * duplicate apps.
222 */
223 it = ao2_iterator_init(owcs, 0);
224 while ((other_owc = ao2_iterator_next(&it))) {
225 const char *other_id = ast_sorcery_object_get_id(other_owc);
226 if (!ast_strings_equal(other_id, id)) {
227 int i = 0;
228 for (i = 0; i < AST_VECTOR_SIZE(&apps); i++) {
229 const char *app = AST_VECTOR_GET(&apps, i);
230 if (ast_in_delimited_string(app, other_owc->apps, ',')) {
232 "%s: Outbound websocket '%s' is also trying to register app '%s'\n",
233 id, other_id, app);
234 state->invalid_fields |= ARI_OWC_FIELD_APPS;
235 }
236 }
237 }
238 ao2_cleanup(other_owc);
239 if (owc->invalid) {
240 break;
241 }
242 }
246
247 /*
248 * Check that the local_ari_user is valid and has
249 * a plain text password.
250 */
252 if (!user) {
253 ast_log(LOG_WARNING, "%s: Outbound websocket ARI user '%s' not found\n",
254 id, owc->local_ari_user);
255 state->invalid_fields |= ARI_OWC_FIELD_LOCAL_ARI_USER;
256 } else {
257 if (user->password_format != ARI_PASSWORD_FORMAT_PLAIN) {
258 ast_log(LOG_WARNING, "%s: Outbound websocket ARI user '%s' password MUST be plain text\n",
259 id, owc->local_ari_user);
260 state->invalid_fields |= ARI_OWC_FIELD_LOCAL_ARI_USER;
261 }
262 if (ast_string_field_set(owc, local_ari_password, user->password) != 0) {
263 state->invalid_fields |= ARI_OWC_FIELD_LOCAL_ARI_USER;
264 }
265 }
267
268 /*
269 * The container has AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE set so
270 * this is an insert or replace operation.
271 */
274
275 return 0;
276}
277
278static int outbound_websocket_state_cleanup(void *obj, void *arg, int flags)
279{
280 struct outbound_websocket_state *state = obj;
282 int res = 0;
283
284 if (!owc) {
285 ast_debug(3, "%s: Cleaning up orphaned outbound websocket state\n", state->id);
286 res = CMP_MATCH;
287 }
288 ao2_cleanup(owc);
289
290 return res;
291}
292
293static void outbound_websockets_validate(const char *name)
294{
296
298 /* Clean up any states whose configs have disappeared. */
301}
302
304{
305 if (!sorcery) {
306 return NULL;
307 }
308
309 return ast_sorcery_retrieve_by_fields(sorcery, "outbound_websocket",
311}
312
314{
315 if (!sorcery) {
316 return NULL;
317 }
318
319 return ast_sorcery_retrieve_by_id(sorcery, "outbound_websocket", id);
320}
321
323 const char *app_name, unsigned int ws_type)
324{
325 struct ari_conf_outbound_websocket *owc = NULL;
326 struct ao2_container *owcs = NULL;
327 struct ao2_iterator i;
328
330 return NULL;
331 }
332
333 ast_debug(3, "Checking outbound websockets for app '%s'\n", app_name);
334
335 owcs = ari_conf_get_owcs();
336 if (!owcs || ao2_container_count(owcs) == 0) {
337 ast_debug(3, "No outbound websockets found\n");
338 return NULL;
339 }
340
341 i = ao2_iterator_init(owcs, 0);
342 while ((owc = ao2_iterator_next(&i))) {
343 const char *id = ast_sorcery_object_get_id(owc);
344
345 ast_debug(3, "%s: Checking outbound websocket apps '%s' for app '%s'\n",
346 id, owc->apps, app_name);
347 if (owc->websocket_client->connection_type & ws_type
348 && ast_in_delimited_string(app_name, owc->apps, ',')) {
349 ast_debug(3, "%s: Found correct websocket type for apps '%s' for app '%s'\n",
350 id, owc->apps, app_name);
351 break;
352 }
353 ao2_cleanup(owc);
354 }
356 ao2_cleanup(owcs);
357 if (!owc) {
358 ast_debug(3, "No outbound websocket found for app '%s'\n", app_name);
359 }
360
361 return owc;
362}
363
365{
366 switch (type) {
368 return "persistent";
370 return "per_call";
372 return "per_call_config";
374 return "inbound";
375 case AST_WS_TYPE_ANY:
376 return "any";
377 default:
378 return "unknown";
379 }
380}
381
383 struct ari_conf_outbound_websocket *old_owc,
384 struct ari_conf_outbound_websocket *new_owc)
385{
387 const char *new_id = ast_sorcery_object_get_id(new_owc);
388 RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
389 struct ast_variable *v = NULL;
390 int res = 0;
391 int changes_found = 0;
392
393 ast_debug(2, "%s: Detecting changes\n", new_id);
394
395 res = ast_sorcery_diff(sorcery, old_owc, new_owc, &changes);
396 if (res != 0) {
397 ast_log(LOG_WARNING, "%s: Failed to create changeset\n", new_id);
398 return ARI_OWC_FIELD_NONE;
399 }
400
401 for (v = changes; v; v = v->next) {
402 changes_found = 1;
403 ast_debug(2, "%s: %s changed to %s\n", new_id, v->name, v->value);
404 if (ast_strings_equal(v->name, "apps")) {
405 changed |= ARI_OWC_FIELD_APPS;
406 } else if (ast_strings_equal(v->name, "subscribe_all")) {
408 } else if (ast_strings_equal(v->name, "local_ari_user")) {
410 } else if (ast_strings_equal(v->name, "local_ari_password")) {
412 } else {
413 ast_debug(2, "%s: Unknown change %s\n", new_id, v->name);
414 }
415 }
416 if (!changes_found) {
417 ast_debug(2, "%s: No changes found %p %p\n", new_id,
418 old_owc->websocket_client,new_owc->websocket_client);
419 }
420
422 old_owc->websocket_client, new_owc->websocket_client);
423
424 return changed;
425
426}
427
428/*! \brief \ref ast_ari_conf destructor. */
429static void general_dtor(void *obj)
430{
431 struct ari_conf_general *cfg = obj;
432
434}
435
436static void *general_alloc(const char *name)
437{
439 sizeof(*general), general_dtor);
440
441 if (!general) {
442 return NULL;
443 }
444
445 if (ast_string_field_init(general, 64) != 0) {
446 return NULL;
447 }
448
449 return general;
450}
451
452#define MAX_VARS 128
453
454static int general_apply(const struct ast_sorcery *sorcery, void *obj)
455{
456 struct ari_conf_general *general = obj;
457 char *parse = NULL;
459 AST_APP_ARG(vars)[MAX_VARS];
460 );
461
462 ast_debug(2, "Initializing general config\n");
463
464 parse = ast_strdupa(general->channelvars);
466
468 return 0;
469}
470
471/*! \brief Encoding format handler converts from boolean to enum. */
472static int general_pretty_from_str(const struct aco_option *opt,
473 struct ast_variable *var, void *obj)
474{
475 struct ari_conf_general *general = obj;
476
477 general->format = ast_true(var->value) ? AST_JSON_PRETTY : AST_JSON_COMPACT;
478
479 return 0;
480}
481
483{
484 if (!sorcery) {
485 return NULL;
486 }
487
488 return ast_sorcery_retrieve_by_id(sorcery, "general", "general");
489}
490
491static int general_pretty_to_str(const void *obj, const intptr_t *args, char **buf)
492{
493 const struct ari_conf_general *general = obj;
494
495 if (general->format == AST_JSON_PRETTY) {
496 *buf = ast_strdup("yes");
497 } else {
498 *buf = ast_strdup("no");
499 }
500 return 0;
501}
502
503/*! \brief Destructor for \ref ast_ari_conf_user */
504static void user_dtor(void *obj)
505{
506 struct ari_conf_user *user = obj;
508 ast_debug(3, "%s: Disposing of user\n", ast_sorcery_object_get_id(user));
509}
510
511/*! \brief Allocate an \ref ast_ari_conf_user for config parsing */
512static void *user_alloc(const char *cat)
513{
515 sizeof(*user), user_dtor);
516
517 if (!user) {
518 return NULL;
519 }
520
521 if (ast_string_field_init(user, 64) != 0) {
523 user = NULL;
524 }
525
526 return user;
527}
528
529static int user_apply(const struct ast_sorcery *sorcery, void *obj)
530{
531 struct ari_conf_user *user = obj;
532 const char *id = ast_sorcery_object_get_id(user);
533
534 ast_debug(2, "%s: Initializing user\n", id);
535
536 if (ast_strlen_zero(user->password)) {
537 ast_log(LOG_WARNING, "%s: User missing password\n", id);
538 return -1;
539 }
540
541 return 0;
542}
543
544/*! \brief Parses the ast_ari_password_format enum from a config file */
545static int user_password_format_from_str(const struct aco_option *opt,
546 struct ast_variable *var, void *obj)
547{
548 struct ari_conf_user *user = obj;
549
550 if (strcasecmp(var->value, "plain") == 0) {
551 user->password_format = ARI_PASSWORD_FORMAT_PLAIN;
552 } else if (strcasecmp(var->value, "crypt") == 0) {
553 user->password_format = ARI_PASSWORD_FORMAT_CRYPT;
554 } else {
555 return -1;
556 }
557
558 return 0;
559}
560
561static int user_password_format_to_str(const void *obj, const intptr_t *args, char **buf)
562{
563 const struct ari_conf_user *user = obj;
564
565 if (user->password_format == ARI_PASSWORD_FORMAT_CRYPT) {
566 *buf = ast_strdup("crypt");
567 } else {
568 *buf = ast_strdup("plain");
569 }
570 return 0;
571}
572
574{
575 if (!sorcery) {
576 return NULL;
577 }
578
581}
582
583struct ari_conf_user *ari_conf_get_user(const char *username)
584{
585 if (!sorcery) {
586 return NULL;
587 }
588
589 return ast_sorcery_retrieve_by_id(sorcery, "user", username);
590}
591
592/*
593 * This is called by res_ari.c to validate the user and password
594 * for the websocket connection.
595 */
596struct ari_conf_user *ari_conf_validate_user(const char *username,
597 const char *password)
598{
599 struct ari_conf_user *user = NULL;
600 int is_valid = 0;
601
602 if (ast_strlen_zero(username) || ast_strlen_zero(password)) {
603 return NULL;
604 }
605
606 user = ast_sorcery_retrieve_by_id(sorcery, "user", username);
607 if (!user) {
608 return NULL;
609 }
610
611 switch (user->password_format) {
613 is_valid = strcmp(password, user->password) == 0;
614 break;
616 is_valid = ast_crypt_validate(password, user->password);
617 break;
618 }
619
620 if (!is_valid) {
622 user = NULL;
623 }
624
625 return user;
626}
627
628int ari_sorcery_observer_add(const char *object_type,
629 const struct ast_sorcery_observer *callbacks)
630{
631 if (!sorcery) {
632 return -1;
633 }
634 return ast_sorcery_observer_add(sorcery, object_type, callbacks);
635}
636
637int ari_sorcery_observer_remove(const char *object_type,
638 const struct ast_sorcery_observer *callbacks)
639{
640 if (!sorcery) {
641 return -1;
642 }
644 return 0;
645}
646
649};
650
651static void ws_client_load(const char *name)
652{
653 ast_sorcery_force_reload_object(sorcery, "outbound_websocket");
654}
655
658};
659
662
663static int ari_conf_init(void)
664{
665 int res = 0;
666 ast_debug(2, "Initializing ARI configuration\n");
667
670 outbound_websocket_state_hash_fn, NULL,
671 outbound_websocket_state_cmp_fn);
672 if (!owc_states) {
673 ast_log(LOG_ERROR, "Failed to allocate outbound websocket states\n");
674 return -1;
675 }
676
677 if (!(sorcery = ast_sorcery_open())) {
678 ast_log(LOG_ERROR, "Failed to open sorcery\n");
679 return -1;
680 }
681
682 ast_sorcery_apply_default(sorcery, "general", "config",
683 "ari.conf,criteria=type=general,single_object=yes,explicit_name=general");
684 ast_sorcery_apply_default(sorcery, "user", "config",
685 "ari.conf,criteria=type=user");
686 ast_sorcery_apply_default(sorcery, "outbound_websocket", "config",
687 "ari.conf,criteria=type=outbound_websocket");
688
690 ast_log(LOG_ERROR, "Failed to register ARI general object with sorcery\n");
692 sorcery = NULL;
693 return -1;
694 }
695
697 ast_log(LOG_ERROR, "Failed to register ARI user object with sorcery\n");
699 sorcery = NULL;
700 return -1;
701 }
702
705 ast_log(LOG_ERROR, "Failed to register ARI outbound_websocket object with sorcery\n");
707 sorcery = NULL;
708 return -1;
709 }
710
711 if (ast_sorcery_observer_add(sorcery, "outbound_websocket", &observer_callbacks)) {
712 ast_log(LOG_ERROR, "Failed to register ARI outbound_websocket observer with sorcery\n");
714 sorcery = NULL;
715 return -1;
716 }
717
718 ast_sorcery_object_field_register_nodoc(sorcery, "general", "type", "", OPT_NOOP_T, 0, 0);
719 ast_sorcery_register_sf(general, ari_conf_general, auth_realm, auth_realm, "Asterisk REST Interface");
720 ast_sorcery_register_sf(general, ari_conf_general, allowed_origins, allowed_origins, "");
721 ast_sorcery_register_sf(general, ari_conf_general, channelvars, channelvars, "");
723 ast_sorcery_register_cust(general, pretty, "no");
724 ast_sorcery_register_int(general, ari_conf_general, websocket_write_timeout, write_timeout,
726
727
728 ast_sorcery_object_field_register(sorcery, "user", "type", "", OPT_NOOP_T, 0, 0);
729 ast_sorcery_register_sf(user, ari_conf_user, password, password, "");
730 ast_sorcery_register_bool(user, ari_conf_user, read_only, read_only, "no");
731 ast_sorcery_register_cust(user, password_format, "plain");
732
733 ast_sorcery_object_field_register(sorcery, "outbound_websocket", "type", "", OPT_NOOP_T, 0, 0);
734 ast_sorcery_register_cust(outbound_websocket, websocket_client_id, "");
736 ast_sorcery_register_sf(outbound_websocket, ari_conf_outbound_websocket, local_ari_user, local_ari_user, "");
738
740 if (res < 0) {
741 ast_log(LOG_WARNING, "Failed to register websocket client observer\n");
743 sorcery = NULL;
744 return -1;
745 }
746
747 return 0;
748}
749
751{
752 void (*loader)(const struct ast_sorcery *sorcery, const char *type);
753 const char *msg_prefix;
754
755 if (flags & ARI_CONF_RELOAD) {
757 msg_prefix= "Reloading";
759 } else {
761 msg_prefix= "Loading";
762 }
763
764 if (flags & ARI_CONF_INIT) {
765 if (ari_conf_init() != 0) {
766 ast_log(LOG_ERROR, "Failed to initialize ARI configuration\n");
767 return -1;
768 }
769 }
770
771 if (!sorcery) {
772 ast_log(LOG_ERROR, "ARI configuration not initialized\n");
773 return -1;
774 }
775
776 if (flags & ARI_CONF_LOAD_GENERAL) {
777 ast_debug(2, "%s ARI '%s' configuration\n", msg_prefix, "general");
778 loader(sorcery, "general");
779 }
780
781 if (flags & ARI_CONF_LOAD_USER) {
782 ast_debug(2, "%s ARI '%s' configuration\n", msg_prefix, "user");
783 loader(sorcery, "user");
784 }
785
786 if (flags & ARI_CONF_LOAD_OWC) {
787 ast_debug(2, "%s ARI '%s' configuration\n", msg_prefix, "outbound_websocket");
788 loader(sorcery, "outbound_websocket");
789 }
790
791 return 0;
792}
793
795{
797
799 sorcery = NULL;
801}
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:7847
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:1260
#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:9587
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 @476 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:2380
#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:2486
#define ast_sorcery_register_cust(object, option, def_value)
Register a custom field within an object.
Definition: sorcery.h:1767
@ 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:1868
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:1916
#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:2454
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:1456
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1791
#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:1710
#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:1520
#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:1684
#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:1505
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:1960
#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:1746
#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:2235
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:1871
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:231
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 phoneprov_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:978
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.