ari: Fix deadlock problem with functions that use autoservice.
[asterisk/asterisk.git] / res / stasis / control.c
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
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include "asterisk/stasis_channels.h"
31
32 #include "command.h"
33 #include "control.h"
34 #include "asterisk/dial.h"
35 #include "asterisk/bridge.h"
36 #include "asterisk/bridge_after.h"
37 #include "asterisk/bridge_basic.h"
38 #include "asterisk/frame.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/musiconhold.h"
41 #include "asterisk/app.h"
42
43 struct stasis_app_control {
44         ast_cond_t wait_cond;
45         /*! Queue of commands to dispatch on the channel */
46         struct ao2_container *command_queue;
47         /*!
48          * The associated channel.
49          * Be very careful with the threading associated w/ manipulating
50          * the channel.
51          */
52         struct ast_channel *channel;
53         /*!
54          * When a channel is in a bridge, the bridge that it is in.
55          */
56         struct ast_bridge *bridge;
57         /*!
58          * Holding place for channel's PBX while imparted to a bridge.
59          */
60         struct ast_pbx *pbx;
61         /*!
62          * Silence generator, when silence is being generated.
63          */
64         struct ast_silence_generator *silgen;
65         /*!
66          * When set, /c app_stasis should exit and continue in the dialplan.
67          */
68         int is_done:1;
69 };
70
71 static void control_dtor(void *obj)
72 {
73         struct stasis_app_control *control = obj;
74
75         /* We may have a lingering silence generator; free it */
76         ast_channel_stop_silence_generator(control->channel, control->silgen);
77         control->silgen = NULL;
78
79         ao2_cleanup(control->command_queue);
80         ast_cond_destroy(&control->wait_cond);
81 }
82
83 struct stasis_app_control *control_create(struct ast_channel *channel)
84 {
85         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
86         int res;
87
88         control = ao2_alloc(sizeof(*control), control_dtor);
89         if (!control) {
90                 return NULL;
91         }
92
93         res = ast_cond_init(&control->wait_cond, NULL);
94         if (res != 0) {
95                 ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
96                         strerror(errno));
97                 return NULL;
98         }
99
100         control->command_queue = ao2_container_alloc_list(
101                 AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL);
102
103         if (!control->command_queue) {
104                 return NULL;
105         }
106
107         control->channel = channel;
108
109         ao2_ref(control, +1);
110         return control;
111 }
112
113 static void *noop_cb(struct stasis_app_control *control,
114         struct ast_channel *chan, void *data)
115 {
116         return NULL;
117 }
118
119
120 static struct stasis_app_command *exec_command(
121         struct stasis_app_control *control, stasis_app_command_cb command_fn,
122         void *data)
123 {
124         RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
125
126         command_fn = command_fn ? : noop_cb;
127
128         command = command_create(command_fn, data);
129         if (!command) {
130                 return NULL;
131         }
132
133         ao2_lock(control->command_queue);
134         ao2_link_flags(control->command_queue, command, OBJ_NOLOCK);
135         ast_cond_signal(&control->wait_cond);
136         ao2_unlock(control->command_queue);
137
138         ao2_ref(command, +1);
139         return command;
140 }
141
142 struct stasis_app_control_dial_data {
143         char endpoint[AST_CHANNEL_NAME];
144         int timeout;
145 };
146
147 static void *app_control_add_channel_to_bridge(
148         struct stasis_app_control *control,
149         struct ast_channel *chan, void *data);
150
151 static void *app_control_dial(struct stasis_app_control *control,
152         struct ast_channel *chan, void *data)
153 {
154         RAII_VAR(struct ast_dial *, dial, ast_dial_create(), ast_dial_destroy);
155         RAII_VAR(struct stasis_app_control_dial_data *, dial_data, data, ast_free);
156         enum ast_dial_result res;
157         char *tech, *resource;
158         struct ast_channel *new_chan;
159         RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
160
161         tech = dial_data->endpoint;
162         if (!(resource = strchr(tech, '/'))) {
163                 return NULL;
164         }
165         *resource++ = '\0';
166
167         if (!dial) {
168                 ast_log(LOG_ERROR, "Failed to create dialing structure.\n");
169                 return NULL;
170         }
171
172         if (ast_dial_append(dial, tech, resource) < 0) {
173                 ast_log(LOG_ERROR, "Failed to add %s/%s to dialing structure.\n", tech, resource);
174                 return NULL;
175         }
176
177         ast_dial_set_global_timeout(dial, dial_data->timeout);
178
179         res = ast_dial_run(dial, NULL, 0);
180         if (res != AST_DIAL_RESULT_ANSWERED || !(new_chan = ast_dial_answered_steal(dial))) {
181                 return NULL;
182         }
183
184         if (!(bridge = ast_bridge_basic_new())) {
185                 ast_log(LOG_ERROR, "Failed to create basic bridge.\n");
186                 return NULL;
187         }
188
189         if (ast_bridge_impart(bridge, new_chan, NULL, NULL,
190                 AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
191                 ast_hangup(new_chan);
192         } else {
193                 app_control_add_channel_to_bridge(control, chan, bridge);
194         }
195
196         return NULL;
197 }
198
199 int stasis_app_control_dial(struct stasis_app_control *control, const char *endpoint, const char *exten, const char *context,
200                             int timeout)
201 {
202         struct stasis_app_control_dial_data *dial_data;
203
204         if (!(dial_data = ast_calloc(1, sizeof(*dial_data)))) {
205                 return -1;
206         }
207
208         if (!ast_strlen_zero(endpoint)) {
209                 ast_copy_string(dial_data->endpoint, endpoint, sizeof(dial_data->endpoint));
210         } else if (!ast_strlen_zero(exten) && !ast_strlen_zero(context)) {
211                 snprintf(dial_data->endpoint, sizeof(dial_data->endpoint), "Local/%s@%s", exten, context);
212         } else {
213                 return -1;
214         }
215
216         if (timeout > 0) {
217                 dial_data->timeout = timeout * 1000;
218         } else if (timeout == -1) {
219                 dial_data->timeout = -1;
220         } else {
221                 dial_data->timeout = 30000;
222         }
223
224         stasis_app_send_command_async(control, app_control_dial, dial_data);
225
226         return 0;
227 }
228
229 int stasis_app_control_add_role(struct stasis_app_control *control, const char *role)
230 {
231         return ast_channel_add_bridge_role(control->channel, role);
232 }
233
234 void stasis_app_control_clear_roles(struct stasis_app_control *control)
235 {
236         ast_channel_clear_bridge_roles(control->channel);
237 }
238
239 int control_is_done(struct stasis_app_control *control)
240 {
241         /* Called from stasis_app_exec thread; no lock needed */
242         return control->is_done;
243 }
244
245 struct stasis_app_control_continue_data {
246         char context[AST_MAX_CONTEXT];
247         char extension[AST_MAX_EXTENSION];
248         int priority;
249 };
250
251 static void *app_control_continue(struct stasis_app_control *control,
252         struct ast_channel *chan, void *data)
253 {
254         RAII_VAR(struct stasis_app_control_continue_data *, continue_data, data, ast_free);
255
256         ast_assert(control->channel != NULL);
257
258         /* If we're in a Stasis bridge, depart it before going back to the
259          * dialplan */
260         if (stasis_app_get_bridge(control)) {
261                 ast_bridge_depart(control->channel);
262         }
263
264         /* Called from stasis_app_exec thread; no lock needed */
265         ast_explicit_goto(control->channel, continue_data->context, continue_data->extension, continue_data->priority);
266
267         control->is_done = 1;
268
269         return NULL;
270 }
271
272 int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority)
273 {
274         struct stasis_app_control_continue_data *continue_data;
275
276         if (!(continue_data = ast_calloc(1, sizeof(*continue_data)))) {
277                 return -1;
278         }
279         ast_copy_string(continue_data->context, S_OR(context, ""), sizeof(continue_data->context));
280         ast_copy_string(continue_data->extension, S_OR(extension, ""), sizeof(continue_data->extension));
281         if (priority > 0) {
282                 continue_data->priority = priority;
283         } else {
284                 continue_data->priority = -1;
285         }
286
287         stasis_app_send_command_async(control, app_control_continue, continue_data);
288
289         return 0;
290 }
291
292 struct stasis_app_control_dtmf_data {
293         int before;
294         int between;
295         unsigned int duration;
296         int after;
297         char dtmf[];
298 };
299
300 static void *app_control_dtmf(struct stasis_app_control *control,
301         struct ast_channel *chan, void *data)
302 {
303         RAII_VAR(struct stasis_app_control_dtmf_data *, dtmf_data, data, ast_free);
304
305         if (dtmf_data->before) {
306                 ast_safe_sleep(chan, dtmf_data->before);
307         }
308
309         ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
310
311         if (dtmf_data->after) {
312                 ast_safe_sleep(chan, dtmf_data->after);
313         }
314
315         return NULL;
316 }
317
318 int stasis_app_control_dtmf(struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
319 {
320         struct stasis_app_control_dtmf_data *dtmf_data;
321
322         if (!(dtmf_data = ast_calloc(1, sizeof(*dtmf_data) + strlen(dtmf) + 1))) {
323                 return -1;
324         }
325
326         dtmf_data->before = before;
327         dtmf_data->between = between;
328         dtmf_data->duration = duration;
329         dtmf_data->after = after;
330         strcpy(dtmf_data->dtmf, dtmf);
331
332         stasis_app_send_command_async(control, app_control_dtmf, dtmf_data);
333
334         return 0;
335 }
336
337 static void *app_control_ring(struct stasis_app_control *control,
338         struct ast_channel *chan, void *data)
339 {
340         ast_indicate(control->channel, AST_CONTROL_RINGING);
341
342         return NULL;
343 }
344
345 int stasis_app_control_ring(struct stasis_app_control *control)
346 {
347         stasis_app_send_command_async(control, app_control_ring, NULL);
348
349         return 0;
350 }
351
352 static void *app_control_ring_stop(struct stasis_app_control *control,
353         struct ast_channel *chan, void *data)
354 {
355         ast_indicate(control->channel, -1);
356
357         return NULL;
358 }
359
360 int stasis_app_control_ring_stop(struct stasis_app_control *control)
361 {
362         stasis_app_send_command_async(control, app_control_ring_stop, NULL);
363
364         return 0;
365 }
366
367 struct stasis_app_control_mute_data {
368         enum ast_frame_type frametype;
369         unsigned int direction;
370 };
371
372 static void *app_control_mute(struct stasis_app_control *control,
373         struct ast_channel *chan, void *data)
374 {
375         RAII_VAR(struct stasis_app_control_mute_data *, mute_data, data, ast_free);
376         SCOPED_CHANNELLOCK(lockvar, chan);
377
378         ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);
379
380         return NULL;
381 }
382
383 int stasis_app_control_mute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
384 {
385         struct stasis_app_control_mute_data *mute_data;
386
387         if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
388                 return -1;
389         }
390
391         mute_data->direction = direction;
392         mute_data->frametype = frametype;
393
394         stasis_app_send_command_async(control, app_control_mute, mute_data);
395
396         return 0;
397 }
398
399 static void *app_control_unmute(struct stasis_app_control *control,
400         struct ast_channel *chan, void *data)
401 {
402         RAII_VAR(struct stasis_app_control_mute_data *, mute_data, data, ast_free);
403         SCOPED_CHANNELLOCK(lockvar, chan);
404
405         ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);
406
407         return NULL;
408 }
409
410 int stasis_app_control_unmute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
411 {
412         struct stasis_app_control_mute_data *mute_data;
413
414         if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
415                 return -1;
416         }
417
418         mute_data->direction = direction;
419         mute_data->frametype = frametype;
420
421         stasis_app_send_command_async(control, app_control_unmute, mute_data);
422
423         return 0;
424 }
425
426 char *stasis_app_control_get_channel_var(struct stasis_app_control *control, const char *variable)
427 {
428         RAII_VAR(struct ast_str *, tmp, ast_str_create(32), ast_free);
429
430         /* You may be tempted to lock the channel you're about to read from. You
431          * would be wrong. Some dialplan functions put the channel into
432          * autoservice, which deadlocks if the channel is already locked.
433          * ast_str_retrieve_variable() does its own locking, and the dialplan
434          * functions need to as well. We should be fine without the lock.
435          */
436
437         if (!tmp) {
438                 return NULL;
439         }
440
441         if (variable[strlen(variable) - 1] == ')') {
442                 if (ast_func_read2(control->channel, variable, &tmp, 0)) {
443                         return NULL;
444                 }
445         } else {
446                 if (!ast_str_retrieve_variable(&tmp, 0, control->channel, NULL, variable)) {
447                         return NULL;
448                 }
449         }
450
451         return ast_strdup(ast_str_buffer(tmp));
452 }
453
454 int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
455 {
456         return pbx_builtin_setvar_helper(control->channel, variable, value);
457 }
458
459 static void *app_control_hold(struct stasis_app_control *control,
460         struct ast_channel *chan, void *data)
461 {
462         ast_indicate(control->channel, AST_CONTROL_HOLD);
463
464         return NULL;
465 }
466
467 void stasis_app_control_hold(struct stasis_app_control *control)
468 {
469         stasis_app_send_command_async(control, app_control_hold, NULL);
470 }
471
472 static void *app_control_unhold(struct stasis_app_control *control,
473         struct ast_channel *chan, void *data)
474 {
475         ast_indicate(control->channel, AST_CONTROL_UNHOLD);
476
477         return NULL;
478 }
479
480 void stasis_app_control_unhold(struct stasis_app_control *control)
481 {
482         stasis_app_send_command_async(control, app_control_unhold, NULL);
483 }
484
485 static void *app_control_moh_start(struct stasis_app_control *control,
486         struct ast_channel *chan, void *data)
487 {
488         char *moh_class = data;
489
490         ast_moh_start(chan, moh_class, NULL);
491
492         ast_free(moh_class);
493         return NULL;
494 }
495
496 void stasis_app_control_moh_start(struct stasis_app_control *control, const char *moh_class)
497 {
498         char *data = NULL;
499
500         if (!ast_strlen_zero(moh_class)) {
501                 data = ast_strdup(moh_class);
502         }
503
504         stasis_app_send_command_async(control, app_control_moh_start, data);
505 }
506
507 static void *app_control_moh_stop(struct stasis_app_control *control,
508         struct ast_channel *chan, void *data)
509 {
510         ast_moh_stop(chan);
511         return NULL;
512 }
513
514 void stasis_app_control_moh_stop(struct stasis_app_control *control)
515 {
516         stasis_app_send_command_async(control, app_control_moh_stop, NULL);
517 }
518
519 static void *app_control_silence_start(struct stasis_app_control *control,
520         struct ast_channel *chan, void *data)
521 {
522         if (control->silgen) {
523                 /* We have a silence generator, but it may have been implicitly
524                  * disabled by media actions (music on hold, playing media,
525                  * etc.) Just stop it and restart a new one.
526                  */
527                 ast_channel_stop_silence_generator(
528                         control->channel, control->silgen);
529         }
530
531         ast_debug(3, "%s: Starting silence generator\n",
532                 stasis_app_control_get_channel_id(control));
533         control->silgen = ast_channel_start_silence_generator(control->channel);
534
535         if (!control->silgen) {
536                 ast_log(LOG_WARNING,
537                         "%s: Failed to start silence generator.\n",
538                         stasis_app_control_get_channel_id(control));
539         }
540
541         return NULL;
542 }
543
544 void stasis_app_control_silence_start(struct stasis_app_control *control)
545 {
546         stasis_app_send_command_async(control, app_control_silence_start, NULL);
547 }
548
549 static void *app_control_silence_stop(struct stasis_app_control *control,
550         struct ast_channel *chan, void *data)
551 {
552         if (control->silgen) {
553                 ast_debug(3, "%s: Stopping silence generator\n",
554                         stasis_app_control_get_channel_id(control));
555                 ast_channel_stop_silence_generator(
556                         control->channel, control->silgen);
557                 control->silgen = NULL;
558         }
559
560         return NULL;
561 }
562
563 void stasis_app_control_silence_stop(struct stasis_app_control *control)
564 {
565         stasis_app_send_command_async(control, app_control_silence_stop, NULL);
566 }
567
568 struct ast_channel_snapshot *stasis_app_control_get_snapshot(
569         const struct stasis_app_control *control)
570 {
571         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
572         struct ast_channel_snapshot *snapshot;
573
574         msg = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(),
575                 stasis_app_control_get_channel_id(control));
576         if (!msg) {
577                 return NULL;
578         }
579
580         snapshot = stasis_message_data(msg);
581         ast_assert(snapshot != NULL);
582
583         ao2_ref(snapshot, +1);
584         return snapshot;
585 }
586
587 void *stasis_app_send_command(struct stasis_app_control *control,
588         stasis_app_command_cb command_fn, void *data)
589 {
590         RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
591
592         if (control == NULL) {
593                 return NULL;
594         }
595
596         command = exec_command(control, command_fn, data);
597         if (!command) {
598                 return NULL;
599         }
600
601         return command_join(command);
602 }
603
604 int stasis_app_send_command_async(struct stasis_app_control *control,
605         stasis_app_command_cb command_fn, void *data)
606 {
607         RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
608
609         if (control == NULL) {
610                 return -1;
611         }
612
613         command = exec_command(control, command_fn, data);
614         if (!command) {
615                 return -1;
616         }
617
618         return 0;
619 }
620
621 struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control)
622 {
623         if (!control) {
624                 return NULL;
625         } else {
626                 SCOPED_AO2LOCK(lock, control);
627                 return control->bridge;
628         }
629 }
630
631 static void *bridge_channel_depart(struct stasis_app_control *control,
632         struct ast_channel *chan, void *data)
633 {
634         RAII_VAR(struct ast_bridge_channel *, bridge_channel, data, ao2_cleanup);
635
636         {
637                 SCOPED_CHANNELLOCK(lock, chan);
638
639                 if (bridge_channel != ast_channel_internal_bridge_channel(chan)) {
640                         ast_debug(3, "%s: Channel is no longer in departable state\n",
641                                 ast_channel_uniqueid(chan));
642                         return NULL;
643                 }
644         }
645
646         ast_debug(3, "%s: Channel departing bridge\n",
647                 ast_channel_uniqueid(chan));
648
649         ast_bridge_depart(chan);
650
651         return NULL;
652 }
653
654 static void bridge_after_cb(struct ast_channel *chan, void *data)
655 {
656         struct stasis_app_control *control = data;
657         SCOPED_AO2LOCK(lock, control);
658         struct ast_bridge_channel *bridge_channel;
659
660         ast_debug(3, "%s, %s: Channel leaving bridge\n",
661                 ast_channel_uniqueid(chan), control->bridge->uniqueid);
662
663         ast_assert(chan == control->channel);
664
665         /* Restore the channel's PBX */
666         ast_channel_pbx_set(control->channel, control->pbx);
667         control->pbx = NULL;
668
669         /* No longer in the bridge */
670         control->bridge = NULL;
671
672         /* Get the bridge channel so we don't depart from the wrong bridge */
673         ast_channel_lock(chan);
674         bridge_channel = ast_channel_get_bridge_channel(chan);
675         ast_channel_unlock(chan);
676
677         /* Depart this channel from the bridge using the command queue if possible */
678         if (stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel)) {
679                 ao2_cleanup(bridge_channel);
680         }
681 }
682
683 static void bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason,
684         void *data)
685 {
686         struct stasis_app_control *control = data;
687
688         bridge_after_cb(control->channel, data);
689
690         ast_debug(3, "  reason: %s\n",
691                 ast_bridge_after_cb_reason_string(reason));
692 }
693
694 static int OK = 0;
695 static int FAIL = -1;
696
697 static void *app_control_add_channel_to_bridge(
698         struct stasis_app_control *control,
699         struct ast_channel *chan, void *data)
700 {
701         struct ast_bridge *bridge = data;
702         int res;
703
704         if (!control || !bridge) {
705                 return NULL;
706         }
707
708         ast_debug(3, "%s: Adding to bridge %s\n",
709                 stasis_app_control_get_channel_id(control),
710                 bridge->uniqueid);
711
712         ast_assert(chan != NULL);
713
714         /* Depart whatever Stasis bridge we're currently in. */
715         if (stasis_app_get_bridge(control)) {
716                 /* Note that it looks like there's a race condition here, since
717                  * we don't have control locked. But this happens from the
718                  * control callback thread, so there won't be any other
719                  * concurrent attempts to bridge.
720                  */
721                 ast_bridge_depart(chan);
722         }
723
724
725         res = ast_bridge_set_after_callback(chan, bridge_after_cb,
726                 bridge_after_cb_failed, control);
727         if (res != 0) {
728                 ast_log(LOG_ERROR, "Error setting after-bridge callback\n");
729                 return &FAIL;
730         }
731
732         {
733                 /* pbx and bridge are modified by the bridging impart thread.
734                  * It shouldn't happen concurrently, but we still need to lock
735                  * for the memory fence.
736                  */
737                 SCOPED_AO2LOCK(lock, control);
738
739                 /* Save off the channel's PBX */
740                 ast_assert(control->pbx == NULL);
741                 if (!control->pbx) {
742                         control->pbx = ast_channel_pbx(chan);
743                         ast_channel_pbx_set(chan, NULL);
744                 }
745
746                 res = ast_bridge_impart(bridge,
747                         chan,
748                         NULL, /* swap channel */
749                         NULL, /* features */
750                         AST_BRIDGE_IMPART_CHAN_DEPARTABLE);
751                 if (res != 0) {
752                         ast_log(LOG_ERROR, "Error adding channel to bridge\n");
753                         ast_channel_pbx_set(chan, control->pbx);
754                         control->pbx = NULL;
755                         return &FAIL;
756                 }
757
758                 ast_assert(stasis_app_get_bridge(control) == NULL);
759                 control->bridge = bridge;
760         }
761         return &OK;
762 }
763
764 int stasis_app_control_add_channel_to_bridge(
765         struct stasis_app_control *control, struct ast_bridge *bridge)
766 {
767         int *res;
768         ast_debug(3, "%s: Sending channel add_to_bridge command\n",
769                         stasis_app_control_get_channel_id(control));
770         res = stasis_app_send_command(control,
771                 app_control_add_channel_to_bridge, bridge);
772         return *res;
773 }
774
775 static void *app_control_remove_channel_from_bridge(
776         struct stasis_app_control *control,
777         struct ast_channel *chan, void *data)
778 {
779         struct ast_bridge *bridge = data;
780
781         if (!control) {
782                 return &FAIL;
783         }
784
785         /* We should only depart from our own bridge */
786         ast_debug(3, "%s: Departing bridge %s\n",
787                 stasis_app_control_get_channel_id(control),
788                 bridge->uniqueid);
789
790         if (bridge != stasis_app_get_bridge(control)) {
791                 ast_log(LOG_WARNING, "%s: Not in bridge %s; not removing\n",
792                         stasis_app_control_get_channel_id(control),
793                         bridge->uniqueid);
794                 return &FAIL;
795         }
796
797         ast_bridge_depart(chan);
798         return &OK;
799 }
800
801 int stasis_app_control_remove_channel_from_bridge(
802         struct stasis_app_control *control, struct ast_bridge *bridge)
803 {
804         int *res;
805         ast_debug(3, "%s: Sending channel remove_from_bridge command\n",
806                         stasis_app_control_get_channel_id(control));
807         res = stasis_app_send_command(control,
808                 app_control_remove_channel_from_bridge, bridge);
809         return *res;
810 }
811
812 const char *stasis_app_control_get_channel_id(
813         const struct stasis_app_control *control)
814 {
815         return ast_channel_uniqueid(control->channel);
816 }
817
818 void stasis_app_control_publish(
819         struct stasis_app_control *control, struct stasis_message *message)
820 {
821         if (!control || !control->channel || !message) {
822                 return;
823         }
824         stasis_publish(ast_channel_topic(control->channel), message);
825 }
826
827 int stasis_app_control_queue_control(struct stasis_app_control *control,
828         enum ast_control_frame_type frame_type)
829 {
830         return ast_queue_control(control->channel, frame_type);
831 }
832
833 int control_dispatch_all(struct stasis_app_control *control,
834         struct ast_channel *chan)
835 {
836         int count = 0;
837         struct ao2_iterator i;
838         void *obj;
839
840         ast_assert(control->channel == chan);
841
842         i = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
843
844         while ((obj = ao2_iterator_next(&i))) {
845                 RAII_VAR(struct stasis_app_command *, command, obj, ao2_cleanup);
846                 command_invoke(command, control, chan);
847                 ++count;
848         }
849
850         ao2_iterator_destroy(&i);
851         return count;
852 }
853
854 void control_wait(struct stasis_app_control *control)
855 {
856         if (!control) {
857                 return;
858         }
859
860         ast_assert(control->command_queue != NULL);
861
862         ao2_lock(control->command_queue);
863         while (ao2_container_count(control->command_queue) == 0) {
864                 int res = ast_cond_wait(&control->wait_cond,
865                         ao2_object_get_lockaddr(control->command_queue));
866                 if (res < 0) {
867                         ast_log(LOG_ERROR, "Error waiting on command queue\n");
868                         break;
869                 }
870         }
871         ao2_unlock(control->command_queue);
872 }