Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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
31#include "command.h"
32#include "control.h"
33#include "app.h"
34#include "asterisk/dial.h"
35#include "asterisk/bridge.h"
39#include "asterisk/frame.h"
40#include "asterisk/pbx.h"
42#include "asterisk/app.h"
43
45
46/*!
47 * \brief Indicates if the Stasis app internals are being shut down
48 */
49static int shutting_down;
50
53 /*! Queue of commands to dispatch on the channel */
55 /*!
56 * The associated channel.
57 * Be very careful with the threading associated w/ manipulating
58 * the channel.
59 */
61 /*!
62 * When a channel is in a bridge, the bridge that it is in.
63 */
65 /*!
66 * 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.
67 */
69 /*!
70 * Holding place for channel's PBX while imparted to a bridge.
71 */
72 struct ast_pbx *pbx;
73 /*!
74 * A list of rules to check before adding a channel to a bridge.
75 */
77 /*!
78 * A list of rules to check before removing a channel from a bridge.
79 */
81 /*!
82 * Silence generator, when silence is being generated.
83 */
85 /*!
86 * The app for which this control is currently controlling.
87 * This can change through the use of the /channels/{channelId}/move
88 * command.
89 */
90 struct stasis_app *app;
91 /*!
92 * The name of the next Stasis application to move to.
93 */
94 char *next_app;
95 /*!
96 * The thread currently blocking on the channel.
97 */
98 pthread_t control_thread;
99 /*!
100 * The list of arguments to pass to StasisStart when moving to another app.
101 */
103 /*!
104 * When set, /c app_stasis should exit and continue in the dialplan.
105 */
106 unsigned int is_done:1;
107};
108
109static void control_dtor(void *obj)
110{
111 struct stasis_app_control *control = obj;
112
113 ao2_cleanup(control->command_queue);
114
116 ao2_cleanup(control->app);
117
118 control_move_cleanup(control);
119
120 ast_cond_destroy(&control->wait_cond);
124
125}
126
128{
129 struct stasis_app_control *control;
130 int res;
131
132 control = ao2_alloc(sizeof(*control), control_dtor);
133 if (!control) {
134 return NULL;
135 }
136
137 AST_LIST_HEAD_INIT(&control->add_rules);
139
140 res = ast_cond_init(&control->wait_cond, NULL);
141 if (res != 0) {
142 ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
143 strerror(errno));
144 ao2_ref(control, -1);
145 return NULL;
146 }
147
148 control->app = ao2_bump(app);
149
151 control->channel = channel;
152
155 if (!control->command_queue) {
156 ao2_ref(control, -1);
157 return NULL;
158 }
159
160 control->next_app = NULL;
161 AST_VECTOR_INIT(&control->next_app_args, 0);
162
164
165 return control;
166}
167
169 struct stasis_app_control *control,
170 struct app_control_rules *list, struct stasis_app_control_rule *obj)
171{
172 ao2_lock(control->command_queue);
173 AST_LIST_INSERT_TAIL(list, obj, next);
174 ao2_unlock(control->command_queue);
175}
176
178 struct stasis_app_control *control,
179 struct app_control_rules *list, struct stasis_app_control_rule *obj)
180{
182
183 ao2_lock(control->command_queue);
185 if (rule == obj) {
187 break;
188 }
189 }
191 ao2_unlock(control->command_queue);
192}
193
194void control_set_thread(struct stasis_app_control *control, pthread_t threadid)
195{
196 ao2_lock(control->command_queue);
197 control->control_thread = threadid;
198 ao2_unlock(control->command_queue);
199}
200
201/*!
202 * \internal
203 * \brief Checks to make sure each rule in the given list passes.
204 *
205 * \details Loops over a list of rules checking for rejections or failures.
206 * If one rule fails its resulting error code is returned.
207 *
208 * \note Command queue should be locked before calling this function.
209 *
210 * \param control The stasis application control
211 * \param list The list of rules to check
212 *
213 * \retval 0 if all rules pass
214 * \retval non-zero error code if a rule fails
215 */
217 const struct stasis_app_control *control,
218 struct app_control_rules *list)
219{
220 int res = 0;
222 AST_LIST_TRAVERSE(list, rule, next) {
223 if ((res = rule->check_rule(control))) {
224 return res;
225 }
226 }
227 return res;
228}
229
231 struct stasis_app_control *control,
233{
234 return app_control_register_rule(control, &control->add_rules, rule);
235}
236
238 struct stasis_app_control *control,
240{
241 app_control_unregister_rule(control, &control->add_rules, rule);
242}
243
245 struct stasis_app_control *control,
247{
248 return app_control_register_rule(control, &control->remove_rules, rule);
249}
250
252 struct stasis_app_control *control,
254{
255 app_control_unregister_rule(control, &control->remove_rules, rule);
256}
257
259 struct stasis_app_control *control)
260{
261 return app_control_check_rules(control, &control->add_rules);
262}
263
265 struct stasis_app_control *control)
266{
267 return app_control_check_rules(control, &control->remove_rules);
268}
269
270static int noop_cb(struct stasis_app_control *control,
271 struct ast_channel *chan, void *data)
272{
273 return 0;
274}
275
276/*! Callback type to see if the command can execute
277 note: command_queue is locked during callback */
278typedef int (*app_command_can_exec_cb)(struct stasis_app_control *control);
279
281 struct stasis_app_control *control, stasis_app_command_cb command_fn,
283 app_command_can_exec_cb can_exec_fn)
284{
285 int retval;
286 struct stasis_app_command *command;
287
288 command_fn = command_fn ? : noop_cb;
289
290 command = command_create(command_fn, data, data_destructor);
291 if (!command) {
292 return NULL;
293 }
294
295 ao2_lock(control->command_queue);
296 if (control->is_done) {
297 ao2_unlock(control->command_queue);
298 ao2_ref(command, -1);
299 return NULL;
300 }
301 if (can_exec_fn && (retval = can_exec_fn(control))) {
302 ao2_unlock(control->command_queue);
303 command_complete(command, retval);
304 return command;
305 }
306
307 ao2_link_flags(control->command_queue, command, OBJ_NOLOCK);
308 ast_cond_signal(&control->wait_cond);
309
310 if (control->control_thread != AST_PTHREADT_NULL) {
311 /* if the control thread is waiting on the channel, send the SIGURG
312 to let it know there is a new command */
313 pthread_kill(control->control_thread, SIGURG);
314 }
315
316 ao2_unlock(control->command_queue);
317
318 return command;
319}
320
322 struct stasis_app_control *control, stasis_app_command_cb command_fn,
324{
325 return exec_command_on_condition(control, command_fn, data, data_destructor, NULL);
326}
327
328static int app_control_add_role(struct stasis_app_control *control,
329 struct ast_channel *chan, void *data)
330{
331 char *role = data;
332
333 return ast_channel_add_bridge_role(chan, role);
334}
335
336int stasis_app_control_add_role(struct stasis_app_control *control, const char *role)
337{
338 char *role_dup;
339
340 role_dup = ast_strdup(role);
341 if (!role_dup) {
342 return -1;
343 }
344
346
347 return 0;
348}
349
351 struct ast_channel *chan, void *data)
352{
354
355 return 0;
356}
357
359{
361}
362
364{
365 return ao2_container_count(control->command_queue);
366}
367
369{
370 /* Called from stasis_app_exec thread; no lock needed */
371 return control->is_done;
372}
373
375{
376 /* Locking necessary to sync with other threads adding commands to the queue. */
377 ao2_lock(control->command_queue);
378 control->is_done = 1;
379 ao2_unlock(control->command_queue);
380}
381
386};
387
388static int app_control_continue(struct stasis_app_control *control,
389 struct ast_channel *chan, void *data)
390{
391 struct stasis_app_control_continue_data *continue_data = data;
392
393 ast_assert(control->channel != NULL);
394
395 /* If we're in a Stasis bridge, depart it before going back to the
396 * dialplan */
397 if (stasis_app_get_bridge(control)) {
398 ast_bridge_depart(control->channel);
399 }
400
401 /* Called from stasis_app_exec thread; no lock needed */
402 ast_explicit_goto(control->channel, continue_data->context, continue_data->extension, continue_data->priority);
403
404 control_mark_done(control);
405
406 return 0;
407}
408
409int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority)
410{
411 struct stasis_app_control_continue_data *continue_data;
412
413 if (!(continue_data = ast_calloc(1, sizeof(*continue_data)))) {
414 return -1;
415 }
416 ast_copy_string(continue_data->context, S_OR(context, ""), sizeof(continue_data->context));
417 ast_copy_string(continue_data->extension, S_OR(extension, ""), sizeof(continue_data->extension));
418 if (priority > 0) {
419 continue_data->priority = priority;
420 } else {
421 continue_data->priority = -1;
422 }
423
425
426 return 0;
427}
428
430 char *app_name;
431 char *app_args;
432};
433
434static int app_control_move(struct stasis_app_control *control,
435 struct ast_channel *chan, void *data)
436{
437 struct stasis_app_control_move_data *move_data = data;
438
439 control->next_app = ast_strdup(move_data->app_name);
440 if (!control->next_app) {
441 ast_log(LOG_ERROR, "Allocation failed for next app\n");
442 return -1;
443 }
444
445 if (move_data->app_args) {
446 char *token;
447
448 while ((token = strtok_r(move_data->app_args, ",", &move_data->app_args))) {
449 int res;
450 char *arg;
451
452 if (!(arg = ast_strdup(token))) {
453 ast_log(LOG_ERROR, "Allocation failed for next app arg\n");
454 control_move_cleanup(control);
455 return -1;
456 }
457
458 res = AST_VECTOR_APPEND(&control->next_app_args, arg);
459 if (res) {
460 ast_log(LOG_ERROR, "Failed to append arg to next app args\n");
461 ast_free(arg);
462 control_move_cleanup(control);
463 return -1;
464 }
465 }
466 }
467
468 return 0;
469}
470
471int stasis_app_control_move(struct stasis_app_control *control, const char *app_name, const char *app_args)
472{
473 struct stasis_app_control_move_data *move_data;
474 size_t size;
475
476 size = sizeof(*move_data) + strlen(app_name) + 1;
477 if (app_args) {
478 /* Application arguments are optional */
479 size += strlen(app_args) + 1;
480 }
481
482 if (!(move_data = ast_calloc(1, size))) {
483 return -1;
484 }
485
486 move_data->app_name = (char *)move_data + sizeof(*move_data);
487 strcpy(move_data->app_name, app_name); /* Safe */
488
489 if (app_args) {
490 move_data->app_args = move_data->app_name + strlen(app_name) + 1;
491 strcpy(move_data->app_args, app_args); /* Safe */
492 } else {
493 move_data->app_args = NULL;
494 }
495
497
498 return 0;
499}
500
501static int app_control_redirect(struct stasis_app_control *control,
502 struct ast_channel *chan, void *data)
503{
504 char *endpoint = data;
505 int res;
506
507 ast_assert(control->channel != NULL);
508 ast_assert(endpoint != NULL);
509
510 res = ast_transfer(control->channel, endpoint);
511 if (!res) {
512 ast_log(LOG_NOTICE, "Unsupported transfer requested on channel '%s'\n",
513 ast_channel_name(control->channel));
514 return 0;
515 }
516
517 return 0;
518}
519
520int stasis_app_control_redirect(struct stasis_app_control *control, const char *endpoint)
521{
522 char *endpoint_data = ast_strdup(endpoint);
523
524 if (!endpoint_data) {
525 return -1;
526 }
527
529
530 return 0;
531}
532
536 unsigned int duration;
537 int after;
538 char dtmf[];
539};
540
541static void dtmf_in_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
542{
543 if (dtmf_data->before) {
544 usleep(dtmf_data->before * 1000);
545 }
546
547 ast_dtmf_stream_external(chan, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
548
549 if (dtmf_data->after) {
550 usleep(dtmf_data->after * 1000);
551 }
552}
553
554static void dtmf_no_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
555{
556 if (dtmf_data->before) {
557 ast_safe_sleep(chan, dtmf_data->before);
558 }
559
560 ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
561
562 if (dtmf_data->after) {
563 ast_safe_sleep(chan, dtmf_data->after);
564 }
565}
566
567static int app_control_dtmf(struct stasis_app_control *control,
568 struct ast_channel *chan, void *data)
569{
570 struct stasis_app_control_dtmf_data *dtmf_data = data;
571
572 if (ast_channel_state(chan) != AST_STATE_UP) {
574 }
575
576 if (stasis_app_get_bridge(control)) {
577 dtmf_in_bridge(chan, dtmf_data);
578 } else {
579 dtmf_no_bridge(chan, dtmf_data);
580 }
581
582 return 0;
583}
584
585int stasis_app_control_dtmf(struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
586{
587 struct stasis_app_control_dtmf_data *dtmf_data;
588
589 if (!(dtmf_data = ast_calloc(1, sizeof(*dtmf_data) + strlen(dtmf) + 1))) {
590 return -1;
591 }
592
593 dtmf_data->before = before;
594 dtmf_data->between = between;
595 dtmf_data->duration = duration;
596 dtmf_data->after = after;
597 strcpy(dtmf_data->dtmf, dtmf);
598
600
601 return 0;
602}
603
604static int app_control_ring(struct stasis_app_control *control,
605 struct ast_channel *chan, void *data)
606{
608
609 return 0;
610}
611
613{
615
616 return 0;
617}
618
619static int app_control_ring_stop(struct stasis_app_control *control,
620 struct ast_channel *chan, void *data)
621{
622 ast_indicate(control->channel, -1);
623
624 return 0;
625}
626
628{
630
631 return 0;
632}
633
636 unsigned int direction;
637};
638
639static int app_control_mute(struct stasis_app_control *control,
640 struct ast_channel *chan, void *data)
641{
642 struct stasis_app_control_mute_data *mute_data = data;
643
644 ast_channel_lock(chan);
645 ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);
646 ast_channel_unlock(chan);
647
648 return 0;
649}
650
652{
653 struct stasis_app_control_mute_data *mute_data;
654
655 if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
656 return -1;
657 }
658
659 mute_data->direction = direction;
660 mute_data->frametype = frametype;
661
663
664 return 0;
665}
666
667static int app_control_unmute(struct stasis_app_control *control,
668 struct ast_channel *chan, void *data)
669{
670 struct stasis_app_control_mute_data *mute_data = data;
671
672 ast_channel_lock(chan);
673 ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);
674 ast_channel_unlock(chan);
675
676 return 0;
677}
678
680{
681 struct stasis_app_control_mute_data *mute_data;
682
683 if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
684 return -1;
685 }
686
687 mute_data->direction = direction;
688 mute_data->frametype = frametype;
689
691
692 return 0;
693}
694
695/*!
696 * \brief structure for queuing ARI channel variable setting
697 *
698 * It may seem weird to define this custom structure given that we already have
699 * ast_var_t and ast_variable defined elsewhere. The problem with those is that
700 * they are not tolerant of NULL channel variable value pointers. In fact, in both
701 * cases, the best they could do is to have a zero-length variable value. However,
702 * when un-setting a channel variable, it is important to pass a NULL value, not
703 * a zero-length string.
704 */
705struct chanvar {
706 /*! Name of variable to set/unset */
707 char *name;
708 /*! Value of variable to set. If unsetting, this will be NULL */
709 char *value;
710};
711
712static void free_chanvar(void *data)
713{
714 struct chanvar *var = data;
715
716 ast_free(var->name);
717 ast_free(var->value);
718 ast_free(var);
719}
720
722 struct ast_channel *chan, void *data)
723{
724 struct chanvar *var = data;
725
726 pbx_builtin_setvar_helper(control->channel, var->name, var->value);
727
728 return 0;
729}
730
731int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
732{
733 struct chanvar *var;
734
735 var = ast_calloc(1, sizeof(*var));
736 if (!var) {
737 return -1;
738 }
739
740 var->name = ast_strdup(variable);
741 if (!var->name) {
743 return -1;
744 }
745
746 /* It's kosher for value to be NULL. It means the variable is being unset */
747 if (value) {
748 var->value = ast_strdup(value);
749 if (!var->value) {
751 return -1;
752 }
753 }
754
756
757 return 0;
758}
759
760static int app_control_hold(struct stasis_app_control *control,
761 struct ast_channel *chan, void *data)
762{
764
765 return 0;
766}
767
769{
771}
772
773static int app_control_unhold(struct stasis_app_control *control,
774 struct ast_channel *chan, void *data)
775{
777
778 return 0;
779}
780
782{
784}
785
786static int app_control_moh_start(struct stasis_app_control *control,
787 struct ast_channel *chan, void *data)
788{
789 char *moh_class = data;
790
791 if (ast_channel_state(chan) != AST_STATE_UP) {
793 }
794
795 ast_moh_start(chan, moh_class, NULL);
796
797 return 0;
798}
799
800void stasis_app_control_moh_start(struct stasis_app_control *control, const char *moh_class)
801{
802 char *data = NULL;
803
804 if (!ast_strlen_zero(moh_class)) {
805 data = ast_strdup(moh_class);
806 }
807
809}
810
811static int app_control_moh_stop(struct stasis_app_control *control,
812 struct ast_channel *chan, void *data)
813{
814 ast_moh_stop(chan);
815 return 0;
816}
817
819{
821}
822
824 struct ast_channel *chan, void *data)
825{
826 if (ast_channel_state(chan) != AST_STATE_UP) {
828 }
829
830 if (control->silgen) {
831 /* We have a silence generator, but it may have been implicitly
832 * disabled by media actions (music on hold, playing media,
833 * etc.) Just stop it and restart a new one.
834 */
836 control->channel, control->silgen);
837 }
838
839 ast_debug(3, "%s: Starting silence generator\n",
842
843 if (!control->silgen) {
845 "%s: Failed to start silence generator.\n",
847 }
848
849 return 0;
850}
851
853{
855}
856
858{
859 if (control->silgen) {
860 ast_debug(3, "%s: Stopping silence generator\n",
863 control->channel, control->silgen);
864 control->silgen = NULL;
865 }
866}
867
869 struct ast_channel *chan, void *data)
870{
872 return 0;
873}
874
876{
878}
879
881 const struct stasis_app_control *control)
882{
884}
885
887 stasis_app_command_cb command_fn, void *data,
888 command_data_destructor_fn data_destructor,
889 app_command_can_exec_cb can_exec_fn)
890{
891 int ret;
892 struct stasis_app_command *command;
893
894 if (control == NULL || control->is_done) {
895 /* If exec_command_on_condition fails, it calls the data_destructor.
896 * In order to provide consistent behavior, we'll also call the data_destructor
897 * on this error path. This way, callers never have to call the
898 * data_destructor themselves.
899 */
900 if (data_destructor) {
902 }
903 return -1;
904 }
905
907 control, command_fn, data, data_destructor, can_exec_fn);
908 if (!command) {
909 return -1;
910 }
911
912 ret = command_join(command);
913 ao2_ref(command, -1);
914
915 return ret;
916}
917
920{
921 return app_send_command_on_condition(control, command_fn, data, data_destructor, NULL);
922}
923
925 stasis_app_command_cb command_fn, void *data,
927{
928 struct stasis_app_command *command;
929
930 if (control == NULL || control->is_done) {
931 /* If exec_command fails, it calls the data_destructor. In order to
932 * provide consistent behavior, we'll also call the data_destructor
933 * on this error path. This way, callers never have to call the
934 * data_destructor themselves.
935 */
936 if (data_destructor) {
938 }
939 return -1;
940 }
941
942 command = exec_command(control, command_fn, data, data_destructor);
943 if (!command) {
944 return -1;
945 }
946 ao2_ref(command, -1);
947
948 return 0;
949}
950
952{
953 struct ast_bridge *ret;
954
955 if (!control) {
956 return NULL;
957 }
958
959 ao2_lock(control);
960 ret = control->bridge;
961 ao2_unlock(control);
962
963 return ret;
964}
965
966/*!
967 * \brief Singleton dial bridge
968 *
969 * The dial bridge is a holding bridge used to hold all
970 * outbound dialed channels that are not in any "real" ARI-created
971 * bridge. The dial bridge is invisible, meaning that it does not
972 * show up in channel snapshots, AMI or ARI output, and no events
973 * get raised for it.
974 *
975 * This is used to keep dialed channels confined to the bridging system
976 * and unify the threading model used for dialing outbound channels.
977 */
978static struct ast_bridge *dial_bridge;
980
981/*!
982 * \brief Retrieve a reference to the dial bridge.
983 *
984 * If the dial bridge has not been created yet, it will
985 * be created, otherwise, a reference to the existing bridge
986 * will be returned.
987 *
988 * The caller will need to unreference the dial bridge once
989 * they are finished with it.
990 *
991 * \retval NULL Unable to find/create the dial bridge
992 * \retval non-NULL A reference to the dial bridge
993 */
994static struct ast_bridge *get_dial_bridge(void)
995{
996 struct ast_bridge *ret_bridge = NULL;
997
999
1000 if (shutting_down) {
1001 goto end;
1002 }
1003
1004 if (dial_bridge) {
1005 ret_bridge = ao2_bump(dial_bridge);
1006 goto end;
1007 }
1008
1009 dial_bridge = stasis_app_bridge_create_invisible("holding", "dial_bridge", NULL);
1010 if (!dial_bridge) {
1011 goto end;
1012 }
1013 ret_bridge = ao2_bump(dial_bridge);
1014
1015end:
1017 return ret_bridge;
1018}
1019
1020static int bridge_channel_depart(struct stasis_app_control *control,
1021 struct ast_channel *chan, void *data);
1022
1023/*!
1024 * \brief after bridge callback for the dial bridge
1025 *
1026 * The only purpose of this callback is to ensure that the control structure's
1027 * bridge pointer is NULLed
1028 */
1029static void dial_bridge_after_cb(struct ast_channel *chan, void *data)
1030{
1031 struct stasis_app_control *control = data;
1032 struct ast_bridge_channel *bridge_channel;
1033
1035 bridge_channel = ast_channel_get_bridge_channel(chan);
1037
1038 ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), ast_channel_hangupcause(chan));
1039
1041
1042 control->bridge = NULL;
1043}
1044
1046{
1047 struct stasis_app_control *control = data;
1048
1049 ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), reason);
1050 dial_bridge_after_cb(control->channel, data);
1051}
1052
1053/*!
1054 * \brief Add a channel to the singleton dial bridge.
1055 *
1056 * \param control The Stasis control structure
1057 * \param chan The channel to add to the bridge
1058 * \retval -1 Failed
1059 * \retval 0 Success
1060 */
1061static int add_to_dial_bridge(struct stasis_app_control *control, struct ast_channel *chan)
1062{
1063 struct ast_bridge *bridge;
1064
1065 bridge = get_dial_bridge();
1066 if (!bridge) {
1067 return -1;
1068 }
1069
1070 control->bridge = bridge;
1073 control->bridge = NULL;
1074 ao2_ref(bridge, -1);
1075 return -1;
1076 }
1077
1078 ao2_ref(bridge, -1);
1079
1080 return 0;
1081}
1082
1083/*!
1084 * \brief Depart a channel from a bridge, and potentially add it back to the dial bridge
1085 *
1086 * \param control Take a guess
1087 * \param chan Take another guess
1088 */
1089static int depart_channel(struct stasis_app_control *control, struct ast_channel *chan)
1090{
1091 ast_bridge_depart(chan);
1092
1093 /* Channels which have a PBX are not ones that have been created and dialed from ARI. They
1094 * have externally come in from the dialplan, and thus should not be placed into the dial
1095 * bridge. Only channels which are created and dialed in ARI should go into the dial bridge.
1096 */
1097 if (!ast_check_hangup(chan) && ast_channel_state(chan) != AST_STATE_UP && !ast_channel_pbx(chan)) {
1098 /* Channel is still being dialed, so put it back in the dialing bridge */
1099 add_to_dial_bridge(control, chan);
1100 }
1101
1102 return 0;
1103}
1104
1106 struct ast_channel *chan, void *data)
1107{
1108 struct ast_bridge_channel *bridge_channel;
1109
1111 bridge_channel = ast_channel_internal_bridge_channel(chan);
1113
1114 if (bridge_channel != data) {
1115 ast_debug(3, "%s: Channel is no longer in departable state\n",
1117 return -1;
1118 }
1119
1120 ast_debug(3, "%s: Channel departing bridge\n",
1122
1123 depart_channel(control, chan);
1124
1125 return 0;
1126}
1127
1128static void internal_bridge_after_cb(struct ast_channel *chan, void *data,
1129 enum ast_bridge_after_cb_reason reason)
1130{
1131 struct stasis_app_control *control = data;
1132 struct ast_bridge_channel *bridge_channel;
1133
1134 ao2_lock(control);
1135 ast_debug(3, "%s, %s: %s\n",
1136 ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown",
1138
1140 /* The impart actually failed so control->bridge isn't valid. */
1141 control->bridge = NULL;
1142 }
1143
1144 ast_assert(chan == control->channel);
1145
1146 /* Restore the channel's PBX */
1147 ast_channel_pbx_set(control->channel, control->pbx);
1148 control->pbx = NULL;
1149
1150 if (control->bridge) {
1151 app_unsubscribe_bridge(control->app, control->bridge);
1152
1153 /* No longer in the bridge */
1154 control->bridge = NULL;
1155
1156 /* Get the bridge channel so we don't depart from the wrong bridge */
1158 bridge_channel = ast_channel_get_bridge_channel(chan);
1160
1161 /* Depart this channel from the bridge using the command queue if possible */
1163 }
1164
1166 /* The channel has had a StasisEnd published on it, but until now had remained in
1167 * the bridging system. This means that the channel moved from a Stasis bridge to a
1168 * non-Stasis bridge and is now exiting the bridging system. Because of this, the
1169 * channel needs to exit the Stasis application and go to wherever the non-Stasis
1170 * bridge has directed it to go. If the non-Stasis bridge has not set up an after
1171 * bridge destination, then the channel should be hung up.
1172 */
1173 int hangup_flag;
1174
1177 ast_softhangup_nolock(chan, hangup_flag);
1179 }
1180 ao2_unlock(control);
1181}
1182
1183static void bridge_after_cb(struct ast_channel *chan, void *data)
1184{
1185 struct stasis_app_control *control = data;
1186
1188}
1189
1191 void *data)
1192{
1193 struct stasis_app_control *control = data;
1194
1195 internal_bridge_after_cb(control->channel, data, reason);
1196
1197 ast_debug(3, " reason: %s\n",
1199}
1200
1201/*!
1202 * \brief Dial timeout datastore
1203 *
1204 * A datastore is used because a channel may change
1205 * bridges during the course of a dial attempt. This
1206 * may be because the channel changes from the dial bridge
1207 * to a standard bridge, or it may move between standard
1208 * bridges. In order to keep the dial timeout, we need
1209 * to keep the timeout information local to the channel.
1210 * That is what this datastore is for
1211 */
1213 .type = "ARI dial timeout",
1214};
1215
1216static int hangup_channel(struct stasis_app_control *control,
1217 struct ast_channel *chan, void *data)
1218{
1220 return 0;
1221}
1222
1223/*!
1224 * \brief Dial timeout
1225 *
1226 * This is a bridge interval hook callback. The interval hook triggering
1227 * means that the dial timeout has been reached. If the channel has not
1228 * been answered by the time this callback is called, then the channel
1229 * is hung up
1230 *
1231 * \param bridge_channel Bridge channel on which interval hook has been called
1232 * \param ignore Ignored
1233 * \return -1 (i.e. remove the interval hook)
1234 */
1235static int bridge_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
1236{
1237 struct ast_datastore *datastore;
1238 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1239
1240 control = stasis_app_control_find_by_channel(bridge_channel->chan);
1241
1242 ast_channel_lock(bridge_channel->chan);
1243 if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) {
1244 /* Don't bother removing the datastore because it will happen when the channel is hung up */
1245 ast_channel_unlock(bridge_channel->chan);
1247 return -1;
1248 }
1249
1250 datastore = ast_channel_datastore_find(bridge_channel->chan, &timeout_datastore, NULL);
1251 if (!datastore) {
1252 ast_channel_unlock(bridge_channel->chan);
1253 return -1;
1254 }
1255 ast_channel_datastore_remove(bridge_channel->chan, datastore);
1256 ast_channel_unlock(bridge_channel->chan);
1257 ast_datastore_free(datastore);
1258
1259 return -1;
1260}
1261
1262/*!
1263 * \brief Set a dial timeout interval hook on the channel.
1264 *
1265 * The absolute time that the timeout should occur is stored on
1266 * a datastore on the channel. This time is converted into a relative
1267 * number of milliseconds in the future. Then an interval hook is set
1268 * to trigger in that number of milliseconds.
1269 *
1270 * \pre chan is locked
1271 *
1272 * \param chan The channel on which to set the interval hook
1273 */
1274static void set_interval_hook(struct ast_channel *chan)
1275{
1276 struct ast_datastore *datastore;
1277 struct timeval *hangup_time;
1278 int64_t ms;
1279 struct ast_bridge_channel *bridge_channel;
1280
1282 if (!datastore) {
1283 return;
1284 }
1285
1286 hangup_time = datastore->data;
1287
1288 ms = ast_tvdiff_ms(*hangup_time, ast_tvnow());
1289 bridge_channel = ast_channel_get_bridge_channel(chan);
1290 if (!bridge_channel) {
1291 return;
1292 }
1293
1294 if (ast_bridge_interval_hook(bridge_channel->features, 0, ms > 0 ? ms : 1,
1295 bridge_timeout, NULL, NULL, 0)) {
1296 ao2_ref(bridge_channel, -1);
1297 return;
1298 }
1299
1300 ast_queue_frame(bridge_channel->chan, &ast_null_frame);
1301 ao2_ref(bridge_channel, -1);
1302}
1303
1305{
1306 int res;
1307 struct ast_bridge_features *features;
1309
1310 if (!control || !bridge) {
1311 return -1;
1312 }
1313
1314 ast_debug(3, "%s: Adding to bridge %s\n",
1316 bridge->uniqueid);
1317
1318 ast_assert(chan != NULL);
1319
1320 /* Depart whatever Stasis bridge we're currently in. */
1321 if (stasis_app_get_bridge(control)) {
1322 /* Note that it looks like there's a race condition here, since
1323 * we don't have control locked. But this happens from the
1324 * control callback thread, so there won't be any other
1325 * concurrent attempts to bridge.
1326 */
1327 ast_bridge_depart(chan);
1328 }
1329
1330
1332 bridge_after_cb_failed, control);
1333 if (res != 0) {
1334 ast_log(LOG_ERROR, "Error setting after-bridge callback\n");
1335 return -1;
1336 }
1337
1338 ao2_lock(control);
1339
1340 /* Ensure the controlling application is subscribed early enough
1341 * to receive the ChannelEnteredBridge message. This works in concert
1342 * with the subscription handled in the Stasis application execution
1343 * loop */
1344 app_subscribe_bridge(control->app, bridge);
1345
1346 /* Save off the channel's PBX */
1347 ast_assert(control->pbx == NULL);
1348 if (!control->pbx) {
1349 control->pbx = ast_channel_pbx(chan);
1351 }
1352
1353 /* Pull bridge features from the control */
1354 features = control->bridge_features;
1355 control->bridge_features = NULL;
1356 if (features && features->inhibit_colp) {
1358 }
1359
1361 /* We need to set control->bridge here since bridge_after_cb may be run
1362 * before ast_bridge_impart returns. bridge_after_cb gets a reason
1363 * code so it can tell if the bridge is actually valid or not.
1364 */
1365 control->bridge = bridge;
1366
1367 /* We can't be holding the control lock while impart is running
1368 * or we could create a deadlock with bridge_after_cb which also
1369 * tries to lock control.
1370 */
1371 ao2_unlock(control);
1372 res = ast_bridge_impart(bridge,
1373 chan,
1374 swap,
1375 features, /* features */
1376 flags);
1377 if (res != 0) {
1378 /* ast_bridge_impart failed before it could spawn the depart
1379 * thread. The callbacks aren't called in this case.
1380 * The impart could still fail even if ast_bridge_impart returned
1381 * ok but that's handled by bridge_after_cb.
1382 */
1383 ast_log(LOG_ERROR, "Error adding channel to bridge\n");
1384 ao2_lock(control);
1385 ast_channel_pbx_set(chan, control->pbx);
1386 control->pbx = NULL;
1387 control->bridge = NULL;
1388 ao2_unlock(control);
1389 } else {
1390 ast_channel_lock(chan);
1391 set_interval_hook(chan);
1392 ast_channel_unlock(chan);
1393 }
1394
1395 return res;
1396}
1397
1398int control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
1399{
1400 return control_swap_channel_in_bridge(control, data, chan, NULL);
1401}
1402
1404 struct stasis_app_control *control, struct ast_bridge *bridge)
1405{
1406 ast_debug(3, "%s: Sending channel add_to_bridge command\n",
1408
1410 control, control_add_channel_to_bridge, bridge, NULL,
1412}
1413
1415 struct stasis_app_control *control,
1416 struct ast_channel *chan, void *data)
1417{
1418 struct ast_bridge *bridge = data;
1419
1420 if (!control) {
1421 return -1;
1422 }
1423
1424 /* We should only depart from our own bridge */
1425 ast_debug(3, "%s: Departing bridge %s\n",
1427 bridge->uniqueid);
1428
1429 if (bridge != stasis_app_get_bridge(control)) {
1430 ast_log(LOG_WARNING, "%s: Not in bridge %s; not removing\n",
1432 bridge->uniqueid);
1433 return -1;
1434 }
1435
1436 depart_channel(control, chan);
1437 return 0;
1438}
1439
1441 struct stasis_app_control *control, struct ast_bridge *bridge)
1442{
1443 ast_debug(3, "%s: Sending channel remove_from_bridge command\n",
1448}
1449
1451 const struct stasis_app_control *control)
1452{
1453 return ast_channel_uniqueid(control->channel);
1454}
1455
1457 struct stasis_app_control *control, struct stasis_message *message)
1458{
1459 if (!control || !control->channel || !message) {
1460 return;
1461 }
1463}
1464
1467{
1468 return ast_queue_control(control->channel, frame_type);
1469}
1470
1472 struct stasis_app_control *control)
1473{
1474 struct ast_bridge_features *features;
1475
1476 features = ast_bridge_features_new();
1477 if (!features) {
1478 return 1;
1479 }
1480 control->bridge_features = features;
1481 return 0;
1482}
1483
1485 struct stasis_app_control *control, int absorb)
1486{
1487 control->bridge_features->dtmf_passthrough = !absorb;
1488}
1489
1491 struct stasis_app_control *control, int mute)
1492{
1493 control->bridge_features->mute = mute;
1494}
1495
1497 struct stasis_app_control *control, int inhibit_colp)
1498{
1500}
1501
1503{
1504 struct ao2_iterator iter;
1505 struct stasis_app_command *command;
1506
1508 while ((command = ao2_iterator_next(&iter))) {
1509 command_complete(command, -1);
1510 ao2_ref(command, -1);
1511 }
1512 ao2_iterator_destroy(&iter);
1513}
1514
1516 struct ast_channel *chan)
1517{
1518 int count = 0;
1519 struct ao2_iterator iter;
1520 struct stasis_app_command *command;
1521
1522 ast_assert(control->channel == chan);
1523
1525 while ((command = ao2_iterator_next(&iter))) {
1526 command_invoke(command, control, chan);
1527 ao2_ref(command, -1);
1528 ++count;
1529 }
1530 ao2_iterator_destroy(&iter);
1531
1532 return count;
1533}
1534
1536{
1537 if (!control) {
1538 return;
1539 }
1540
1541 ast_assert(control->command_queue != NULL);
1542
1543 ao2_lock(control->command_queue);
1544 while (ao2_container_count(control->command_queue) == 0) {
1545 int res = ast_cond_wait(&control->wait_cond,
1547 if (res < 0) {
1548 ast_log(LOG_ERROR, "Error waiting on command queue\n");
1549 break;
1550 }
1551 }
1552 ao2_unlock(control->command_queue);
1553}
1554
1556 struct ast_channel *chan)
1557{
1558 struct ao2_container *command_queue;
1559 int count = 0;
1560 struct ao2_iterator iter;
1561 struct stasis_app_command *command;
1562
1563 ast_channel_lock(chan);
1564 command_queue = command_prestart_get_container(chan);
1565 ast_channel_unlock(chan);
1566 if (!command_queue) {
1567 return 0;
1568 }
1569
1570 iter = ao2_iterator_init(command_queue, AO2_ITERATOR_UNLINK);
1571
1572 while ((command = ao2_iterator_next(&iter))) {
1573 command_invoke(command, control, chan);
1574 ao2_cleanup(command);
1575 ++count;
1576 }
1577
1578 ao2_iterator_destroy(&iter);
1579 ao2_cleanup(command_queue);
1580 return count;
1581}
1582
1584{
1585 return control->app;
1586}
1587
1589 unsigned int timeout;
1590 char dialstring[0];
1591};
1592
1594 unsigned int timeout)
1595{
1596 struct control_dial_args *args;
1597
1598 args = ast_malloc(sizeof(*args) + strlen(dialstring) + 1);
1599 if (!args) {
1600 return NULL;
1601 }
1602
1603 args->timeout = timeout;
1604 /* Safe */
1605 strcpy(args->dialstring, dialstring);
1606
1607 return args;
1608}
1609
1610static void control_dial_args_destroy(void *data)
1611{
1612 struct control_dial_args *args = data;
1613
1614 ast_free(args);
1615}
1616
1617/*!
1618 * \brief Set dial timeout on a channel to be dialed.
1619 *
1620 * \param chan The channel on which to set the dial timeout
1621 * \param timeout The timeout in seconds
1622 */
1623static int set_timeout(struct ast_channel *chan, unsigned int timeout)
1624{
1625 struct ast_datastore *datastore;
1626 struct timeval *hangup_time;
1627
1628 hangup_time = ast_malloc(sizeof(struct timeval));
1629
1631 if (!datastore) {
1632 return -1;
1633 }
1634 *hangup_time = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1));
1635 datastore->data = hangup_time;
1636
1637 ast_channel_lock(chan);
1638 ast_channel_datastore_add(chan, datastore);
1639
1640 if (ast_channel_is_bridged(chan)) {
1641 set_interval_hook(chan);
1642 }
1643 ast_channel_unlock(chan);
1644
1645 return 0;
1646}
1647
1648static int app_control_dial(struct stasis_app_control *control,
1649 struct ast_channel *chan, void *data)
1650{
1651 struct control_dial_args *args = data;
1652 int bridged;
1653
1654 ast_channel_lock(chan);
1655 bridged = ast_channel_is_bridged(chan);
1656 ast_channel_unlock(chan);
1657
1658 if (!bridged && add_to_dial_bridge(control, chan)) {
1659 return -1;
1660 }
1661
1662 if (args->timeout && set_timeout(chan, args->timeout)) {
1663 return -1;
1664 }
1665
1666 if (ast_call(chan, args->dialstring, 0)) {
1667 /* If call fails normally this channel would then just be normally hung up and destroyed.
1668 * In this case though the channel is being handled by the ARI control thread and dial
1669 * bridge which needs to be notified that the channel should be hung up. To do this we
1670 * queue a soft hangup which will cause each to wake up, see that the channel has been
1671 * hung up, and then destroy it.
1672 */
1673 int hangup_flag;
1675 ast_channel_lock(chan);
1676 ast_softhangup_nolock(chan, hangup_flag);
1677 ast_channel_unlock(chan);
1678 return -1;
1679 }
1680
1681 ast_channel_publish_dial(NULL, chan, args->dialstring, NULL);
1682
1683 return 0;
1684}
1685
1687 const char *dialstring, unsigned int timeout)
1688{
1689 struct control_dial_args *args;
1690
1692 if (!args) {
1693 return -1;
1694 }
1695
1698}
1699
1701{
1703 shutting_down = 1;
1704 if (dial_bridge) {
1706 dial_bridge = NULL;
1707 }
1709}
1710
1711void control_set_app(struct stasis_app_control *control, struct stasis_app *app)
1712{
1713 ao2_cleanup(control->app);
1714 control->app = ao2_bump(app);
1715}
1716
1718{
1719 return control->next_app;
1720}
1721
1723{
1724 ast_free(control->next_app);
1725 control->next_app = NULL;
1726
1728}
1729
1731{
1732 return AST_VECTOR_STEAL_ELEMENTS(&control->next_app_args);
1733}
1734
1736{
1737 return AST_VECTOR_SIZE(&control->next_app_args);
1738}
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:1906
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944
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:1878
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
Definition: bridge.h:588
@ AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP
Definition: bridge.h:592
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:3319
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3683
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3674
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
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:6461
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
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:2922
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8164
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
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:8210
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
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:1139
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:10777
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:10545
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1126
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
#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:10582
int ast_transfer(struct ast_channel *chan, char *dest)
Transfer a channel (if supported).
Definition: channel.c:6485
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:10839
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#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:2399
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:1490
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:177
void control_set_thread(struct stasis_app_control *control, pthread_t threadid)
set the control's thread id
Definition: control.c:194
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:244
static void set_interval_hook(struct ast_channel *chan)
Set a dial timeout interval hook on the channel.
Definition: control.c:1274
static int app_control_ring(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:604
struct stasis_app_control * control_create(struct ast_channel *channel, struct stasis_app *app)
Create a control object.
Definition: control.c:127
static void dtmf_no_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
Definition: control.c:554
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:800
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:1450
static int app_control_continue(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:388
static int set_timeout(struct ast_channel *chan, unsigned int timeout)
Set dial timeout on a channel to be dialed.
Definition: control.c:1623
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:1061
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:1465
static int app_control_set_channel_var(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:721
int control_prestart_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all queued prestart commands.
Definition: control.c:1555
static int app_control_clear_roles(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:350
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:251
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:1304
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:679
void stasis_app_control_unhold(struct stasis_app_control *control)
Remove the channel associated with the control from hold.
Definition: control.c:781
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:280
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:1403
void control_wait(struct stasis_app_control *control)
Blocks until control's command queue has a command available.
Definition: control.c:1535
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:1730
static void bridge_after_cb(struct ast_channel *chan, void *data)
Definition: control.c:1183
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:918
void stasis_app_control_silence_start(struct stasis_app_control *control)
Start playing silence to a channel.
Definition: control.c:852
void stasis_app_control_silence_stop(struct stasis_app_control *control)
Stop playing silence to a channel.
Definition: control.c:875
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:1398
static void dial_bridge_after_cb(struct ast_channel *chan, void *data)
after bridge callback for the dial bridge
Definition: control.c:1029
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:358
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:409
static int app_control_ring_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:619
static int app_control_hold(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:760
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:216
static int app_control_unhold(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:773
int control_is_done(struct stasis_app_control *control)
Returns true if control_continue() has been called on this control.
Definition: control.c:368
static void free_chanvar(void *data)
Definition: control.c:712
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:1456
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:520
static int app_control_remove_channel_from_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1414
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:818
static struct control_dial_args * control_dial_args_alloc(const char *dialstring, unsigned int timeout)
Definition: control.c:1593
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:471
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:651
static struct ast_bridge * dial_bridge
Singleton dial bridge.
Definition: control.c:978
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:1484
struct ast_datastore_info timeout_datastore
Dial timeout datastore.
Definition: control.c:1212
static int app_control_moh_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:811
static void bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition: control.c:1190
int(* app_command_can_exec_cb)(struct stasis_app_control *control)
Definition: control.c:278
static int noop_cb(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:270
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:585
static int shutting_down
Indicates if the Stasis app internals are being shut down.
Definition: control.c:49
void control_flush_queue(struct stasis_app_control *control)
Flush the control command queue.
Definition: control.c:1502
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:336
static int app_control_add_role(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:328
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:1496
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:886
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:1440
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition: control.c:951
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:924
int stasis_app_control_bridge_features_init(struct stasis_app_control *control)
Initialize bridge features into a channel control.
Definition: control.c:1471
static int app_control_move(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:434
static int hangup_channel(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1216
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:1089
void stasis_app_control_hold(struct stasis_app_control *control)
Place the channel associated with the control on hold.
Definition: control.c:768
int control_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all commands enqueued to this control.
Definition: control.c:1515
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:1735
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:237
void control_set_app(struct stasis_app_control *control, struct stasis_app *app)
Set the application the control object belongs to.
Definition: control.c:1711
static void dtmf_in_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
Definition: control.c:541
static int app_control_unmute(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:667
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:168
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:627
static int app_control_redirect(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:501
int stasis_app_control_dial(struct stasis_app_control *control, const char *dialstring, unsigned int timeout)
Dial a channel.
Definition: control.c:1686
static int bridge_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
Dial timeout.
Definition: control.c:1235
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:880
int control_command_count(struct stasis_app_control *control)
Returns the count of items in a control's command queue.
Definition: control.c:363
static int app_control_can_remove_channel_from_bridge(struct stasis_app_control *control)
Definition: control.c:264
static void control_dial_args_destroy(void *data)
Definition: control.c:1610
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:230
void control_silence_stop_now(struct stasis_app_control *control)
Stop playing silence to a channel right now.
Definition: control.c:857
static int app_control_silence_start(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:823
static int app_control_can_add_channel_to_bridge(struct stasis_app_control *control)
Definition: control.c:258
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:321
static int app_control_dial(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1648
static int app_control_moh_start(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:786
static ast_mutex_t dial_bridge_lock
Definition: control.c:979
static int bridge_channel_depart(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1105
static struct ast_bridge * get_dial_bridge(void)
Retrieve a reference to the dial bridge.
Definition: control.c:994
char * control_next_app(struct stasis_app_control *control)
Returns the name of the application we are moving to.
Definition: control.c:1717
static void internal_bridge_after_cb(struct ast_channel *chan, void *data, enum ast_bridge_after_cb_reason reason)
Definition: control.c:1128
static int app_control_dtmf(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:567
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:1583
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:731
static int app_control_silence_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:868
static int app_control_mute(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:639
static void dial_bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition: control.c:1045
int stasis_app_control_ring(struct stasis_app_control *control)
Indicate ringing to the channel associated with this control.
Definition: control.c:612
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:1722
void stasis_app_control_shutdown(void)
Let Stasis app internals shut down.
Definition: control.c:1700
static void control_dtor(void *obj)
Definition: control.c:109
void control_mark_done(struct stasis_app_control *control)
Definition: control.c:374
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...
static ENTRY retval
Definition: hsearch.c:50
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:202
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_unlock(a)
Definition: lock.h:190
pthread_cond_t ast_cond_t
Definition: lock.h:178
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
#define ast_cond_signal(cond)
Definition: lock.h:203
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:7766
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776
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:6945
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:1511
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:859
stasis_app_control_channel_result
Result codes used when adding/removing channels to/from bridges.
Definition: stasis_app.h:776
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:1302
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:349
const ast_string_field uniqueid
Definition: bridge.h:401
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:214
structure for queuing ARI channel variable setting
Definition: control.c:705
char * value
Definition: control.c:709
char * name
Definition: control.c:707
char dialstring[0]
Definition: control.c:1590
unsigned int timeout
Definition: control.c:1589
structure to hold extensions
command_data_destructor_fn data_destructor
Definition: command.c:38
char extension[AST_MAX_EXTENSION]
Definition: control.c:384
char context[AST_MAX_CONTEXT]
Definition: control.c:383
enum ast_frame_type frametype
Definition: control.c:635
Rule to check to see if an operation is allowed.
Definition: stasis_app.h:345
struct stasis_app_control_rule * next
Definition: stasis_app.h:355
struct stasis_app * app
Definition: control.c:90
struct ast_bridge_features * bridge_features
Definition: control.c:68
struct ast_channel * channel
Definition: control.c:60
struct ast_bridge * bridge
Definition: control.c:64
struct ao2_container * command_queue
Definition: control.c:54
unsigned int is_done
Definition: control.c:106
struct stasis_app_control::@489 next_app_args
struct app_control_rules remove_rules
Definition: control.c:80
struct ast_silence_generator * silgen
Definition: control.c:84
char * next_app
Definition: control.c:94
struct app_control_rules add_rules
Definition: control.c:76
ast_cond_t wait_cond
Definition: control.c:52
pthread_t control_thread
Definition: control.c:98
struct ast_pbx * pbx
Definition: control.c:72
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:941
#define ast_assert(a)
Definition: utils.h:739
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition: vector.h:140
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44