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