Asterisk - The Open Source Telephony Project GIT-master-0a46be9
control.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 Stasis application control support.
22 *
23 * \author David M. Lee, II <dlee@digium.com>
24 */
25
26#include "asterisk.h"
27
29#include "asterisk/stasis_app.h"
30#include "asterisk/causes.h"
31
32#include "command.h"
33#include "control.h"
34#include "app.h"
35#include "asterisk/dial.h"
36#include "asterisk/bridge.h"
40#include "asterisk/frame.h"
41#include "asterisk/pbx.h"
43#include "asterisk/app.h"
44
45#include <signal.h>
46
48
49/*!
50 * \brief Indicates if the Stasis app internals are being shut down
51 */
52static int shutting_down;
53
56 /*! Queue of commands to dispatch on the channel */
58 /*!
59 * The associated channel.
60 * Be very careful with the threading associated w/ manipulating
61 * the channel.
62 */
64 /*!
65 * When a channel is in a bridge, the bridge that it is in.
66 */
68 /*!
69 * Bridge features which should be applied to the channel when it enters the next bridge. These only apply to the next bridge and will be emptied thereafter.
70 */
72 /*!
73 * Holding place for channel's PBX while imparted to a bridge.
74 */
75 struct ast_pbx *pbx;
76 /*!
77 * A list of rules to check before adding a channel to a bridge.
78 */
80 /*!
81 * A list of rules to check before removing a channel from a bridge.
82 */
84 /*!
85 * Silence generator, when silence is being generated.
86 */
88 /*!
89 * The app for which this control is currently controlling.
90 * This can change through the use of the /channels/{channelId}/move
91 * command.
92 */
93 struct stasis_app *app;
94 /*!
95 * The name of the next Stasis application to move to.
96 */
97 char *next_app;
98 /*!
99 * The list of arguments to pass to StasisStart when moving to another app.
100 */
102 /*!
103 * When set, /c app_stasis should exit and continue in the dialplan.
104 */
105 unsigned int is_done:1;
106 /*!
107 * When set, /c app_stasis should exit indicating failure and continue
108 * in the dialplan.
109 */
110 unsigned int failed:1;
111};
112
113static void control_dtor(void *obj)
114{
115 struct stasis_app_control *control = obj;
116
117 ao2_cleanup(control->command_queue);
118
120 ao2_cleanup(control->app);
121
122 control_move_cleanup(control);
123
124 ast_cond_destroy(&control->wait_cond);
128
129}
130
132{
133 struct stasis_app_control *control;
134 int res;
135
136 control = ao2_alloc(sizeof(*control), control_dtor);
137 if (!control) {
138 return NULL;
139 }
140
141 AST_LIST_HEAD_INIT(&control->add_rules);
143
144 res = ast_cond_init(&control->wait_cond, NULL);
145 if (res != 0) {
146 ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
147 strerror(errno));
148 ao2_ref(control, -1);
149 return NULL;
150 }
151
152 control->app = ao2_bump(app);
153
155 control->channel = channel;
156
159 if (!control->command_queue) {
160 ao2_ref(control, -1);
161 return NULL;
162 }
163
164 control->next_app = NULL;
165 AST_VECTOR_INIT(&control->next_app_args, 0);
166
167 return control;
168}
169
171 struct stasis_app_control *control,
172 struct app_control_rules *list, struct stasis_app_control_rule *obj)
173{
174 ao2_lock(control->command_queue);
175 AST_LIST_INSERT_TAIL(list, obj, next);
176 ao2_unlock(control->command_queue);
177}
178
180 struct stasis_app_control *control,
181 struct app_control_rules *list, struct stasis_app_control_rule *obj)
182{
184
185 ao2_lock(control->command_queue);
187 if (rule == obj) {
189 break;
190 }
191 }
193 ao2_unlock(control->command_queue);
194}
195
196/*!
197 * \internal
198 * \brief Checks to make sure each rule in the given list passes.
199 *
200 * \details Loops over a list of rules checking for rejections or failures.
201 * If one rule fails its resulting error code is returned.
202 *
203 * \note Command queue should be locked before calling this function.
204 *
205 * \param control The stasis application control
206 * \param list The list of rules to check
207 *
208 * \retval 0 if all rules pass
209 * \retval non-zero error code if a rule fails
210 */
212 const struct stasis_app_control *control,
213 struct app_control_rules *list)
214{
215 int res = 0;
217 AST_LIST_TRAVERSE(list, rule, next) {
218 if ((res = rule->check_rule(control))) {
219 return res;
220 }
221 }
222 return res;
223}
224
226 struct stasis_app_control *control,
228{
229 return app_control_register_rule(control, &control->add_rules, rule);
230}
231
233 struct stasis_app_control *control,
235{
236 app_control_unregister_rule(control, &control->add_rules, rule);
237}
238
240 struct stasis_app_control *control,
242{
243 return app_control_register_rule(control, &control->remove_rules, rule);
244}
245
247 struct stasis_app_control *control,
249{
250 app_control_unregister_rule(control, &control->remove_rules, rule);
251}
252
254 struct stasis_app_control *control)
255{
256 return app_control_check_rules(control, &control->add_rules);
257}
258
260 struct stasis_app_control *control)
261{
262 return app_control_check_rules(control, &control->remove_rules);
263}
264
265static int noop_cb(struct stasis_app_control *control,
266 struct ast_channel *chan, void *data)
267{
268 return 0;
269}
270
271/*! Callback type to see if the command can execute
272 note: command_queue is locked during callback */
273typedef int (*app_command_can_exec_cb)(struct stasis_app_control *control);
274
276 struct stasis_app_control *control, stasis_app_command_cb command_fn,
278 app_command_can_exec_cb can_exec_fn)
279{
280 int retval;
281 struct stasis_app_command *command;
282
283 command_fn = command_fn ? : noop_cb;
284
285 command = command_create(command_fn, data, data_destructor);
286 if (!command) {
287 return NULL;
288 }
289
290 ao2_lock(control->command_queue);
291 if (control->is_done) {
292 ao2_unlock(control->command_queue);
293 ao2_ref(command, -1);
294 return NULL;
295 }
296 if (can_exec_fn && (retval = can_exec_fn(control))) {
297 ao2_unlock(control->command_queue);
298 command_complete(command, retval);
299 return command;
300 }
301
302 ao2_link_flags(control->command_queue, command, OBJ_NOLOCK);
303 ast_cond_signal(&control->wait_cond);
304
305 if (control->channel) {
306 /* Queue a null frame so that if and when the channel is waited on,
307 return immediately to process the new command */
309 }
310
311 ao2_unlock(control->command_queue);
312
313 return command;
314}
315
317 struct stasis_app_control *control, stasis_app_command_cb command_fn,
319{
320 return exec_command_on_condition(control, command_fn, data, data_destructor, NULL);
321}
322
323static int app_control_add_role(struct stasis_app_control *control,
324 struct ast_channel *chan, void *data)
325{
326 char *role = data;
327
328 return ast_channel_add_bridge_role(chan, role);
329}
330
331int stasis_app_control_add_role(struct stasis_app_control *control, const char *role)
332{
333 char *role_dup;
334
335 role_dup = ast_strdup(role);
336 if (!role_dup) {
337 return -1;
338 }
339
341
342 return 0;
343}
344
346 struct ast_channel *chan, void *data)
347{
349
350 return 0;
351}
352
354{
356}
357
359{
360 return ao2_container_count(control->command_queue);
361}
362
364{
365 /* Called from stasis_app_exec thread; no lock needed */
366 return control->is_done;
367}
368
370{
371 /* Locking necessary to sync with other threads adding commands to the queue. */
372 ao2_lock(control->command_queue);
373 control->is_done = 1;
374 ao2_unlock(control->command_queue);
375}
376
378{
379 control->failed = 1;
380}
381
383{
384 return control->failed;
385}
386
387
392};
393
394static int app_control_continue(struct stasis_app_control *control,
395 struct ast_channel *chan, void *data)
396{
397 struct stasis_app_control_continue_data *continue_data = data;
398
399 ast_assert(control->channel != NULL);
400
401 /* If we're in a Stasis bridge, depart it before going back to the
402 * dialplan */
403 if (stasis_app_get_bridge(control)) {
404 ast_bridge_depart(control->channel);
405 }
406
407 /* Called from stasis_app_exec thread; no lock needed */
408 ast_explicit_goto(control->channel, continue_data->context, continue_data->extension, continue_data->priority);
409
410 control_mark_done(control);
411
412 return 0;
413}
414
415int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority)
416{
417 struct stasis_app_control_continue_data *continue_data;
418
419 if (!(continue_data = ast_calloc(1, sizeof(*continue_data)))) {
420 return -1;
421 }
422 ast_copy_string(continue_data->context, S_OR(context, ""), sizeof(continue_data->context));
423 ast_copy_string(continue_data->extension, S_OR(extension, ""), sizeof(continue_data->extension));
424 if (priority > 0) {
425 continue_data->priority = priority;
426 } else {
427 continue_data->priority = -1;
428 }
429
431
432 return 0;
433}
434
436 char *app_name;
437 char *app_args;
438};
439
440static int app_control_move(struct stasis_app_control *control,
441 struct ast_channel *chan, void *data)
442{
443 struct stasis_app_control_move_data *move_data = data;
444
445 control->next_app = ast_strdup(move_data->app_name);
446 if (!control->next_app) {
447 ast_log(LOG_ERROR, "Allocation failed for next app\n");
448 return -1;
449 }
450
451 if (move_data->app_args) {
452 char *token;
453
454 while ((token = strtok_r(move_data->app_args, ",", &move_data->app_args))) {
455 int res;
456 char *arg;
457
458 if (!(arg = ast_strdup(token))) {
459 ast_log(LOG_ERROR, "Allocation failed for next app arg\n");
460 control_move_cleanup(control);
461 return -1;
462 }
463
464 res = AST_VECTOR_APPEND(&control->next_app_args, arg);
465 if (res) {
466 ast_log(LOG_ERROR, "Failed to append arg to next app args\n");
467 ast_free(arg);
468 control_move_cleanup(control);
469 return -1;
470 }
471 }
472 }
473
474 return 0;
475}
476
477int stasis_app_control_move(struct stasis_app_control *control, const char *app_name, const char *app_args)
478{
479 struct stasis_app_control_move_data *move_data;
480 size_t size;
481
482 size = sizeof(*move_data) + strlen(app_name) + 1;
483 if (app_args) {
484 /* Application arguments are optional */
485 size += strlen(app_args) + 1;
486 }
487
488 if (!(move_data = ast_calloc(1, size))) {
489 return -1;
490 }
491
492 move_data->app_name = (char *)move_data + sizeof(*move_data);
493 strcpy(move_data->app_name, app_name); /* Safe */
494
495 if (app_args) {
496 move_data->app_args = move_data->app_name + strlen(app_name) + 1;
497 strcpy(move_data->app_args, app_args); /* Safe */
498 } else {
499 move_data->app_args = NULL;
500 }
501
503
504 return 0;
505}
506
507static int app_control_redirect(struct stasis_app_control *control,
508 struct ast_channel *chan, void *data)
509{
510 char *endpoint = data;
511 int res;
512
513 ast_assert(control->channel != NULL);
514 ast_assert(endpoint != NULL);
515
516 res = ast_transfer(control->channel, endpoint);
517 if (!res) {
518 ast_log(LOG_NOTICE, "Unsupported transfer requested on channel '%s'\n",
519 ast_channel_name(control->channel));
520 return 0;
521 }
522
523 return 0;
524}
525
526int stasis_app_control_redirect(struct stasis_app_control *control, const char *endpoint)
527{
528 char *endpoint_data = ast_strdup(endpoint);
529
530 if (!endpoint_data) {
531 return -1;
532 }
533
535
536 return 0;
537}
538
542 unsigned int duration;
543 int after;
544 char dtmf[];
545};
546
547static void dtmf_in_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
548{
549 if (dtmf_data->before) {
550 usleep(dtmf_data->before * 1000);
551 }
552
553 ast_dtmf_stream_external(chan, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
554
555 if (dtmf_data->after) {
556 usleep(dtmf_data->after * 1000);
557 }
558}
559
560static void dtmf_no_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
561{
562 if (dtmf_data->before) {
563 ast_safe_sleep(chan, dtmf_data->before);
564 }
565
566 ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
567
568 if (dtmf_data->after) {
569 ast_safe_sleep(chan, dtmf_data->after);
570 }
571}
572
573static int app_control_dtmf(struct stasis_app_control *control,
574 struct ast_channel *chan, void *data)
575{
576 struct stasis_app_control_dtmf_data *dtmf_data = data;
577
578 if (ast_channel_state(chan) != AST_STATE_UP) {
580 }
581
582 if (stasis_app_get_bridge(control)) {
583 dtmf_in_bridge(chan, dtmf_data);
584 } else {
585 dtmf_no_bridge(chan, dtmf_data);
586 }
587
588 return 0;
589}
590
591int stasis_app_control_dtmf(struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
592{
593 struct stasis_app_control_dtmf_data *dtmf_data;
594
595 if (!(dtmf_data = ast_calloc(1, sizeof(*dtmf_data) + strlen(dtmf) + 1))) {
596 return -1;
597 }
598
599 dtmf_data->before = before;
600 dtmf_data->between = between;
601 dtmf_data->duration = duration;
602 dtmf_data->after = after;
603 strcpy(dtmf_data->dtmf, dtmf);
604
606
607 return 0;
608}
609
610static int app_control_ring(struct stasis_app_control *control,
611 struct ast_channel *chan, void *data)
612{
614
615 return 0;
616}
617
619{
621
622 return 0;
623}
624
625static int app_control_ring_stop(struct stasis_app_control *control,
626 struct ast_channel *chan, void *data)
627{
628 ast_indicate(control->channel, -1);
629
630 return 0;
631}
632
634{
636
637 return 0;
638}
639
640static int app_control_progress(struct stasis_app_control *control,
641 struct ast_channel *chan, void *data)
642{
644
645 return 0;
646}
647
649{
651
652 return 0;
653}
654
657 unsigned int direction;
658};
659
660static int app_control_mute(struct stasis_app_control *control,
661 struct ast_channel *chan, void *data)
662{
663 struct stasis_app_control_mute_data *mute_data = data;
664
665 ast_channel_lock(chan);
666 ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);
667 ast_channel_unlock(chan);
668
669 return 0;
670}
671
673{
674 struct stasis_app_control_mute_data *mute_data;
675
676 if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
677 return -1;
678 }
679
680 mute_data->direction = direction;
681 mute_data->frametype = frametype;
682
684
685 return 0;
686}
687
688static int app_control_unmute(struct stasis_app_control *control,
689 struct ast_channel *chan, void *data)
690{
691 struct stasis_app_control_mute_data *mute_data = data;
692
693 ast_channel_lock(chan);
694 ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);
695 ast_channel_unlock(chan);
696
697 return 0;
698}
699
701{
702 struct stasis_app_control_mute_data *mute_data;
703
704 if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
705 return -1;
706 }
707
708 mute_data->direction = direction;
709 mute_data->frametype = frametype;
710
712
713 return 0;
714}
715
716/*!
717 * \brief structure for queuing ARI channel variable setting
718 *
719 * It may seem weird to define this custom structure given that we already have
720 * ast_var_t and ast_variable defined elsewhere. The problem with those is that
721 * they are not tolerant of NULL channel variable value pointers. In fact, in both
722 * cases, the best they could do is to have a zero-length variable value. However,
723 * when un-setting a channel variable, it is important to pass a NULL value, not
724 * a zero-length string.
725 */
726struct chanvar {
727 /*! Name of variable to set/unset */
728 char *name;
729 /*! Value of variable to set. If unsetting, this will be NULL */
730 char *value;
731};
732
733static void free_chanvar(void *data)
734{
735 struct chanvar *var = data;
736
737 ast_free(var->name);
738 ast_free(var->value);
739 ast_free(var);
740}
741
743 struct ast_channel *chan, void *data)
744{
745 struct chanvar *var = data;
746
747 pbx_builtin_setvar_helper(control->channel, var->name, var->value);
748
749 return 0;
750}
751
752int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
753{
754 struct chanvar *var;
755
756 var = ast_calloc(1, sizeof(*var));
757 if (!var) {
758 return -1;
759 }
760
761 var->name = ast_strdup(variable);
762 if (!var->name) {
764 return -1;
765 }
766
767 /* It's kosher for value to be NULL. It means the variable is being unset */
768 if (value) {
769 var->value = ast_strdup(value);
770 if (!var->value) {
772 return -1;
773 }
774 }
775
777
778 return 0;
779}
780
781static int app_control_hold(struct stasis_app_control *control,
782 struct ast_channel *chan, void *data)
783{
785
786 return 0;
787}
788
790{
792}
793
794static int app_control_unhold(struct stasis_app_control *control,
795 struct ast_channel *chan, void *data)
796{
798
799 return 0;
800}
801
803{
805}
806
807static int app_control_moh_start(struct stasis_app_control *control,
808 struct ast_channel *chan, void *data)
809{
810 char *moh_class = data;
811
812 if (ast_channel_state(chan) != AST_STATE_UP) {
814 }
815
816 ast_moh_start(chan, moh_class, NULL);
817
818 return 0;
819}
820
821void stasis_app_control_moh_start(struct stasis_app_control *control, const char *moh_class)
822{
823 char *data = NULL;
824
825 if (!ast_strlen_zero(moh_class)) {
826 data = ast_strdup(moh_class);
827 }
828
830}
831
832static int app_control_moh_stop(struct stasis_app_control *control,
833 struct ast_channel *chan, void *data)
834{
835 ast_moh_stop(chan);
836 return 0;
837}
838
840{
842}
843
845 struct ast_channel *chan, void *data)
846{
847 if (ast_channel_state(chan) != AST_STATE_UP) {
849 }
850
851 if (control->silgen) {
852 /* We have a silence generator, but it may have been implicitly
853 * disabled by media actions (music on hold, playing media,
854 * etc.) Just stop it and restart a new one.
855 */
857 control->channel, control->silgen);
858 }
859
860 ast_debug(3, "%s: Starting silence generator\n",
863
864 if (!control->silgen) {
866 "%s: Failed to start silence generator.\n",
868 }
869
870 return 0;
871}
872
874{
876}
877
879{
880 if (control->silgen) {
881 ast_debug(3, "%s: Stopping silence generator\n",
884 control->channel, control->silgen);
885 control->silgen = NULL;
886 }
887}
888
890 struct ast_channel *chan, void *data)
891{
893 return 0;
894}
895
897{
899}
900
902 const struct stasis_app_control *control)
903{
905}
906
908 stasis_app_command_cb command_fn, void *data,
909 command_data_destructor_fn data_destructor,
910 app_command_can_exec_cb can_exec_fn)
911{
912 int ret;
913 struct stasis_app_command *command;
914
915 if (control == NULL || control->is_done) {
916 /* If exec_command_on_condition fails, it calls the data_destructor.
917 * In order to provide consistent behavior, we'll also call the data_destructor
918 * on this error path. This way, callers never have to call the
919 * data_destructor themselves.
920 */
921 if (data_destructor) {
923 }
924 return -1;
925 }
926
928 control, command_fn, data, data_destructor, can_exec_fn);
929 if (!command) {
930 return -1;
931 }
932
933 ret = command_join(command);
934 ao2_ref(command, -1);
935
936 return ret;
937}
938
941{
942 return app_send_command_on_condition(control, command_fn, data, data_destructor, NULL);
943}
944
946 stasis_app_command_cb command_fn, void *data,
948{
949 struct stasis_app_command *command;
950
951 if (control == NULL || control->is_done) {
952 /* If exec_command fails, it calls the data_destructor. In order to
953 * provide consistent behavior, we'll also call the data_destructor
954 * on this error path. This way, callers never have to call the
955 * data_destructor themselves.
956 */
957 if (data_destructor) {
959 }
960 return -1;
961 }
962
963 command = exec_command(control, command_fn, data, data_destructor);
964 if (!command) {
965 return -1;
966 }
967 ao2_ref(command, -1);
968
969 return 0;
970}
971
973{
974 struct ast_bridge *ret;
975
976 if (!control) {
977 return NULL;
978 }
979
980 ao2_lock(control);
981 ret = control->bridge;
982 ao2_unlock(control);
983
984 return ret;
985}
986
987/*!
988 * \brief Singleton dial bridge
989 *
990 * The dial bridge is a holding bridge used to hold all
991 * outbound dialed channels that are not in any "real" ARI-created
992 * bridge. The dial bridge is invisible, meaning that it does not
993 * show up in channel snapshots, AMI or ARI output, and no events
994 * get raised for it.
995 *
996 * This is used to keep dialed channels confined to the bridging system
997 * and unify the threading model used for dialing outbound channels.
998 */
999static struct ast_bridge *dial_bridge;
1001
1002/*!
1003 * \brief Retrieve a reference to the dial bridge.
1004 *
1005 * If the dial bridge has not been created yet, it will
1006 * be created, otherwise, a reference to the existing bridge
1007 * will be returned.
1008 *
1009 * The caller will need to unreference the dial bridge once
1010 * they are finished with it.
1011 *
1012 * \retval NULL Unable to find/create the dial bridge
1013 * \retval non-NULL A reference to the dial bridge
1014 */
1015static struct ast_bridge *get_dial_bridge(void)
1016{
1017 struct ast_bridge *ret_bridge = NULL;
1018
1020
1021 if (shutting_down) {
1022 goto end;
1023 }
1024
1025 if (dial_bridge) {
1026 ret_bridge = ao2_bump(dial_bridge);
1027 goto end;
1028 }
1029
1030 dial_bridge = stasis_app_bridge_create_invisible("holding", "dial_bridge", NULL);
1031 if (!dial_bridge) {
1032 goto end;
1033 }
1034 ret_bridge = ao2_bump(dial_bridge);
1035
1036end:
1038 return ret_bridge;
1039}
1040
1041static int bridge_channel_depart(struct stasis_app_control *control,
1042 struct ast_channel *chan, void *data);
1043
1044/*!
1045 * \brief after bridge callback for the dial bridge
1046 *
1047 * The only purpose of this callback is to ensure that the control structure's
1048 * bridge pointer is NULLed
1049 */
1050static void dial_bridge_after_cb(struct ast_channel *chan, void *data)
1051{
1052 struct stasis_app_control *control = data;
1053 struct ast_bridge_channel *bridge_channel;
1054
1056 bridge_channel = ast_channel_get_bridge_channel(chan);
1058
1059 ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), ast_channel_hangupcause(chan));
1060
1062
1063 control->bridge = NULL;
1064}
1065
1067{
1068 struct stasis_app_control *control = data;
1069
1070 ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), reason);
1071 dial_bridge_after_cb(control->channel, data);
1072}
1073
1074/*!
1075 * \brief Add a channel to the singleton dial bridge.
1076 *
1077 * \param control The Stasis control structure
1078 * \param chan The channel to add to the bridge
1079 * \retval -1 Failed
1080 * \retval 0 Success
1081 */
1082static int add_to_dial_bridge(struct stasis_app_control *control, struct ast_channel *chan)
1083{
1084 struct ast_bridge *bridge;
1085
1086 bridge = get_dial_bridge();
1087 if (!bridge) {
1088 return -1;
1089 }
1090
1091 control->bridge = bridge;
1094 control->bridge = NULL;
1095 ao2_ref(bridge, -1);
1096 return -1;
1097 }
1098
1099 ao2_ref(bridge, -1);
1100
1101 return 0;
1102}
1103
1104/*!
1105 * \brief Depart a channel from a bridge, and potentially add it back to the dial bridge
1106 *
1107 * \param control Take a guess
1108 * \param chan Take another guess
1109 */
1110static int depart_channel(struct stasis_app_control *control, struct ast_channel *chan)
1111{
1112 ast_bridge_depart(chan);
1113
1114 /* Channels which have a PBX are not ones that have been created and dialed from ARI. They
1115 * have externally come in from the dialplan, and thus should not be placed into the dial
1116 * bridge. Only channels which are created and dialed in ARI should go into the dial bridge.
1117 */
1118 if (!ast_check_hangup(chan) && ast_channel_state(chan) != AST_STATE_UP && !ast_channel_pbx(chan)) {
1119 /* Channel is still being dialed, so put it back in the dialing bridge */
1120 add_to_dial_bridge(control, chan);
1121 }
1122
1123 return 0;
1124}
1125
1127 struct ast_channel *chan, void *data)
1128{
1129 struct ast_bridge_channel *bridge_channel;
1130
1132 bridge_channel = ast_channel_internal_bridge_channel(chan);
1134
1135 if (bridge_channel != data) {
1136 ast_debug(3, "%s: Channel is no longer in departable state\n",
1138 return -1;
1139 }
1140
1141 ast_debug(3, "%s: Channel departing bridge\n",
1143
1144 depart_channel(control, chan);
1145
1146 return 0;
1147}
1148
1149static void internal_bridge_after_cb(struct ast_channel *chan, void *data,
1150 enum ast_bridge_after_cb_reason reason)
1151{
1152 struct stasis_app_control *control = data;
1153 struct ast_bridge_channel *bridge_channel;
1154
1155 ao2_lock(control);
1156 ast_debug(3, "%s, %s: %s\n",
1157 ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown",
1159
1161 /* The impart actually failed so control->bridge isn't valid. */
1162 control->bridge = NULL;
1163 }
1164
1165 ast_assert(chan == control->channel);
1166
1167 /* Restore the channel's PBX */
1168 ast_channel_pbx_set(control->channel, control->pbx);
1169 control->pbx = NULL;
1170
1171 if (control->bridge) {
1172 app_unsubscribe_bridge(control->app, control->bridge);
1173
1174 /* No longer in the bridge */
1175 control->bridge = NULL;
1176
1177 /* Get the bridge channel so we don't depart from the wrong bridge */
1179 bridge_channel = ast_channel_get_bridge_channel(chan);
1181
1182 /* Depart this channel from the bridge using the command queue if possible */
1184 }
1185
1187 /* The channel has had a StasisEnd published on it, but until now had remained in
1188 * the bridging system. This means that the channel moved from a Stasis bridge to a
1189 * non-Stasis bridge and is now exiting the bridging system. Because of this, the
1190 * channel needs to exit the Stasis application and go to wherever the non-Stasis
1191 * bridge has directed it to go. If the non-Stasis bridge has not set up an after
1192 * bridge destination, then the channel should be hung up.
1193 */
1194 int hangup_flag;
1195
1198 ast_softhangup_nolock(chan, hangup_flag);
1200 }
1201 ao2_unlock(control);
1202}
1203
1204static void bridge_after_cb(struct ast_channel *chan, void *data)
1205{
1206 struct stasis_app_control *control = data;
1207
1209}
1210
1212 void *data)
1213{
1214 struct stasis_app_control *control = data;
1215
1216 internal_bridge_after_cb(control->channel, data, reason);
1217
1218 ast_debug(3, " reason: %s\n",
1220}
1221
1222/*!
1223 * \brief Dial timeout datastore
1224 *
1225 * A datastore is used because a channel may change
1226 * bridges during the course of a dial attempt. This
1227 * may be because the channel changes from the dial bridge
1228 * to a standard bridge, or it may move between standard
1229 * bridges. In order to keep the dial timeout, we need
1230 * to keep the timeout information local to the channel.
1231 * That is what this datastore is for
1232 */
1234 .type = "ARI dial timeout",
1235};
1236
1237static int hangup_channel(struct stasis_app_control *control,
1238 struct ast_channel *chan, void *data)
1239{
1240 /* Set cause code to No Answer to be consistent with other dial timeout operations */
1241 ast_channel_lock(chan);
1243 ast_channel_unlock(chan);
1245 return 0;
1246}
1247
1248/*!
1249 * \brief Dial timeout
1250 *
1251 * This is a bridge interval hook callback. The interval hook triggering
1252 * means that the dial timeout has been reached. If the channel has not
1253 * been answered by the time this callback is called, then the channel
1254 * is hung up
1255 *
1256 * \param bridge_channel Bridge channel on which interval hook has been called
1257 * \param ignore Ignored
1258 * \return -1 (i.e. remove the interval hook)
1259 */
1260static int bridge_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
1261{
1262 struct ast_datastore *datastore;
1263 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1264
1265 control = stasis_app_control_find_by_channel(bridge_channel->chan);
1266
1267 ast_channel_lock(bridge_channel->chan);
1268 if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) {
1269 /* Don't bother removing the datastore because it will happen when the channel is hung up */
1270 ast_channel_unlock(bridge_channel->chan);
1272 return -1;
1273 }
1274
1275 datastore = ast_channel_datastore_find(bridge_channel->chan, &timeout_datastore, NULL);
1276 if (!datastore) {
1277 ast_channel_unlock(bridge_channel->chan);
1278 return -1;
1279 }
1280 ast_channel_datastore_remove(bridge_channel->chan, datastore);
1281 ast_channel_unlock(bridge_channel->chan);
1282 ast_datastore_free(datastore);
1283
1284 return -1;
1285}
1286
1287/*!
1288 * \brief Set a dial timeout interval hook on the channel.
1289 *
1290 * The absolute time that the timeout should occur is stored on
1291 * a datastore on the channel. This time is converted into a relative
1292 * number of milliseconds in the future. Then an interval hook is set
1293 * to trigger in that number of milliseconds.
1294 *
1295 * \pre chan is locked
1296 *
1297 * \param chan The channel on which to set the interval hook
1298 */
1299static void set_interval_hook(struct ast_channel *chan)
1300{
1301 struct ast_datastore *datastore;
1302 struct timeval *hangup_time;
1303 int64_t ms;
1304 struct ast_bridge_channel *bridge_channel;
1305
1307 if (!datastore) {
1308 return;
1309 }
1310
1311 hangup_time = datastore->data;
1312
1313 ms = ast_tvdiff_ms(*hangup_time, ast_tvnow());
1314 bridge_channel = ast_channel_get_bridge_channel(chan);
1315 if (!bridge_channel) {
1316 return;
1317 }
1318
1319 if (ast_bridge_interval_hook(bridge_channel->features, 0, ms > 0 ? ms : 1,
1320 bridge_timeout, NULL, NULL, 0)) {
1321 ao2_ref(bridge_channel, -1);
1322 return;
1323 }
1324
1325 ast_queue_frame(bridge_channel->chan, &ast_null_frame);
1326 ao2_ref(bridge_channel, -1);
1327}
1328
1330{
1331 int res;
1332 struct ast_bridge_features *features;
1334
1335 if (!control || !bridge) {
1336 return -1;
1337 }
1338
1339 ast_debug(3, "%s: Adding to bridge %s\n",
1341 bridge->uniqueid);
1342
1343 ast_assert(chan != NULL);
1344
1345 /* Depart whatever Stasis bridge we're currently in. */
1346 if (stasis_app_get_bridge(control)) {
1347 /* Note that it looks like there's a race condition here, since
1348 * we don't have control locked. But this happens from the
1349 * control callback thread, so there won't be any other
1350 * concurrent attempts to bridge.
1351 */
1352 ast_bridge_depart(chan);
1353 }
1354
1355
1357 bridge_after_cb_failed, control);
1358 if (res != 0) {
1359 ast_log(LOG_ERROR, "Error setting after-bridge callback\n");
1360 return -1;
1361 }
1362
1363 ao2_lock(control);
1364
1365 /* Ensure the controlling application is subscribed early enough
1366 * to receive the ChannelEnteredBridge message. This works in concert
1367 * with the subscription handled in the Stasis application execution
1368 * loop */
1369 app_subscribe_bridge(control->app, bridge);
1370
1371 /* Save off the channel's PBX */
1372 ast_assert(control->pbx == NULL);
1373 if (!control->pbx) {
1374 control->pbx = ast_channel_pbx(chan);
1376 }
1377
1378 /* Pull bridge features from the control */
1379 features = control->bridge_features;
1380 control->bridge_features = NULL;
1381 if (features && features->inhibit_colp) {
1383 }
1384
1386 /* We need to set control->bridge here since bridge_after_cb may be run
1387 * before ast_bridge_impart returns. bridge_after_cb gets a reason
1388 * code so it can tell if the bridge is actually valid or not.
1389 */
1390 control->bridge = bridge;
1391
1392 /* We can't be holding the control lock while impart is running
1393 * or we could create a deadlock with bridge_after_cb which also
1394 * tries to lock control.
1395 */
1396 ao2_unlock(control);
1397 res = ast_bridge_impart(bridge,
1398 chan,
1399 swap,
1400 features, /* features */
1401 flags);
1402 if (res != 0) {
1403 /* ast_bridge_impart failed before it could spawn the depart
1404 * thread. The callbacks aren't called in this case.
1405 * The impart could still fail even if ast_bridge_impart returned
1406 * ok but that's handled by bridge_after_cb.
1407 */
1408 ast_log(LOG_ERROR, "Error adding channel to bridge\n");
1409 ao2_lock(control);
1410 ast_channel_pbx_set(chan, control->pbx);
1411 control->pbx = NULL;
1412 control->bridge = NULL;
1413 ao2_unlock(control);
1414 } else {
1415 ast_channel_lock(chan);
1416 set_interval_hook(chan);
1417 ast_channel_unlock(chan);
1418 }
1419
1420 return res;
1421}
1422
1423int control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
1424{
1425 return control_swap_channel_in_bridge(control, data, chan, NULL);
1426}
1427
1429 struct stasis_app_control *control, struct ast_bridge *bridge)
1430{
1431 ast_debug(3, "%s: Sending channel add_to_bridge command\n",
1433
1435 control, control_add_channel_to_bridge, bridge, NULL,
1437}
1438
1440 struct stasis_app_control *control,
1441 struct ast_channel *chan, void *data)
1442{
1443 struct ast_bridge *bridge = data;
1444
1445 if (!control) {
1446 return -1;
1447 }
1448
1449 /* We should only depart from our own bridge */
1450 ast_debug(3, "%s: Departing bridge %s\n",
1452 bridge->uniqueid);
1453
1454 if (bridge != stasis_app_get_bridge(control)) {
1455 ast_log(LOG_WARNING, "%s: Not in bridge %s; not removing\n",
1457 bridge->uniqueid);
1458 return -1;
1459 }
1460
1461 depart_channel(control, chan);
1462 return 0;
1463}
1464
1466 struct stasis_app_control *control, struct ast_bridge *bridge)
1467{
1468 ast_debug(3, "%s: Sending channel remove_from_bridge command\n",
1473}
1474
1476 const struct stasis_app_control *control)
1477{
1478 return ast_channel_uniqueid(control->channel);
1479}
1480
1482 struct stasis_app_control *control, struct stasis_message *message)
1483{
1484 if (!control || !control->channel || !message) {
1485 return;
1486 }
1488}
1489
1492{
1493 return ast_queue_control(control->channel, frame_type);
1494}
1495
1497 struct stasis_app_control *control)
1498{
1499 struct ast_bridge_features *features;
1500
1501 features = ast_bridge_features_new();
1502 if (!features) {
1503 return 1;
1504 }
1505 control->bridge_features = features;
1506 return 0;
1507}
1508
1510 struct stasis_app_control *control, int absorb)
1511{
1512 control->bridge_features->dtmf_passthrough = !absorb;
1513}
1514
1516 struct stasis_app_control *control, int mute)
1517{
1518 control->bridge_features->mute = mute;
1519}
1520
1522 struct stasis_app_control *control, int inhibit_colp)
1523{
1525}
1526
1528{
1529 struct ao2_iterator iter;
1530 struct stasis_app_command *command;
1531
1533 while ((command = ao2_iterator_next(&iter))) {
1534 command_complete(command, -1);
1535 ao2_ref(command, -1);
1536 }
1537 ao2_iterator_destroy(&iter);
1538}
1539
1541 struct ast_channel *chan)
1542{
1543 int count = 0;
1544 struct ao2_iterator iter;
1545 struct stasis_app_command *command;
1546
1547 ast_assert(control->channel == chan);
1548
1550 while ((command = ao2_iterator_next(&iter))) {
1551 command_invoke(command, control, chan);
1552 ao2_ref(command, -1);
1553 ++count;
1554 }
1555 ao2_iterator_destroy(&iter);
1556
1557 return count;
1558}
1559
1561{
1562 if (!control) {
1563 return;
1564 }
1565
1566 ast_assert(control->command_queue != NULL);
1567
1568 ao2_lock(control->command_queue);
1569 while (ao2_container_count(control->command_queue) == 0) {
1570 int res = ast_cond_wait(&control->wait_cond,
1572 if (res < 0) {
1573 ast_log(LOG_ERROR, "Error waiting on command queue\n");
1574 break;
1575 }
1576 }
1577 ao2_unlock(control->command_queue);
1578}
1579
1581 struct ast_channel *chan)
1582{
1583 struct ao2_container *command_queue;
1584 int count = 0;
1585 struct ao2_iterator iter;
1586 struct stasis_app_command *command;
1587
1588 ast_channel_lock(chan);
1589 command_queue = command_prestart_get_container(chan);
1590 ast_channel_unlock(chan);
1591 if (!command_queue) {
1592 return 0;
1593 }
1594
1595 iter = ao2_iterator_init(command_queue, AO2_ITERATOR_UNLINK);
1596
1597 while ((command = ao2_iterator_next(&iter))) {
1598 command_invoke(command, control, chan);
1599 ao2_cleanup(command);
1600 ++count;
1601 }
1602
1603 ao2_iterator_destroy(&iter);
1604 ao2_cleanup(command_queue);
1605 return count;
1606}
1607
1609{
1610 return control->app;
1611}
1612
1614 unsigned int timeout;
1615 char dialstring[0];
1616};
1617
1619 unsigned int timeout)
1620{
1621 struct control_dial_args *args;
1622
1623 args = ast_malloc(sizeof(*args) + strlen(dialstring) + 1);
1624 if (!args) {
1625 return NULL;
1626 }
1627
1628 args->timeout = timeout;
1629 /* Safe */
1630 strcpy(args->dialstring, dialstring);
1631
1632 return args;
1633}
1634
1635static void control_dial_args_destroy(void *data)
1636{
1637 struct control_dial_args *args = data;
1638
1639 ast_free(args);
1640}
1641
1642/*!
1643 * \brief Set dial timeout on a channel to be dialed.
1644 *
1645 * \param chan The channel on which to set the dial timeout
1646 * \param timeout The timeout in seconds
1647 */
1648static int set_timeout(struct ast_channel *chan, unsigned int timeout)
1649{
1650 struct ast_datastore *datastore;
1651 struct timeval *hangup_time;
1652
1653 hangup_time = ast_malloc(sizeof(struct timeval));
1654
1656 if (!datastore) {
1657 return -1;
1658 }
1659 *hangup_time = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1));
1660 datastore->data = hangup_time;
1661
1662 ast_channel_lock(chan);
1663 ast_channel_datastore_add(chan, datastore);
1664
1665 if (ast_channel_is_bridged(chan)) {
1666 set_interval_hook(chan);
1667 }
1668 ast_channel_unlock(chan);
1669
1670 return 0;
1671}
1672
1673static int app_control_dial(struct stasis_app_control *control,
1674 struct ast_channel *chan, void *data)
1675{
1676 struct control_dial_args *args = data;
1677 int bridged;
1678
1679 ast_channel_lock(chan);
1680 bridged = ast_channel_is_bridged(chan);
1681 ast_channel_unlock(chan);
1682
1683 if (!bridged && add_to_dial_bridge(control, chan)) {
1684 return -1;
1685 }
1686
1687 if (args->timeout && set_timeout(chan, args->timeout)) {
1688 return -1;
1689 }
1690
1691 if (ast_call(chan, args->dialstring, 0)) {
1692 /* If call fails normally this channel would then just be normally hung up and destroyed.
1693 * In this case though the channel is being handled by the ARI control thread and dial
1694 * bridge which needs to be notified that the channel should be hung up. To do this we
1695 * queue a soft hangup which will cause each to wake up, see that the channel has been
1696 * hung up, and then destroy it.
1697 */
1698 int hangup_flag;
1700 ast_channel_lock(chan);
1701 ast_softhangup_nolock(chan, hangup_flag);
1702 ast_channel_unlock(chan);
1703 return -1;
1704 }
1705
1706 ast_channel_publish_dial(NULL, chan, args->dialstring, NULL);
1707
1708 return 0;
1709}
1710
1712 const char *dialstring, unsigned int timeout)
1713{
1714 struct control_dial_args *args;
1715
1717 if (!args) {
1718 return -1;
1719 }
1720
1723}
1724
1726{
1728 shutting_down = 1;
1729 if (dial_bridge) {
1731 dial_bridge = NULL;
1732 }
1734}
1735
1736void control_set_app(struct stasis_app_control *control, struct stasis_app *app)
1737{
1738 ao2_cleanup(control->app);
1739 control->app = ao2_bump(app);
1740}
1741
1743{
1744 return control->next_app;
1745}
1746
1748{
1749 ast_free(control->next_app);
1750 control->next_app = NULL;
1751
1753}
1754
1756{
1757 return AST_VECTOR_STEAL_ELEMENTS(&control->next_app_args);
1758}
1759
1761{
1762 return AST_VECTOR_SIZE(&control->next_app_args);
1763}
static const char app[]
Definition: app_adsiprog.c:56
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
@ AO2_ITERATOR_UNLINK
Definition: astobj2.h:1863
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void __ao2_cleanup(void *obj)
Definition: astobj2.c:677
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
Bridging API.
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition: bridge.c:1975
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:1009
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1947
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
Definition: bridge.h:592
@ AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP
Definition: bridge.h:596
After Bridge Execution API.
ast_bridge_after_cb_reason
Definition: bridge_after.h:37
@ AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED
Definition: bridge_after.h:49
@ AST_BRIDGE_AFTER_CB_REASON_DEPART
Definition: bridge_after.h:45
int ast_bridge_setup_after_goto(struct ast_channel *chan)
Setup any after bridge goto location to begin execution.
Definition: bridge_after.c:435
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
Setup an after bridge callback for when the channel leaves the bridging system.
Definition: bridge_after.c:251
const char * ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason)
Get a string representation of an after bridge callback reason.
Definition: bridge_after.c:288
Basic bridge subclass API.
Channel Bridging API.
int ast_bridge_interval_hook(struct ast_bridge_features *features, enum ast_bridge_hook_timer_option flags, unsigned int interval, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach an interval hook to a bridge features structure.
Definition: bridge.c:3398
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3762
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3753
int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.
Definition: bridge_roles.c:313
void ast_channel_clear_bridge_roles(struct ast_channel *chan)
Removes all bridge roles currently on a channel.
Definition: bridge_roles.c:356
Internal Asterisk hangup causes.
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:109
static int priority
const char * ast_channel_name(const struct ast_channel *chan)
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6429
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2355
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2364
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
#define ast_channel_lock(chan)
Definition: channel.h:2972
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8178
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1270
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8224
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1170
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_channel_suppress(struct ast_channel *chan, unsigned int direction, enum ast_frame_type frametype)
Suppress passing of a frame type on a channel.
Definition: channel.c:10791
struct ast_bridge_channel * ast_channel_internal_bridge_channel(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int ast_channel_hangupcause(const struct ast_channel *chan)
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10559
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1146
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2441
#define AST_MAX_CONTEXT
Definition: channel.h:135
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10596
int ast_transfer(struct ast_channel *chan, char *dest)
Transfer a channel (if supported).
Definition: channel.c:6453
int ast_channel_unsuppress(struct ast_channel *chan, unsigned int direction, enum ast_frame_type frametype)
Stop suppressing of a frame type on a channel.
Definition: channel.c:10853
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2428
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3019
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4243
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1542
#define ast_channel_unlock(chan)
Definition: channel.h:2973
#define AST_MAX_EXTENSION
Definition: channel.h:134
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2369
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
frame_type
Definition: codec_builtin.c:44
struct ao2_container * command_prestart_get_container(struct ast_channel *chan)
Get the Stasis() prestart commands for a channel.
Definition: command.c:160
struct stasis_app_command * command_create(stasis_app_command_cb callback, void *data, command_data_destructor_fn data_destructor)
Definition: command.c:55
void command_invoke(struct stasis_app_command *command, struct stasis_app_control *control, struct ast_channel *chan)
Definition: command.c:101
void command_complete(struct stasis_app_command *command, int retval)
Definition: command.c:77
int command_join(struct stasis_app_command *command)
Definition: command.c:86
Internal API for the Stasis application commands.
void stasis_app_control_mute_in_bridge(struct stasis_app_control *control, int mute)
Set whether audio from the channel is muted instead of passing through to the bridge.
Definition: control.c:1515
static void app_control_unregister_rule(struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj)
Definition: control.c:179
void stasis_app_control_register_remove_rule(struct stasis_app_control *control, struct stasis_app_control_rule *rule)
Registers a remove channel from bridge rule.
Definition: control.c:239
static int app_control_progress(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:640
static void set_interval_hook(struct ast_channel *chan)
Set a dial timeout interval hook on the channel.
Definition: control.c:1299
static int app_control_ring(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:610
struct stasis_app_control * control_create(struct ast_channel *channel, struct stasis_app *app)
Create a control object.
Definition: control.c:131
static void dtmf_no_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
Definition: control.c:560
void stasis_app_control_moh_start(struct stasis_app_control *control, const char *moh_class)
Play music on hold to a channel (does not affect hold status)
Definition: control.c:821
const char * stasis_app_control_get_channel_id(const struct stasis_app_control *control)
Returns the uniqueid of the channel associated with this control.
Definition: control.c:1475
static int app_control_continue(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:394
static int set_timeout(struct ast_channel *chan, unsigned int timeout)
Set dial timeout on a channel to be dialed.
Definition: control.c:1648
static int add_to_dial_bridge(struct stasis_app_control *control, struct ast_channel *chan)
Add a channel to the singleton dial bridge.
Definition: control.c:1082
int stasis_app_control_queue_control(struct stasis_app_control *control, enum ast_control_frame_type frame_type)
Queue a control frame without payload.
Definition: control.c:1490
static int app_control_set_channel_var(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:742
void stasis_app_control_mark_failed(struct stasis_app_control *control)
Set the failed flag on a control structure.
Definition: control.c:377
int control_prestart_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all queued prestart commands.
Definition: control.c:1580
static int app_control_clear_roles(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:345
void stasis_app_control_unregister_remove_rule(struct stasis_app_control *control, struct stasis_app_control_rule *rule)
Unregisters a remove channel from bridge rule.
Definition: control.c:246
int control_swap_channel_in_bridge(struct stasis_app_control *control, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap)
Command for swapping a channel in a bridge.
Definition: control.c:1329
int stasis_app_control_unmute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
Unmute the channel associated with this control.
Definition: control.c:700
void stasis_app_control_unhold(struct stasis_app_control *control)
Remove the channel associated with the control from hold.
Definition: control.c:802
static struct stasis_app_command * exec_command_on_condition(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
Definition: control.c:275
int stasis_app_control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_bridge *bridge)
Add a channel to the bridge.
Definition: control.c:1428
void control_wait(struct stasis_app_control *control)
Blocks until control's command queue has a command available.
Definition: control.c:1560
int stasis_app_control_is_failed(const struct stasis_app_control *control)
Check if a control object is marked as "failed".
Definition: control.c:382
char ** control_next_app_args(struct stasis_app_control *control)
Returns the list of arguments to pass to the application we are moving to.
Definition: control.c:1755
static void bridge_after_cb(struct ast_channel *chan, void *data)
Definition: control.c:1204
int stasis_app_send_command(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
Invokes a command on a control's channel.
Definition: control.c:939
void stasis_app_control_silence_start(struct stasis_app_control *control)
Start playing silence to a channel.
Definition: control.c:873
void stasis_app_control_silence_stop(struct stasis_app_control *control)
Stop playing silence to a channel.
Definition: control.c:896
int control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Command callback for adding a channel to a bridge.
Definition: control.c:1423
static void dial_bridge_after_cb(struct ast_channel *chan, void *data)
after bridge callback for the dial bridge
Definition: control.c:1050
void stasis_app_control_clear_roles(struct stasis_app_control *control)
Clear bridge roles currently applied to a channel controlled by a stasis app control.
Definition: control.c:353
int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority)
Exit res_stasis and continue execution in the dialplan.
Definition: control.c:415
static int app_control_ring_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:625
static int app_control_hold(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:781
static enum stasis_app_control_channel_result app_control_check_rules(const struct stasis_app_control *control, struct app_control_rules *list)
Definition: control.c:211
static int app_control_unhold(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:794
int control_is_done(struct stasis_app_control *control)
Returns true if control_continue() has been called on this control.
Definition: control.c:363
static void free_chanvar(void *data)
Definition: control.c:733
void stasis_app_control_publish(struct stasis_app_control *control, struct stasis_message *message)
Publish a message to the control's channel's topic.
Definition: control.c:1481
int stasis_app_control_redirect(struct stasis_app_control *control, const char *endpoint)
Redirect a channel in res_stasis to a particular endpoint.
Definition: control.c:526
static int app_control_remove_channel_from_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1439
void stasis_app_control_moh_stop(struct stasis_app_control *control)
Stop playing music on hold to a channel (does not affect hold status)
Definition: control.c:839
static struct control_dial_args * control_dial_args_alloc(const char *dialstring, unsigned int timeout)
Definition: control.c:1618
int stasis_app_control_move(struct stasis_app_control *control, const char *app_name, const char *app_args)
Exit res_stasis and move to another Stasis application.
Definition: control.c:477
int stasis_app_control_mute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
Mute the channel associated with this control.
Definition: control.c:672
static struct ast_bridge * dial_bridge
Singleton dial bridge.
Definition: control.c:999
void stasis_app_control_absorb_dtmf_in_bridge(struct stasis_app_control *control, int absorb)
Set whether DTMF from the channel is absorbed instead of passing through to the bridge.
Definition: control.c:1509
struct ast_datastore_info timeout_datastore
Dial timeout datastore.
Definition: control.c:1233
static int app_control_moh_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:832
static void bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition: control.c:1211
int(* app_command_can_exec_cb)(struct stasis_app_control *control)
Definition: control.c:273
static int noop_cb(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:265
int stasis_app_control_dtmf(struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
Send DTMF to the channel associated with this control.
Definition: control.c:591
static int shutting_down
Indicates if the Stasis app internals are being shut down.
Definition: control.c:52
void control_flush_queue(struct stasis_app_control *control)
Flush the control command queue.
Definition: control.c:1527
int stasis_app_control_add_role(struct stasis_app_control *control, const char *role)
Apply a bridge role to a channel controlled by a stasis app control.
Definition: control.c:331
static int app_control_add_role(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:323
void stasis_app_control_inhibit_colp_in_bridge(struct stasis_app_control *control, int inhibit_colp)
Set whether COLP frames should be generated when joining the bridge.
Definition: control.c:1521
static int app_send_command_on_condition(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
Definition: control.c:907
int stasis_app_control_remove_channel_from_bridge(struct stasis_app_control *control, struct ast_bridge *bridge)
Remove a channel from the bridge.
Definition: control.c:1465
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition: control.c:972
int stasis_app_send_command_async(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
Asynchronous version of stasis_app_send_command().
Definition: control.c:945
int stasis_app_control_bridge_features_init(struct stasis_app_control *control)
Initialize bridge features into a channel control.
Definition: control.c:1496
static int app_control_move(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:440
static int hangup_channel(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1237
static int depart_channel(struct stasis_app_control *control, struct ast_channel *chan)
Depart a channel from a bridge, and potentially add it back to the dial bridge.
Definition: control.c:1110
void stasis_app_control_hold(struct stasis_app_control *control)
Place the channel associated with the control on hold.
Definition: control.c:789
int control_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all commands enqueued to this control.
Definition: control.c:1540
int control_next_app_args_size(struct stasis_app_control *control)
Returns the number of arguments to be passed to the application we are moving to.
Definition: control.c:1760
void stasis_app_control_unregister_add_rule(struct stasis_app_control *control, struct stasis_app_control_rule *rule)
UnRegister an add channel to bridge rule.
Definition: control.c:232
void control_set_app(struct stasis_app_control *control, struct stasis_app *app)
Set the application the control object belongs to.
Definition: control.c:1736
static void dtmf_in_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
Definition: control.c:547
static int app_control_unmute(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:688
static void app_control_register_rule(struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj)
Definition: control.c:170
int stasis_app_control_ring_stop(struct stasis_app_control *control)
Stop locally generated ringing on the channel associated with this control.
Definition: control.c:633
static int app_control_redirect(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:507
int stasis_app_control_dial(struct stasis_app_control *control, const char *dialstring, unsigned int timeout)
Dial a channel.
Definition: control.c:1711
static int bridge_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
Dial timeout.
Definition: control.c:1260
struct ast_channel_snapshot * stasis_app_control_get_snapshot(const struct stasis_app_control *control)
Returns the most recent snapshot for the associated channel.
Definition: control.c:901
int control_command_count(struct stasis_app_control *control)
Returns the count of items in a control's command queue.
Definition: control.c:358
static int app_control_can_remove_channel_from_bridge(struct stasis_app_control *control)
Definition: control.c:259
static void control_dial_args_destroy(void *data)
Definition: control.c:1635
void stasis_app_control_register_add_rule(struct stasis_app_control *control, struct stasis_app_control_rule *rule)
Registers an add channel to bridge rule.
Definition: control.c:225
void control_silence_stop_now(struct stasis_app_control *control)
Stop playing silence to a channel right now.
Definition: control.c:878
static int app_control_silence_start(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:844
static int app_control_can_add_channel_to_bridge(struct stasis_app_control *control)
Definition: control.c:253
static struct stasis_app_command * exec_command(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
Definition: control.c:316
static int app_control_dial(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1673
static int app_control_moh_start(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:807
static ast_mutex_t dial_bridge_lock
Definition: control.c:1000
static int bridge_channel_depart(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1126
static struct ast_bridge * get_dial_bridge(void)
Retrieve a reference to the dial bridge.
Definition: control.c:1015
char * control_next_app(struct stasis_app_control *control)
Returns the name of the application we are moving to.
Definition: control.c:1742
static void internal_bridge_after_cb(struct ast_channel *chan, void *data, enum ast_bridge_after_cb_reason reason)
Definition: control.c:1149
static int app_control_dtmf(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:573
struct stasis_app * control_app(struct stasis_app_control *control)
Returns the pointer (non-reffed) to the app associated with this control.
Definition: control.c:1608
int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
Set a variable on the channel associated with this control to value.
Definition: control.c:752
static int app_control_silence_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:889
static int app_control_mute(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:660
static void dial_bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition: control.c:1066
int stasis_app_control_ring(struct stasis_app_control *control)
Indicate ringing to the channel associated with this control.
Definition: control.c:618
int stasis_app_control_progress(struct stasis_app_control *control)
Indicate progress to the channel associated with this control.
Definition: control.c:648
void control_move_cleanup(struct stasis_app_control *control)
Free any memory that was allocated for switching applications via /channels/{channelId}/move.
Definition: control.c:1747
void stasis_app_control_shutdown(void)
Let Stasis app internals shut down.
Definition: control.c:1725
static void control_dtor(void *obj)
Definition: control.c:113
void control_mark_done(struct stasis_app_control *control)
Definition: control.c:369
Internal API for the Stasis application controller.
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
Dialing API.
char * end
Definition: eagi_proxy.c:73
direction
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
void ast_dtmf_stream_external(struct ast_channel *chan, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel from an external thread.
Definition: main/app.c:1142
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel.
Definition: main/app.c:1127
Asterisk internal frame definitions.
ast_frame_type
Frame types.
ast_control_frame_type
Internal control frame subtype field values.
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_RINGING
@ AST_CONTROL_HOLD
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:653
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:173
#define ast_cond_destroy(cond)
Definition: lock.h:209
#define ast_cond_wait(cond, mutex)
Definition: lock.h:212
#define ast_cond_init(cond, attr)
Definition: lock.h:208
#define ast_mutex_unlock(a)
Definition: lock.h:197
pthread_cond_t ast_cond_t
Definition: lock.h:185
#define ast_mutex_lock(a)
Definition: lock.h:196
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:527
#define ast_cond_signal(cond)
Definition: lock.h:210
int errno
Music on hold handling.
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7748
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7758
def ignore(key=None, val=None, section=None, pjsip=None, nmapped=None, type='endpoint')
Definition: sip_to_pjsip.py:48
Core PBX routines and definitions.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6966
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Add a bridge subscription to an existing channel subscription.
int app_unsubscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Cancel the bridge subscription for an application.
Internal API for the Stasis application controller.
#define NULL
Definition: resample.c:96
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1538
Stasis Application API. See Stasis Application API for detailed documentation.
struct ast_bridge * stasis_app_bridge_create_invisible(const char *type, const char *name, const char *id)
Create an invisible bridge of the specified type.
Definition: res_stasis.c:896
stasis_app_control_channel_result
Result codes used when adding/removing channels to/from bridges.
Definition: stasis_app.h:810
int stasis_app_channel_is_stasis_end_published(struct ast_channel *chan)
Has this channel had a StasisEnd published on it?
Definition: res_stasis.c:1344
struct stasis_app_control * stasis_app_control_find_by_channel(const struct ast_channel *chan)
Returns the handler for the given channel.
Definition: res_stasis.c:338
void(* command_data_destructor_fn)(void *data)
Typedef for data destructor for stasis app commands.
int(* stasis_app_command_cb)(struct stasis_app_control *control, struct ast_channel *chan, void *data)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
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
Structure that contains information regarding a channel in a bridge.
struct ast_channel * swap
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_bridge_features * features
struct ast_channel * chan
Structure that contains features information.
unsigned int dtmf_passthrough
unsigned int inhibit_colp
Structure that contains information about a bridge.
Definition: bridge.h:353
const ast_string_field uniqueid
Definition: bridge.h:405
Structure representing a snapshot of channel state.
Main Channel structure associated with a channel.
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
Definition: pbx.h:215
structure for queuing ARI channel variable setting
Definition: control.c:726
char * value
Definition: control.c:730
char * name
Definition: control.c:728
char dialstring[0]
Definition: control.c:1615
unsigned int timeout
Definition: control.c:1614
structure to hold extensions
command_data_destructor_fn data_destructor
Definition: command.c:38
char extension[AST_MAX_EXTENSION]
Definition: control.c:390
char context[AST_MAX_CONTEXT]
Definition: control.c:389
enum ast_frame_type frametype
Definition: control.c:656
Rule to check to see if an operation is allowed.
Definition: stasis_app.h:355
struct stasis_app_control_rule * next
Definition: stasis_app.h:365
struct stasis_app * app
Definition: control.c:93
struct ast_bridge_features * bridge_features
Definition: control.c:71
struct ast_channel * channel
Definition: control.c:63
struct ast_bridge * bridge
Definition: control.c:67
struct ao2_container * command_queue
Definition: control.c:57
unsigned int is_done
Definition: control.c:105
struct stasis_app_control::@495 next_app_args
struct app_control_rules remove_rules
Definition: control.c:83
struct ast_silence_generator * silgen
Definition: control.c:87
char * next_app
Definition: control.c:97
struct app_control_rules add_rules
Definition: control.c:79
unsigned int failed
Definition: control.c:110
ast_cond_t wait_cond
Definition: control.c:55
struct ast_pbx * pbx
Definition: control.c:75
int value
Definition: syslog.c:37
const char * args
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#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
#define ast_assert(a)
Definition: utils.h:776
#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_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition: vector.h:151
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:124
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:267
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44