Asterisk - The Open Source Telephony Project GIT-master-77d630f
bridge.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2007 - 2009, Digium, Inc.
5 *
6 * Joshua Colp <jcolp@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 Bridging API
22 *
23 * \author Joshua Colp <jcolp@digium.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30/*** DOCUMENTATION
31 <manager name="BridgeTechnologyList" language="en_US">
32 <since>
33 <version>12.0.0</version>
34 </since>
35 <synopsis>
36 List available bridging technologies and their statuses.
37 </synopsis>
38 <syntax>
39 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
40 </syntax>
41 <description>
42 <para>Returns detailed information about the available bridging technologies.</para>
43 </description>
44 <see-also>
45 <ref type="manager">BridgeTechnologySuspend</ref>
46 <ref type="manager">BridgeTechnologyUnsuspend</ref>
47 </see-also>
48 </manager>
49 <manager name="BridgeTechnologySuspend" language="en_US">
50 <since>
51 <version>12.0.0</version>
52 </since>
53 <synopsis>
54 Suspend a bridging technology.
55 </synopsis>
56 <syntax>
57 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
58 <parameter name="BridgeTechnology" required="true">
59 <para>The name of the bridging technology to suspend.</para>
60 </parameter>
61 </syntax>
62 <description>
63 <para>Marks a bridging technology as suspended, which prevents subsequently created bridges from using it.</para>
64 </description>
65 <see-also>
66 <ref type="manager">BridgeTechnologySuspend</ref>
67 <ref type="manager">BridgeTechnologyUnsuspend</ref>
68 </see-also>
69 </manager>
70 <manager name="BridgeTechnologyUnsuspend" language="en_US">
71 <since>
72 <version>12.0.0</version>
73 </since>
74 <synopsis>
75 Unsuspend a bridging technology.
76 </synopsis>
77 <syntax>
78 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
79 <parameter name="BridgeTechnology" required="true">
80 <para>The name of the bridging technology to unsuspend.</para>
81 </parameter>
82 </syntax>
83 <description>
84 <para>Clears a previously suspended bridging technology, which allows subsequently created bridges to use it.</para>
85 </description>
86 <see-also>
87 <ref type="manager">BridgeTechnologyList</ref>
88 <ref type="manager">BridgeTechnologySuspend</ref>
89 </see-also>
90 </manager>
91***/
92
93#include "asterisk.h"
94
95#include "asterisk/logger.h"
96#include "asterisk/channel.h"
97#include "asterisk/options.h"
98#include "asterisk/utils.h"
99#include "asterisk/lock.h"
100#include "asterisk/linkedlists.h"
101#include "asterisk/bridge.h"
112#include "asterisk/app.h"
113#include "asterisk/file.h"
114#include "asterisk/module.h"
115#include "asterisk/astobj2.h"
116#include "asterisk/pbx.h"
117#include "asterisk/test.h"
118#include "asterisk/_private.h"
119#include "asterisk/heap.h"
120#include "asterisk/say.h"
121#include "asterisk/timing.h"
123#include "asterisk/musiconhold.h"
124#include "asterisk/features.h"
125#include "asterisk/cli.h"
126#include "asterisk/parking.h"
127#include "asterisk/core_local.h"
128#include "asterisk/core_unreal.h"
129#include "asterisk/causes.h"
130
131/*! All bridges container. */
132static struct ao2_container *bridges;
133
135
137
138static unsigned int optimization_id;
139
140/* Initial starting point for the bridge array of channels */
141#define BRIDGE_ARRAY_START 128
142
143/* Grow rate of bridge array of channels */
144#define BRIDGE_ARRAY_GROW 32
145
146/* Variable name - stores peer information about the most recent blind transfer */
147#define BLINDTRANSFER "BLINDTRANSFER"
148
149/* Variable name - stores peer information about the most recent attended transfer */
150#define ATTENDEDTRANSFER "ATTENDEDTRANSFER"
151
152static void cleanup_video_mode(struct ast_bridge *bridge);
153
154/*! Default DTMF keys for built in features */
156
157/*! Function handlers for the built in features */
159
160/*! Function handlers for built in interval features */
162
163/*! Bridge manager service request */
165 /*! List of bridge service requests. */
167 /*! Refed bridge requesting service. */
169};
170
172 /*! Condition, used to wake up the bridge manager thread. */
174 /*! Queue of bridge service requests. */
176 /*! Manager thread */
177 pthread_t thread;
178 /*! TRUE if the manager needs to stop. */
179 unsigned int stop:1;
180};
181
182/*! Bridge manager controller. */
184
186{
187 return ao2_bump(bridges);
188}
189
190/*!
191 * \internal
192 * \brief Request service for a bridge from the bridge manager.
193 * \since 12.0.0
194 *
195 * \param bridge Requesting service.
196 */
197static void bridge_manager_service_req(struct ast_bridge *bridge)
198{
200
202 if (bridge_manager->stop) {
204 return;
205 }
206
207 /* Create the service request. */
208 request = ast_calloc(1, sizeof(*request));
209 if (!request) {
210 /* Well. This isn't good. */
212 return;
213 }
214 ao2_ref(bridge, +1);
215 request->bridge = bridge;
216
217 /* Put request into the queue and wake the bridge manager. */
221}
222
224{
226
227 /* Perform a sanity check to make sure the bridge technology conforms to our needed requirements */
228 if (ast_strlen_zero(technology->name)
229 || !technology->capabilities
230 || !technology->write) {
231 ast_log(LOG_WARNING, "Bridge technology %s failed registration sanity check.\n",
232 technology->name);
233 return -1;
234 }
235
237
238 /* Look for duplicate bridge technology already using this name, or already registered */
240 if ((!strcasecmp(current->name, technology->name)) || (current == technology)) {
241 ast_log(LOG_WARNING, "A bridge technology of %s already claims to exist in our world.\n",
242 technology->name);
244 return -1;
245 }
246 }
247
248 /* Copy module pointer so reference counting can keep the module from unloading */
249 technology->mod = module;
250
251 /* Find the correct position to insert the technology. */
253 /* Put the highest preference tech's first in the list. */
254 if (technology->preference >= current->preference) {
255 AST_RWLIST_INSERT_BEFORE_CURRENT(technology, entry);
256
257 break;
258 }
259 }
261
262 if (!current) {
263 /* Insert our new bridge technology to the end of the list. */
264 AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
265 }
266
268
269 ast_verb(5, "Registered bridge technology %s\n", technology->name);
270
271 return 0;
272}
273
275{
277
279
280 /* Ensure the bridge technology is registered before removing it */
282 if (current == technology) {
284 ast_verb(5, "Unregistered bridge technology %s\n", technology->name);
285 break;
286 }
287 }
289
291
292 return current ? 0 : -1;
293}
294
295/*!
296 * \internal
297 * \brief Put an action onto the specified bridge. Don't dup the action frame.
298 * \since 12.0.0
299 *
300 * \param bridge What to queue the action on.
301 * \param action What to do.
302 */
303static void bridge_queue_action_nodup(struct ast_bridge *bridge, struct ast_frame *action)
304{
305 ast_debug(1, "Bridge %s: queueing action type:%u sub:%d\n",
306 bridge->uniqueid, action->frametype, action->subclass.integer);
307
308 ast_bridge_lock(bridge);
310 ast_bridge_unlock(bridge);
312}
313
314int ast_bridge_queue_action(struct ast_bridge *bridge, struct ast_frame *action)
315{
316 struct ast_frame *dup;
317
318 dup = ast_frdup(action);
319 if (!dup) {
320 return -1;
321 }
322 bridge_queue_action_nodup(bridge, dup);
323 return 0;
324}
325
326void bridge_dissolve(struct ast_bridge *bridge, int cause)
327{
328 struct ast_bridge_channel *bridge_channel;
329 struct ast_frame action = {
332 };
333
334 if (bridge->dissolved) {
335 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": already dissolved\n",
336 BRIDGE_PRINTF_VARS(bridge));
337 return;
338 }
339 bridge->dissolved = 1;
340
341 if (cause <= 0) {
343 }
344 bridge->cause = cause;
345
346 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": dissolving with cause %d(%s)\n",
347 BRIDGE_PRINTF_VARS(bridge), cause, ast_cause2str(cause));
348
349 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
350 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": kicking channel %s\n",
351 BRIDGE_PRINTF_VARS(bridge),
352 ast_channel_name(bridge_channel->chan));
353 ast_bridge_channel_leave_bridge(bridge_channel,
355 }
356
357 /* Must defer dissolving bridge because it is already locked. */
358 ast_bridge_queue_action(bridge, &action);
359 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": DEFERRED_DISSOLVING queued. current refcound: %d\n",
360 BRIDGE_PRINTF_VARS(bridge), ao2_ref(bridge, 0));
361
362}
363
364/*!
365 * \internal
366 * \brief Check if a bridge should dissolve because of a stolen channel and do it.
367 * \since 12.0.0
368 *
369 * \param bridge Bridge to check.
370 * \param bridge_channel Stolen channel causing the check. It is not in the bridge to check and may be in another bridge.
371 *
372 * \note On entry, bridge and bridge_channel->bridge are already locked.
373 */
374static void bridge_dissolve_check_stolen(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
375{
376 if (bridge->dissolved) {
377 return;
378 }
379
380 if (bridge_channel->features->usable
381 && ast_test_flag(&bridge_channel->features->feature_flags,
383 /* The stolen channel controlled the bridge it was stolen from. */
384 bridge_dissolve(bridge, 0);
385 return;
386 }
387 if (bridge->num_channels < 2
389 /*
390 * The stolen channel has not left enough channels to keep the
391 * bridge alive. Assume the stolen channel hung up.
392 */
393 bridge_dissolve(bridge, 0);
394 return;
395 }
396}
397
398/*!
399 * \internal
400 * \brief Update connected line information after a bridge has been reconfigured.
401 *
402 * \param bridge The bridge itself.
403 */
405{
407 struct ast_bridge_channel *bridge_channel = AST_LIST_FIRST(&bridge->channels), *peer;
408 unsigned char data[1024];
409 size_t datalen;
410
411 if (!bridge_channel ||
413 !(peer = ast_bridge_channel_peer(bridge_channel)) ||
416 ast_check_hangup_locked(bridge_channel->chan) ||
417 ast_check_hangup_locked(peer->chan)) {
418 return;
419 }
420
422
423 ast_channel_lock(bridge_channel->chan);
425 ast_channel_unlock(bridge_channel->chan);
426
427 if ((datalen = ast_connected_line_build_data(data, sizeof(data), &connected, NULL)) != (size_t) -1) {
429 }
430
431 ast_channel_lock(peer->chan);
433 ast_channel_unlock(peer->chan);
434
435 if ((datalen = ast_connected_line_build_data(data, sizeof(data), &connected, NULL)) != (size_t) -1) {
437 }
438
440}
441
442/*!
443 * \internal
444 * \brief Complete joining a channel to the bridge.
445 * \since 12.0.0
446 *
447 * \param bridge What to operate upon.
448 * \param bridge_channel What is joining the bridge technology.
449 *
450 * \note On entry, bridge is already locked.
451 */
452static void bridge_channel_complete_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
453{
454 /* Tell the bridge technology we are joining so they set us up */
455 ast_debug(1, "Bridge %s: %p(%s) is joining %s technology\n",
456 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
459 && bridge->technology->join(bridge, bridge_channel)) {
460 /* We cannot leave the channel partially in the bridge so we must kick it out */
461 ast_debug(1, "Bridge %s: %p(%s) failed to join %s technology (Kicking it out)\n",
462 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
464 bridge_channel->just_joined = 1;
466 return;
467 }
468
469 bridge_channel->just_joined = 0;
470
471 /*
472 * When a channel joins the bridge its streams need to be mapped to the bridge's
473 * media types vector. This way all streams map to the same media type index for
474 * a given channel.
475 */
476 if (bridge_channel->bridge->technology->stream_topology_changed) {
477 bridge_channel->bridge->technology->stream_topology_changed(
478 bridge_channel->bridge, bridge_channel);
479 } else {
480 ast_bridge_channel_stream_map(bridge_channel);
481 }
482}
483
484/*!
485 * \internal
486 * \brief Complete joining new channels to the bridge.
487 * \since 12.0.0
488 *
489 * \param bridge Check for new channels on this bridge.
490 *
491 * \note On entry, bridge is already locked.
492 */
494{
495 struct ast_bridge_channel *bridge_channel;
496
497 if (bridge->dissolved) {
498 /*
499 * No sense in completing the join on channels for a dissolved
500 * bridge. They are just going to be removed soon anyway.
501 * However, we do have reason to abort here because the bridge
502 * technology may not be able to handle the number of channels
503 * still in the bridge.
504 */
505 return;
506 }
507
508 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
510 if (!bridge_channel->just_joined) {
511 continue;
512 }
513 bridge_channel_complete_join(bridge, bridge_channel);
514 }
515}
516
517/*! \brief Helper function used to find the "best" bridge technology given specified capabilities */
519{
521 struct ast_bridge_technology *best = NULL;
522
525 if (current->suspended) {
526 ast_debug(2, "Bridge technology %s is suspended. Skipping.\n",
527 current->name);
528 continue;
529 }
530 if (!(current->capabilities & capabilities)) {
531 ast_debug(2, "Bridge technology %s does not have any capabilities we want.\n",
532 current->name);
533 continue;
534 }
535 if (best && current->preference <= best->preference) {
536 ast_debug(2, "Bridge technology %s has less preference than %s (%u <= %u). Skipping.\n",
537 current->name, best->name, current->preference, best->preference);
538 continue;
539 }
540 if (current->compatible && !current->compatible(bridge)) {
541 ast_debug(2, "Bridge technology %s is not compatible with properties of existing bridge.\n",
542 current->name);
543 continue;
544 }
545 if (!ast_module_running_ref(current->mod)) {
546 ast_debug(2, "Bridge technology %s is not running, skipping.\n", current->name);
547 continue;
548 }
549 if (best) {
550 ast_module_unref(best->mod);
551 }
552 best = current;
553 }
554
555 if (best) {
556 ast_debug(1, "Chose bridge technology %s\n", best->name);
557 }
558
560
561 return best;
562}
563
566 void *tech_pvt;
567};
568
569/*!
570 * \internal
571 * \brief Deferred destruction of bridge tech private structure.
572 * \since 12.0.0
573 *
574 * \param bridge What to execute the action on.
575 * \param action Deferred bridge tech destruction.
576 *
577 * \note On entry, bridge must not be locked.
578 */
579static void bridge_tech_deferred_destroy(struct ast_bridge *bridge, struct ast_frame *action)
580{
581 struct tech_deferred_destroy *deferred = action->data.ptr;
582 struct ast_bridge dummy_bridge = {
583 .technology = deferred->tech,
584 .tech_pvt = deferred->tech_pvt,
585 .creator = bridge->creator,
586 .name = bridge->name,
587 .uniqueid = bridge->uniqueid,
588 };
589
590 ast_debug(1, "Bridge %s: calling %s technology destructor (deferred, dummy)\n",
591 dummy_bridge.uniqueid, dummy_bridge.technology->name);
592 dummy_bridge.technology->destroy(&dummy_bridge);
593 ast_module_unref(dummy_bridge.technology->mod);
594}
595
596/*!
597 * \internal
598 * \brief Handle bridge action frame.
599 * \since 12.0.0
600 *
601 * \param bridge What to execute the action on.
602 * \param action What to do.
603 *
604 * \note On entry, bridge is already locked.
605 * \note Can be called by the bridge destructor
606 */
607static void bridge_action_bridge(struct ast_bridge *bridge, struct ast_frame *action)
608{
609#if 0 /* In case we need to know when the destructor is calling us. */
610 int in_destructor = !ao2_ref(bridge, 0);
611#endif
612
613 switch (action->subclass.integer) {
615 ast_bridge_unlock(bridge);
616 bridge_tech_deferred_destroy(bridge, action);
617 ast_bridge_lock(bridge);
618 break;
620 ast_bridge_unlock(bridge);
621 bridge->v_table->dissolving(bridge);
622 ast_bridge_lock(bridge);
623 break;
624 default:
625 /* Unexpected deferred action type. Should never happen. */
626 ast_assert(0);
627 break;
628 }
629}
630
631/*!
632 * \internal
633 * \brief Do any pending bridge actions.
634 * \since 12.0.0
635 *
636 * \param bridge What to do actions on.
637 *
638 * \note On entry, bridge is already locked.
639 * \note Can be called by the bridge destructor.
640 */
641static void bridge_handle_actions(struct ast_bridge *bridge)
642{
643 struct ast_frame *action;
644
645 while ((action = AST_LIST_REMOVE_HEAD(&bridge->action_queue, frame_list))) {
646 switch (action->frametype) {
648 bridge_action_bridge(bridge, action);
649 break;
650 default:
651 /* Unexpected deferred frame type. Should never happen. */
652 ast_assert(0);
653 break;
654 }
655 ast_frfree(action);
656 }
657}
658
659static void destroy_bridge(void *obj)
660{
661 struct ast_bridge *bridge = obj;
662
663 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": actually destroying %s bridge, nobody wants it anymore\n",
664 BRIDGE_PRINTF_VARS(bridge), bridge->v_table->name);
665
666 if (bridge->construction_completed) {
667 bridge_topics_destroy(bridge);
668 }
669
670 /* Do any pending actions in the context of destruction. */
671 ast_bridge_lock(bridge);
672 bridge_handle_actions(bridge);
673 ast_bridge_unlock(bridge);
674
675 /* There should not be any channels left in the bridge. */
677
678 ast_debug(1, "Bridge %s: calling %s bridge destructor\n",
679 bridge->uniqueid, bridge->v_table->name);
680 bridge->v_table->destroy(bridge);
681
682 /* Pass off the bridge to the technology to destroy if needed */
683 if (bridge->technology) {
684 ast_debug(1, "Bridge %s: calling %s technology stop\n",
685 bridge->uniqueid, bridge->technology->name);
686 if (bridge->technology->stop) {
687 ast_bridge_lock(bridge);
688 bridge->technology->stop(bridge);
689 ast_bridge_unlock(bridge);
690 }
691 ast_debug(1, "Bridge %s: calling %s technology destructor\n",
692 bridge->uniqueid, bridge->technology->name);
693 if (bridge->technology->destroy) {
694 bridge->technology->destroy(bridge);
695 }
697 bridge->technology = NULL;
698 }
699
701
702 bridge->callid = 0;
703
704 cleanup_video_mode(bridge);
705
706 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": destroyed\n",
707 BRIDGE_PRINTF_VARS(bridge));
710 bridge->current_snapshot = NULL;
711}
712
713struct ast_bridge *bridge_register(struct ast_bridge *bridge)
714{
715 if (bridge) {
717 /*
718 * Although bridge_base_init() should have already checked for
719 * an existing bridge with the same uniqueid, bridge_base_init()
720 * and bridge_register() are two separate public APIs so we need
721 * to check again here.
722 */
723 struct ast_bridge *existing = ast_bridge_find_by_id(bridge->uniqueid);
724 if (existing) {
725 ast_log(LOG_WARNING, "Bridge " BRIDGE_PRINTF_SPEC ": already registered\n",
726 BRIDGE_PRINTF_VARS(bridge));
727 ao2_ref(existing, -1);
728 ast_bridge_destroy(bridge, 0);
729 return NULL;
730 }
731 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": registering\n",
732 BRIDGE_PRINTF_VARS(bridge));
733 bridge->construction_completed = 1;
734 ast_bridge_lock(bridge);
736 ast_bridge_unlock(bridge);
737 if (!ao2_link(bridges, bridge)) {
738 ast_log(LOG_WARNING, "Bridge " BRIDGE_PRINTF_SPEC ": failed to link\n",
739 BRIDGE_PRINTF_VARS(bridge));
740 ast_bridge_destroy(bridge, 0);
741 bridge = NULL;
742 }
743 }
744 return bridge;
745}
746
747struct ast_bridge *bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
748{
749 struct ast_bridge *bridge;
750
751 /* Check v_table that all methods are present. */
752 if (!v_table
753 || !v_table->name
754 || !v_table->destroy
756 || !v_table->push
757 || !v_table->pull
760 ast_log(LOG_ERROR, "Virtual method table for bridge class %s not complete.\n",
761 v_table && v_table->name ? v_table->name : "<unknown>");
762 ast_assert(0);
763 return NULL;
764 }
765
766 bridge = ao2_alloc(size, destroy_bridge);
767 if (!bridge) {
768 return NULL;
769 }
770
771 if (ast_string_field_init(bridge, 80)) {
772 ao2_cleanup(bridge);
773 return NULL;
774 }
775
776 bridge->v_table = v_table;
777
779
780 return bridge;
781}
782
783struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
784{
785 char uuid_hold[AST_UUID_STR_LEN];
786
787 if (!self) {
788 return NULL;
789 }
790
791 {
792 /*
793 * We need to ensure that another bridge with the same uniqueid
794 * doesn't get created before the previous bridge's destructor
795 * has run and deleted the existing topic.
796 */
798 if (!ast_strlen_zero(id)) {
799 if (ast_bridge_topic_exists(id)) {
800 ast_log(LOG_WARNING, "Bridge " BRIDGE_PRINTF_SPEC ": already registered\n",
801 BRIDGE_PRINTF_VARS(self));
802 ast_bridge_destroy(self, 0);
803 return NULL;
804 }
806 } else {
808 ast_string_field_set(self, uniqueid, uuid_hold);
809 }
810 if (!(flags & AST_BRIDGE_FLAG_INVISIBLE)) {
811 if (bridge_topics_init(self) != 0) {
812 ast_log(LOG_WARNING, "Bridge " BRIDGE_PRINTF_SPEC ": Could not initialize topics\n",
813 BRIDGE_PRINTF_VARS(self));
814 ao2_ref(self, -1);
815 return NULL;
816 }
817 }
818 }
819
821 if (!ast_strlen_zero(creator)) {
823 }
824 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": base_init\n",
825 BRIDGE_PRINTF_VARS(self));
826
827 ast_set_flag(&self->feature_flags, flags);
828 self->allowed_capabilities = capabilities;
829
830 /* Use our helper function to find the "best" bridge technology. */
831 self->technology = find_best_technology(capabilities, self);
832 if (!self->technology) {
833 ast_log(LOG_WARNING, "Bridge %s: Could not create class %s. No technology to support it.\n",
834 self->uniqueid, self->v_table->name);
835 ao2_ref(self, -1);
836 return NULL;
837 }
838
839 /* Pass off the bridge to the technology to manipulate if needed */
840 ast_debug(1, "Bridge %s: calling %s technology constructor\n",
841 self->uniqueid, self->technology->name);
842 if (self->technology->create && self->technology->create(self)) {
843 ast_log(LOG_WARNING, "Bridge %s: failed to setup bridge technology %s\n",
844 self->uniqueid, self->technology->name);
845 ao2_ref(self, -1);
846 return NULL;
847 }
848 ast_debug(1, "Bridge %s: calling %s technology start\n",
849 self->uniqueid, self->technology->name);
850 if (self->technology->start && self->technology->start(self)) {
851 ast_log(LOG_WARNING, "Bridge %s: failed to start bridge technology %s\n",
852 self->uniqueid, self->technology->name);
853 ao2_ref(self, -1);
854 return NULL;
855 }
856
857 if (!(flags & AST_BRIDGE_FLAG_INVISIBLE)) {
858 if (!ast_bridge_topic(self)) {
859 ao2_ref(self, -1);
860 return NULL;
861 }
862 }
863
864 self->creationtime = ast_tvnow();
865 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": base_init complete\n",
866 BRIDGE_PRINTF_VARS(self));
867
868 return self;
869}
870
871/*!
872 * \internal
873 * \brief ast_bridge base class destructor.
874 * \since 12.0.0
875 *
876 * \param self Bridge to operate upon.
877 *
878 * \note Stub because of nothing to do.
879 */
880static void bridge_base_destroy(struct ast_bridge *self)
881{
882 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": destroying bridge (noop)\n",
883 BRIDGE_PRINTF_VARS(self));
884}
885
886/*!
887 * \internal
888 * \brief The bridge is being dissolved.
889 * \since 12.0.0
890 *
891 * \param self Bridge to operate upon.
892 */
893static void bridge_base_dissolving(struct ast_bridge *self)
894{
895 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": unlinking bridge. Refcount: %d\n",
896 BRIDGE_PRINTF_VARS(self), ao2_ref(self, 0));
897 ao2_unlink(bridges, self);
898 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": unlinked bridge. Refcount: %d\n",
899 BRIDGE_PRINTF_VARS(self), ao2_ref(self, 0));
900}
901
902/*!
903 * \internal
904 * \brief ast_bridge base push method.
905 * \since 12.0.0
906 *
907 * \param self Bridge to operate upon.
908 * \param bridge_channel Bridge channel to push.
909 * \param swap Bridge channel to swap places with if not NULL.
910 *
911 * \note On entry, self is already locked.
912 * \note Stub because of nothing to do.
913 *
914 * \retval 0 on success
915 * \retval -1 on failure
916 */
917static int bridge_base_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
918{
919 return 0;
920}
921
922/*!
923 * \internal
924 * \brief ast_bridge base pull method.
925 * \since 12.0.0
926 *
927 * \param self Bridge to operate upon.
928 * \param bridge_channel Bridge channel to pull.
929 *
930 * \note On entry, self is already locked.
931 */
932static void bridge_base_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
933{
935}
936
937/*!
938 * \internal
939 * \brief ast_bridge base notify_masquerade method.
940 * \since 12.0.0
941 *
942 * \param self Bridge to operate upon.
943 * \param bridge_channel Bridge channel that was masqueraded.
944 *
945 * \note On entry, self is already locked.
946 */
947static void bridge_base_notify_masquerade(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
948{
949 self->reconfigured = 1;
950}
951
952/*!
953 * \internal
954 * \brief Get the merge priority of this bridge.
955 * \since 12.0.0
956 *
957 * \param self Bridge to operate upon.
958 *
959 * \note On entry, self is already locked.
960 *
961 * \return Merge priority
962 */
964{
965 return 0;
966}
967
968/*!
969 * \internal
970 * \brief ast_bridge base push_peek method.
971 * \since 13.2.0
972 *
973 * \param self Bridge to operate upon.
974 * \param bridge_channel Bridge channel to push.
975 * \param swap Bridge channel to swap places with if not NULL.
976 *
977 * \note On entry, self is already locked.
978 * \note Stub because of nothing to do.
979 *
980 * \retval 0 on success
981 * \retval -1 on failure
982 */
983static int bridge_base_push_peek(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
984{
985 return 0;
986}
987
989 .name = "base",
990 .destroy = bridge_base_destroy,
991 .dissolving = bridge_base_dissolving,
992 .push = bridge_base_push,
993 .pull = bridge_base_pull,
994 .notify_masquerade = bridge_base_notify_masquerade,
995 .get_merge_priority = bridge_base_get_merge_priority,
996 .push_peek = bridge_base_push_peek,
997};
998
999struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
1000{
1001 void *bridge;
1002
1003 bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_base_v_table);
1004 bridge = bridge_base_init(bridge, capabilities, flags, creator, name, id);
1005 bridge = bridge_register(bridge);
1006 return bridge;
1007}
1008
1009int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
1010{
1011 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": destroying. current refcount: %d\n",
1012 BRIDGE_PRINTF_VARS(bridge), ao2_ref(bridge, 0));
1013 ast_bridge_lock(bridge);
1014 bridge_dissolve(bridge, cause);
1015 ast_bridge_unlock(bridge);
1016
1017 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": unreffing. current refcount: %d\n",
1018 BRIDGE_PRINTF_VARS(bridge), ao2_ref(bridge, 0));
1019
1020 ao2_ref(bridge, -1);
1021
1022 return 0;
1023}
1024
1025/*!
1026 * \internal
1027 * \brief Perform the smart bridge operation.
1028 * \since 12.0.0
1029 *
1030 * \param bridge Work on this bridge.
1031 *
1032 * \details
1033 * Basically see if a new bridge technology should be used instead
1034 * of the current one.
1035 *
1036 * \note On entry, bridge is already locked.
1037 *
1038 * \retval 0 on success.
1039 * \retval -1 on error.
1040 */
1041static int smart_bridge_operation(struct ast_bridge *bridge)
1042{
1043 uint32_t new_capabilities;
1044 struct ast_bridge_technology *new_technology;
1045 struct ast_bridge_technology *old_technology = bridge->technology;
1046 struct ast_bridge_channel *bridge_channel;
1047 struct ast_frame *deferred_action;
1048 struct ast_bridge dummy_bridge = {
1049 .technology = bridge->technology,
1050 .tech_pvt = bridge->tech_pvt,
1051 .creator = bridge->creator,
1052 .name = bridge->name,
1053 .uniqueid = bridge->uniqueid,
1054 };
1055
1056 if (bridge->dissolved) {
1057 ast_debug(1, "Bridge %s is dissolved, not performing smart bridge operation.\n",
1058 bridge->uniqueid);
1059 return 0;
1060 }
1061
1062 /* Determine new bridge technology capabilities needed. */
1063 if (2 < bridge->num_channels) {
1064 new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
1065 new_capabilities &= bridge->allowed_capabilities;
1066 } else {
1068 new_capabilities &= bridge->allowed_capabilities;
1069 if (!new_capabilities
1071 /* Allow switching between different multimix bridge technologies. */
1072 new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
1073 }
1074 }
1075
1076 /* Find a bridge technology to satisfy the new capabilities. */
1077 new_technology = find_best_technology(new_capabilities, bridge);
1078 if (!new_technology) {
1079 int is_compatible = 0;
1080
1081 if (old_technology->compatible) {
1082 is_compatible = old_technology->compatible(bridge);
1083 } else if (old_technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
1084 is_compatible = 1;
1085 } else if (bridge->num_channels <= 2
1086 && (old_technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX)) {
1087 is_compatible = 1;
1088 }
1089
1090 if (is_compatible) {
1091 ast_debug(1, "Bridge %s could not get a new technology, staying with old technology.\n",
1092 bridge->uniqueid);
1093 return 0;
1094 }
1095 ast_log(LOG_WARNING, "Bridge %s has no technology available to support it.\n",
1096 bridge->uniqueid);
1097 return -1;
1098 }
1099 if (new_technology == old_technology) {
1100 ast_debug(1, "Bridge %s is already using the new technology.\n",
1101 bridge->uniqueid);
1102 ast_module_unref(old_technology->mod);
1103 return 0;
1104 }
1105
1106 if (old_technology->destroy) {
1107 struct tech_deferred_destroy deferred_tech_destroy = {
1108 .tech = dummy_bridge.technology,
1109 .tech_pvt = dummy_bridge.tech_pvt,
1110 };
1111 struct ast_frame action = {
1114 .data.ptr = &deferred_tech_destroy,
1115 .datalen = sizeof(deferred_tech_destroy),
1116 };
1117
1118 /*
1119 * We need to defer the bridge technology destroy callback
1120 * because we have the bridge locked.
1121 */
1122 deferred_action = ast_frdup(&action);
1123 if (!deferred_action) {
1124 ast_module_unref(new_technology->mod);
1125 return -1;
1126 }
1127 } else {
1129 }
1130
1131 /*
1132 * We are now committed to changing the bridge technology. We
1133 * must not release the bridge lock until we have installed the
1134 * new bridge technology.
1135 */
1136 ast_verb(4, "Bridge %s: switching from %s technology to %s\n",
1137 bridge->uniqueid, old_technology->name, new_technology->name);
1138
1139 /*
1140 * Since we are soon going to pass this bridge to a new
1141 * technology we need to NULL out the tech_pvt pointer but
1142 * don't worry as it still exists in dummy_bridge, ditto for the
1143 * old technology.
1144 */
1145 bridge->tech_pvt = NULL;
1146 bridge->technology = new_technology;
1147
1148 /* Setup the new bridge technology. */
1149 ast_debug(1, "Bridge %s: calling %s technology constructor\n",
1150 bridge->uniqueid, new_technology->name);
1151 if (new_technology->create && new_technology->create(bridge)) {
1152 ast_log(LOG_WARNING, "Bridge %s: failed to setup bridge technology %s\n",
1153 bridge->uniqueid, new_technology->name);
1154 bridge->tech_pvt = dummy_bridge.tech_pvt;
1155 bridge->technology = dummy_bridge.technology;
1156 ast_module_unref(new_technology->mod);
1157 return -1;
1158 }
1159
1160 /* To ensure that things are sane for the old technology move the channels it
1161 * expects to the dummy bridge
1162 */
1163 AST_LIST_TRAVERSE_SAFE_BEGIN(&bridge->channels, bridge_channel, entry) {
1164 if (bridge_channel->just_joined) {
1165 continue;
1166 }
1167 ast_debug(1, "Bridge %s: moving %p(%s) to dummy bridge temporarily\n",
1168 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
1170 AST_LIST_INSERT_TAIL(&dummy_bridge.channels, bridge_channel, entry);
1171 dummy_bridge.num_channels++;
1173 dummy_bridge.num_lonely++;
1174 }
1175 if (!bridge_channel->suspended) {
1176 dummy_bridge.num_active++;
1177 }
1178 }
1180
1181 /* Take all the channels out of the old technology */
1182 AST_LIST_TRAVERSE_SAFE_BEGIN(&dummy_bridge.channels, bridge_channel, entry) {
1183 ast_debug(1, "Bridge %s: %p(%s) is leaving %s technology (dummy)\n",
1184 dummy_bridge.uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
1185 old_technology->name);
1186 if (old_technology->leave) {
1187 old_technology->leave(&dummy_bridge, bridge_channel);
1188 }
1190 AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
1191 dummy_bridge.num_channels--;
1193 dummy_bridge.num_lonely--;
1194 }
1195 if (!bridge_channel->suspended) {
1196 dummy_bridge.num_active--;
1197 }
1198 }
1200
1201 ast_debug(1, "Bridge %s: calling %s technology stop\n",
1202 dummy_bridge.uniqueid, old_technology->name);
1203 if (old_technology->stop) {
1204 old_technology->stop(&dummy_bridge);
1205 }
1206
1207 /* Add any new channels or re-add existing channels to the bridge. */
1208 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1209 bridge_channel_complete_join(bridge, bridge_channel);
1210 }
1211
1212 ast_debug(1, "Bridge %s: calling %s technology start\n",
1213 bridge->uniqueid, new_technology->name);
1214 if (new_technology->start && new_technology->start(bridge)) {
1215 ast_log(LOG_WARNING, "Bridge %s: failed to start bridge technology %s\n",
1216 bridge->uniqueid, new_technology->name);
1217 }
1218
1219 /*
1220 * Now that all the channels have been moved over we need to get
1221 * rid of all the information the old technology may have left
1222 * around.
1223 */
1224 if (old_technology->destroy) {
1225 ast_debug(1, "Bridge %s: deferring %s technology destructor\n",
1226 dummy_bridge.uniqueid, old_technology->name);
1228 } else {
1229 ast_debug(1, "Bridge %s: calling %s technology destructor\n",
1230 dummy_bridge.uniqueid, old_technology->name);
1231 ast_module_unref(old_technology->mod);
1232 }
1233
1234 return 0;
1235}
1236
1237/*!
1238 * \internal
1239 * \brief Bridge channel to check if a BRIDGE_PLAY_SOUND needs to be played.
1240 * \since 12.0.0
1241 *
1242 * \param bridge_channel What to check.
1243 */
1244static void check_bridge_play_sound(struct ast_bridge_channel *bridge_channel)
1245{
1246 const char *play_file;
1247
1248 ast_channel_lock(bridge_channel->chan);
1249 play_file = pbx_builtin_getvar_helper(bridge_channel->chan, "BRIDGE_PLAY_SOUND");
1250 if (!ast_strlen_zero(play_file)) {
1252 pbx_builtin_setvar_helper(bridge_channel->chan, "BRIDGE_PLAY_SOUND", NULL);
1253 } else {
1254 play_file = NULL;
1255 }
1256 ast_channel_unlock(bridge_channel->chan);
1257
1258 if (play_file) {
1260 }
1261}
1262
1263/*!
1264 * \internal
1265 * \brief Check for any BRIDGE_PLAY_SOUND channel variables in the bridge.
1266 * \since 12.0.0
1267 *
1268 * \param bridge What to operate on.
1269 *
1270 * \note On entry, the bridge is already locked.
1271 */
1272static void check_bridge_play_sounds(struct ast_bridge *bridge)
1273{
1274 struct ast_bridge_channel *bridge_channel;
1275
1276 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1277 check_bridge_play_sound(bridge_channel);
1278 }
1279}
1280
1281void ast_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
1282{
1284 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", name);
1285 pbx_builtin_setvar_helper(chan, "BRIDGEPVTCALLID", pvtid);
1287}
1288
1289/*!
1290 * \internal
1291 * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a 2 party bridge.
1292 * \since 12.0.0
1293 *
1294 * \param c0 Party of the first part.
1295 * \param c1 Party of the second part.
1296 *
1297 * \note On entry, the bridge is already locked.
1298 * \note The bridge is expected to have exactly two parties.
1299 */
1300static void set_bridge_peer_vars_2party(struct ast_channel *c0, struct ast_channel *c1)
1301{
1302 const char *c0_name;
1303 const char *c1_name;
1304 const char *c0_pvtid = NULL;
1305 const char *c1_pvtid = NULL;
1306#define UPDATE_BRIDGE_VARS_GET(chan, name, pvtid) \
1307 do { \
1308 name = ast_strdupa(ast_channel_name(chan)); \
1309 if (ast_channel_tech(chan)->get_pvt_uniqueid) { \
1310 pvtid = ast_strdupa(ast_channel_tech(chan)->get_pvt_uniqueid(chan)); \
1311 } \
1312 } while (0)
1313
1314 ast_channel_lock(c1);
1315 UPDATE_BRIDGE_VARS_GET(c1, c1_name, c1_pvtid);
1317
1318 ast_channel_lock(c0);
1319 ast_bridge_vars_set(c0, c1_name, c1_pvtid);
1320 UPDATE_BRIDGE_VARS_GET(c0, c0_name, c0_pvtid);
1322
1323 ast_channel_lock(c1);
1324 ast_bridge_vars_set(c1, c0_name, c0_pvtid);
1326}
1327
1328/*!
1329 * \internal
1330 * \brief Fill the BRIDGEPEER value buffer with a comma separated list of channel names.
1331 * \since 12.0.0
1332 *
1333 * \param buf Buffer to fill. The caller must guarantee the buffer is large enough.
1334 * \param cur_idx Which index into names[] to skip.
1335 * \param names Channel names to put in the buffer.
1336 * \param num_names Number of names in the array.
1337 */
1338static void fill_bridgepeer_buf(char *buf, unsigned int cur_idx, const char *names[], unsigned int num_names)
1339{
1340 int need_separator = 0;
1341 unsigned int idx;
1342 const char *src;
1343 char *pos;
1344
1345 pos = buf;
1346 for (idx = 0; idx < num_names; ++idx) {
1347 if (idx == cur_idx) {
1348 continue;
1349 }
1350
1351 if (need_separator) {
1352 *pos++ = ',';
1353 }
1354 need_separator = 1;
1355
1356 /* Copy name into buffer. */
1357 src = names[idx];
1358 while (*src) {
1359 *pos++ = *src++;
1360 }
1361 }
1362 *pos = '\0';
1363}
1364
1365/*!
1366 * \internal
1367 * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a multi-party bridge.
1368 * \since 12.0.0
1369 *
1370 * \param bridge What to operate on.
1371 *
1372 * \note On entry, the bridge is already locked.
1373 * \note The bridge is expected to have more than two parties.
1374 */
1376{
1377/*
1378 * Set a maximum number of channel names for the BRIDGEPEER
1379 * list. The plus one is for the current channel which is not
1380 * put in the list.
1381 */
1382#define MAX_BRIDGEPEER_CHANS (10 + 1)
1383
1384 unsigned int idx;
1385 unsigned int num_names;
1386 unsigned int len;
1387 const char **names;
1388 char *buf;
1389 struct ast_bridge_channel *bridge_channel;
1390
1391 /* Get first MAX_BRIDGEPEER_CHANS channel names. */
1393 names = ast_alloca(num_names * sizeof(*names));
1394 idx = 0;
1395 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1396 if (num_names <= idx) {
1397 break;
1398 }
1399 ast_channel_lock(bridge_channel->chan);
1400 names[idx++] = ast_strdupa(ast_channel_name(bridge_channel->chan));
1401 ast_channel_unlock(bridge_channel->chan);
1402 }
1403
1404 /* Determine maximum buf size needed. */
1405 len = num_names;
1406 for (idx = 0; idx < num_names; ++idx) {
1407 len += strlen(names[idx]);
1408 }
1409 buf = ast_alloca(len);
1410
1411 /* Set the bridge channel variables. */
1412 idx = 0;
1413 buf[0] = '\0';
1414 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1415 if (idx < num_names) {
1416 fill_bridgepeer_buf(buf, idx, names, num_names);
1417 }
1418 ++idx;
1419
1420 ast_channel_lock(bridge_channel->chan);
1421 ast_bridge_vars_set(bridge_channel->chan, buf, NULL);
1422 ast_channel_unlock(bridge_channel->chan);
1423 }
1424}
1425
1426/*!
1427 * \internal
1428 * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a holding bridge.
1429 * \since 12.0.0
1430 *
1431 * \param bridge What to operate on.
1432 *
1433 * \note On entry, the bridge is already locked.
1434 */
1436{
1437 struct ast_bridge_channel *bridge_channel;
1438
1439 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1440 ast_channel_lock(bridge_channel->chan);
1441 ast_bridge_vars_set(bridge_channel->chan, NULL, NULL);
1442 ast_channel_unlock(bridge_channel->chan);
1443 }
1444}
1445
1446/*!
1447 * \internal
1448 * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in the bridge.
1449 * \since 12.0.0
1450 *
1451 * \param bridge What to operate on.
1452 *
1453 * \note On entry, the bridge is already locked.
1454 */
1456{
1459 return;
1460 }
1461 if (bridge->num_channels < 2) {
1462 return;
1463 }
1464 if (bridge->num_channels == 2) {
1466 AST_LIST_LAST(&bridge->channels)->chan);
1467 } else {
1469 }
1470}
1471
1472void bridge_reconfigured(struct ast_bridge *bridge, unsigned int colp_update)
1473{
1474 if (!bridge->reconfigured) {
1475 return;
1476 }
1477 bridge->reconfigured = 0;
1480 /* Smart bridge failed. */
1482 return;
1483 }
1485
1486 if (bridge->dissolved) {
1487 return;
1488 }
1492
1493 if (colp_update) {
1495 }
1496}
1497
1499{
1500 struct ast_bridge_channel *bridge_channel;
1501
1502 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1503 if (bridge_channel->chan == chan) {
1504 break;
1505 }
1506 }
1507
1508 return bridge_channel;
1509}
1510
1512{
1513 struct ast_bridge_channel *bridge_channel;
1514 struct ast_bridge *bridge;
1515
1516 /* Safely get the bridge_channel pointer for the chan. */
1517 ast_channel_lock(chan);
1518 bridge_channel = ast_channel_get_bridge_channel(chan);
1519 ast_channel_unlock(chan);
1520 if (!bridge_channel) {
1521 /* Not in a bridge */
1522 return;
1523 }
1524
1525 ast_bridge_channel_lock_bridge(bridge_channel);
1526 bridge = bridge_channel->bridge;
1527 if (bridge_channel == bridge_find_channel(bridge, chan)) {
1528/*
1529 * XXX ASTERISK-22366 this needs more work. The channels need
1530 * to be made compatible again if the formats change. The
1531 * bridge_channel thread needs to monitor for this case.
1532 */
1533 /* The channel we want to notify is still in a bridge. */
1534 bridge->v_table->notify_masquerade(bridge, bridge_channel);
1535 bridge_reconfigured(bridge, 1);
1536 }
1537 ast_bridge_unlock(bridge);
1538 ao2_ref(bridge_channel, -1);
1539}
1540
1541/*!
1542 * \brief Internal bridge impart wait condition and associated conditional.
1543 */
1546 /*! Lock for the data structure */
1548 /*! Wait condition */
1550 /*! Wait until done */
1551 int done;
1552};
1553
1555
1556/*!
1557 * \internal
1558 * \brief Signal imparting threads to wake up.
1559 * \since 13.9.0
1560 *
1561 * \param ds_head List of imparting threads to wake up.
1562 */
1564{
1565 if (ds_head) {
1567
1568 while ((cond = AST_LIST_REMOVE_HEAD(ds_head, node))) {
1569 ast_mutex_lock(&cond->lock);
1570 cond->done = 1;
1571 ast_cond_signal(&cond->cond);
1572 ast_mutex_unlock(&cond->lock);
1573 }
1574 }
1575}
1576
1577static void bridge_channel_impart_ds_head_dtor(void *doomed)
1578{
1580 ast_free(doomed);
1581}
1582
1583/*!
1584 * \internal
1585 * \brief Fixup the bridge impart datastore.
1586 * \since 13.9.0
1587 *
1588 * \param data Bridge impart datastore data to fixup from old_chan.
1589 * \param old_chan The datastore is moving from this channel.
1590 * \param new_chan The datastore is moving to this channel.
1591 */
1592static void bridge_channel_impart_ds_head_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
1593{
1594 /*
1595 * Signal any waiting impart threads. The masquerade is going to kill
1596 * old_chan and we don't need to be waiting on new_chan.
1597 */
1599}
1600
1602 .type = "bridge-impart-ds",
1605};
1606
1607/*!
1608 * \internal
1609 * \brief Add impart wait datastore conditional to channel.
1610 * \since 13.9.0
1611 *
1612 * \param chan Channel to add the impart wait conditional.
1613 * \param cond Imparting conditional to add.
1614 *
1615 * \retval 0 on success.
1616 * \retval -1 on error.
1617 */
1619{
1620 struct ast_datastore *datastore;
1621 struct bridge_channel_impart_ds_head *ds_head;
1622
1623 ast_channel_lock(chan);
1624
1626 if (!datastore) {
1628 if (!datastore) {
1629 ast_channel_unlock(chan);
1630 return -1;
1631 }
1632 ds_head = ast_calloc(1, sizeof(*ds_head));
1633 if (!ds_head) {
1634 ast_channel_unlock(chan);
1635 ast_datastore_free(datastore);
1636 return -1;
1637 }
1638 datastore->data = ds_head;
1639 ast_channel_datastore_add(chan, datastore);
1640 } else {
1641 ds_head = datastore->data;
1642 ast_assert(ds_head != NULL);
1643 }
1644
1645 AST_LIST_INSERT_TAIL(ds_head, cond, node);
1646
1647 ast_channel_unlock(chan);
1648 return 0;
1649}
1650
1652{
1653 struct ast_datastore *datastore;
1654
1655 ast_channel_lock(chan);
1657 if (datastore) {
1659 }
1660 ast_channel_unlock(chan);
1661}
1662
1663/*!
1664 * \internal
1665 * \brief Block imparting channel thread until signaled.
1666 * \since 13.9.0
1667 *
1668 * \param cond Imparting conditional to wait for.
1669 */
1671{
1672 ast_mutex_lock(&cond->lock);
1673 while (!cond->done) {
1674 ast_cond_wait(&cond->cond, &cond->lock);
1675 }
1676 ast_mutex_unlock(&cond->lock);
1677}
1678
1679/*
1680 * XXX ASTERISK-21271 make ast_bridge_join() require features to be allocated just like ast_bridge_impart() and not expect the struct back.
1681 *
1682 * This change is really going to break ConfBridge. All other
1683 * users are easily changed. However, it is needed so the
1684 * bridging code can manipulate features on all channels
1685 * consistently no matter how they joined.
1686 *
1687 * Need to update the features parameter doxygen when this
1688 * change is made to be like ast_bridge_impart().
1689 */
1690int ast_bridge_join(struct ast_bridge *bridge,
1691 struct ast_channel *chan,
1692 struct ast_channel *swap,
1693 struct ast_bridge_features *features,
1694 struct ast_bridge_tech_optimizations *tech_args,
1695 enum ast_bridge_join_flags flags)
1696{
1697 struct ast_bridge_channel *bridge_channel;
1698 int res = 0;
1699 SCOPE_TRACE(1, "%s Bridge: %s\n", ast_channel_name(chan), bridge->uniqueid);
1700
1701 bridge_channel = bridge_channel_internal_alloc(bridge);
1702 if (flags & AST_BRIDGE_JOIN_PASS_REFERENCE) {
1703 ao2_ref(bridge, -1);
1704 }
1705 if (!bridge_channel) {
1706 ao2_t_cleanup(swap, "Error exit: bridge_channel alloc failed");
1707 res = -1;
1708 goto join_exit;
1709 }
1710/* XXX ASTERISK-21271 features cannot be NULL when passed in. When it is changed to allocated we can do like ast_bridge_impart() and allocate one. */
1712 if (!features) {
1713 ao2_ref(bridge_channel, -1);
1714 ao2_t_cleanup(swap, "Error exit: features is NULL");
1715 res = -1;
1716 goto join_exit;
1717 }
1718 if (tech_args) {
1719 bridge_channel->tech_args = *tech_args;
1720 }
1721
1724 res = -1;
1725 } else {
1727 }
1729 bridge_channel->thread = pthread_self();
1730 bridge_channel->chan = chan;
1731 bridge_channel->swap = swap;
1732 bridge_channel->features = features;
1733 bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP);
1734
1735 /* allow subclass to peek at upcoming push operation */
1736 if (bridge->v_table->push_peek && !res) {
1737 struct ast_bridge_channel *bcswap = NULL;
1738
1740 if (bridge_channel->swap) {
1741 bcswap = bridge_find_channel(bridge, bridge_channel->swap);
1742 }
1743 res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
1745 }
1746
1747 if (!res) {
1748 res = bridge_channel_internal_join(bridge_channel);
1749 }
1750
1751 /* Cleanup all the data in the bridge channel after it leaves the bridge. */
1755 /* Due to a race condition, we lock the bridge channel here for ast_bridge_channel_get_chan */
1756 ao2_lock(bridge_channel);
1757 bridge_channel->chan = NULL;
1758 ao2_unlock(bridge_channel);
1759 /* If bridge_channel->swap is not NULL then the join failed. */
1760 ao2_t_cleanup(bridge_channel->swap, "Bridge complete: join failed");
1761 bridge_channel->swap = NULL;
1762 bridge_channel->features = NULL;
1763
1764 ao2_ref(bridge_channel, -1);
1765
1766join_exit:
1771 /* Claim the after bridge goto is an async goto destination. */
1775 }
1776 return res;
1777}
1778
1779/*! \brief Thread responsible for imparted bridged channels to be departed */
1780static void *bridge_channel_depart_thread(void *data)
1781{
1782 struct ast_bridge_channel *bridge_channel = data;
1783 int res = 0;
1784
1785 if (bridge_channel->callid) {
1786 ast_callid_threadassoc_add(bridge_channel->callid);
1787 }
1788
1789 res = bridge_channel_internal_join(bridge_channel);
1790
1791 /*
1792 * cleanup
1793 *
1794 * If bridge_channel->swap is not NULL then the join failed.
1795 */
1796 ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Departable impart join failed");
1797 bridge_channel->swap = NULL;
1798 ast_bridge_features_destroy(bridge_channel->features);
1799 bridge_channel->features = NULL;
1800
1803 /* If join failed there will be impart threads waiting. */
1804 bridge_channel_impart_signal(bridge_channel->chan);
1805 ast_bridge_discard_after_goto(bridge_channel->chan);
1806
1807 return NULL;
1808}
1809
1810/*! \brief Thread responsible for independent imparted bridged channels */
1811static void *bridge_channel_ind_thread(void *data)
1812{
1813 struct ast_bridge_channel *bridge_channel = data;
1814 struct ast_channel *chan;
1815
1816 if (bridge_channel->callid) {
1818 }
1819
1821 chan = bridge_channel->chan;
1822
1823 /* cleanup */
1824 ast_channel_lock(chan);
1826 ast_channel_unlock(chan);
1827 /* Lock here for ast_bridge_channel_get_chan */
1831 /* If bridge_channel->swap is not NULL then the join failed. */
1832 ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Independent impart join failed");
1836
1838
1840 /* If join failed there will be impart threads waiting. */
1843 return NULL;
1844}
1845
1847 struct ast_channel *chan,
1848 struct ast_channel *swap,
1849 struct ast_bridge_features *features,
1852{
1853 int res = 0;
1854 struct ast_bridge_channel *bridge_channel;
1855
1856 /* Imparted channels cannot have a PBX. */
1857 if (ast_channel_pbx(chan)) {
1858 ast_log(AST_LOG_WARNING, "Channel %s has a PBX thread and cannot be imparted into bridge %s\n",
1861 return -1;
1862 }
1863
1864 /* Supply an empty features structure if the caller did not. */
1865 if (!features) {
1867 if (!features) {
1868 return -1;
1869 }
1870 }
1871
1872 /* Try to allocate a structure for the bridge channel */
1873 bridge_channel = bridge_channel_internal_alloc(bridge);
1874 if (!bridge_channel) {
1876 return -1;
1877 }
1878
1881 ast_log(AST_LOG_NOTICE, "Channel %s is a zombie and cannot be imparted into bridge %s\n",
1883 res = -1;
1884 } else {
1886 }
1888 bridge_channel->chan = chan;
1889 bridge_channel->swap = ao2_t_bump(swap, "Setting up bridge impart");
1890 bridge_channel->features = features;
1891 bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP);
1892 bridge_channel->depart_wait =
1894 bridge_channel->callid = ast_read_threadstorage_callid();
1895
1896 /* allow subclass to peek at swap channel before it can hangup */
1897 if (bridge->v_table->push_peek && !res) {
1898 struct ast_bridge_channel *bcswap = NULL;
1899
1901 if (bridge_channel->swap) {
1902 bcswap = bridge_find_channel(bridge, bridge_channel->swap);
1903 }
1904 res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
1906 }
1907
1908 /* Actually create the thread that will handle the channel */
1909 if (!res) {
1911 }
1912 if (!res) {
1914 res = ast_pthread_create_detached(&bridge_channel->thread, NULL,
1915 bridge_channel_ind_thread, bridge_channel);
1916 } else {
1917 res = ast_pthread_create(&bridge_channel->thread, NULL,
1918 bridge_channel_depart_thread, bridge_channel);
1919 }
1920
1921 if (!res) {
1923 }
1924 }
1925
1926 if (res) {
1927 /* cleanup */
1931 /* Lock here for ast_bridge_channel_get_chan */
1932 ao2_lock(bridge_channel);
1933 bridge_channel->chan = NULL;
1934 ao2_unlock(bridge_channel);
1935 ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Impart failed");
1936 bridge_channel->swap = NULL;
1937 ast_bridge_features_destroy(bridge_channel->features);
1938 bridge_channel->features = NULL;
1939
1940 ao2_ref(bridge_channel, -1);
1941 return -1;
1942 }
1943
1944 return 0;
1945}
1946
1948 struct ast_channel *chan,
1949 struct ast_channel *swap,
1951 enum ast_bridge_impart_flags flags)
1952{
1954 .done = 0,
1955 };
1956 int res;
1957 SCOPE_TRACE(1, "%s Bridge: %s\n", ast_channel_name(chan), bridge->uniqueid);
1958
1959 ast_mutex_init(&cond.lock);
1960 ast_cond_init(&cond.cond, NULL);
1961
1962 res = bridge_impart_internal(bridge, chan, swap, features, flags, &cond);
1963 if (res) {
1964 /* Impart failed. Signal any other waiting impart threads */
1967 }
1968
1969 ast_cond_destroy(&cond.cond);
1970 ast_mutex_destroy(&cond.lock);
1971
1972 return res;
1973}
1974
1976{
1977 struct ast_bridge_channel *bridge_channel;
1978 int departable;
1979 SCOPE_TRACE(1, "%s\n", ast_channel_name(chan));
1980
1982 bridge_channel = ast_channel_internal_bridge_channel(chan);
1983 departable = bridge_channel && bridge_channel->depart_wait;
1985 if (!departable) {
1986 ast_log(LOG_ERROR, "Channel %s cannot be departed.\n",
1988 /*
1989 * Should never happen. It likely means that
1990 * ast_bridge_depart() is called by two threads for the same
1991 * channel, the channel was never imparted to be departed, or it
1992 * has already been departed.
1993 */
1994 ast_assert(0);
1995 return -1;
1996 }
1997
1998 /*
1999 * We are claiming the bridge_channel reference held by
2000 * bridge_channel_depart_thread().
2001 */
2002
2003 ast_bridge_channel_leave_bridge(bridge_channel,
2005
2006 /* Wait for the depart thread to die */
2007 ast_debug(1, "Waiting for %p(%s) bridge thread to die.\n",
2008 bridge_channel, ast_channel_name(bridge_channel->chan));
2009 pthread_join(bridge_channel->thread, NULL);
2010
2014
2015 /* We can get rid of the bridge_channel after the depart thread has died. */
2016 ao2_ref(bridge_channel, -1);
2017 return 0;
2018}
2019
2021{
2022 struct ast_bridge_channel *bridge_channel;
2023
2024 ast_debug(1, "Removing channel %s from bridge %s\n",
2026
2028
2029 /* Try to find the channel that we want to remove */
2030 if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
2032 return -1;
2033 }
2034
2035 ast_bridge_channel_leave_bridge(bridge_channel,
2037
2039
2040 return 0;
2041}
2042
2043static void kick_it(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
2044{
2046}
2047
2049{
2050 struct ast_bridge_channel *bridge_channel;
2051 int res;
2052
2054
2055 /* Try to find the channel that we want to kick. */
2056 if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
2058 return -1;
2059 }
2060
2061 res = ast_bridge_channel_queue_callback(bridge_channel, 0, kick_it, NULL, 0);
2062
2064
2065 return res;
2066}
2067
2068/*!
2069 * \internal
2070 * \brief Point the bridge_channel to a new bridge.
2071 * \since 12.0.0
2072 *
2073 * \param bridge_channel What is to point to a new bridge.
2074 * \param new_bridge Where the bridge channel should point.
2075 */
2076static void bridge_channel_change_bridge(struct ast_bridge_channel *bridge_channel, struct ast_bridge *new_bridge)
2077{
2078 struct ast_bridge *old_bridge;
2079
2080 ao2_ref(new_bridge, +1);
2081 ast_bridge_channel_lock(bridge_channel);
2082 ast_channel_lock(bridge_channel->chan);
2083 old_bridge = bridge_channel->bridge;
2084 bridge_channel->bridge = new_bridge;
2085 ast_channel_internal_bridge_set(bridge_channel->chan, new_bridge);
2086 ast_channel_unlock(bridge_channel->chan);
2087 ast_bridge_channel_unlock(bridge_channel);
2088 ao2_ref(old_bridge, -1);
2089}
2090
2091static void bridge_channel_moving(struct ast_bridge_channel *bridge_channel, struct ast_bridge *src, struct ast_bridge *dst)
2092{
2093 struct ast_bridge_features *features = bridge_channel->features;
2094 struct ast_bridge_hook *hook;
2095 struct ao2_iterator iter;
2096
2097 /* Run any moving hooks. */
2098 iter = ao2_iterator_init(features->other_hooks, 0);
2099 for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
2100 int remove_me;
2102
2103 if (hook->type != AST_BRIDGE_HOOK_TYPE_MOVE) {
2104 continue;
2105 }
2107 remove_me = move_cb(bridge_channel, hook->hook_pvt, src, dst);
2108 if (remove_me) {
2109 ast_debug(1, "Move detection hook %p is being removed from %p(%s)\n",
2110 hook, bridge_channel, ast_channel_name(bridge_channel->chan));
2111 ao2_unlink(features->other_hooks, hook);
2112 }
2113 }
2114 ao2_iterator_destroy(&iter);
2115}
2116
2117void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_bridge_channel **kick_me, unsigned int num_kick,
2118 unsigned int optimized)
2119{
2120 struct ast_bridge_channel *bridge_channel;
2121 unsigned int idx;
2122
2123 ast_debug(1, "Merging bridge %s into bridge %s\n",
2124 src_bridge->uniqueid, dst_bridge->uniqueid);
2125
2126 ast_bridge_publish_merge(dst_bridge, src_bridge);
2127
2128 /*
2129 * Move channels from src_bridge over to dst_bridge.
2130 *
2131 * We must use AST_LIST_TRAVERSE_SAFE_BEGIN() because
2132 * bridge_channel_internal_pull() alters the list we are traversing.
2133 */
2134 AST_LIST_TRAVERSE_SAFE_BEGIN(&src_bridge->channels, bridge_channel, entry) {
2135 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
2136 /*
2137 * The channel is already leaving let it leave normally because
2138 * pulling it may delete hooks that should run for this channel.
2139 */
2140 continue;
2141 }
2142 if (ast_test_flag(&bridge_channel->features->feature_flags,
2144 continue;
2145 }
2146
2147 if (kick_me) {
2148 for (idx = 0; idx < num_kick; ++idx) {
2149 if (bridge_channel == kick_me[idx]) {
2150 ast_bridge_channel_leave_bridge(bridge_channel,
2152 break;
2153 }
2154 }
2155 }
2156 bridge_channel_internal_pull(bridge_channel);
2157 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
2158 /*
2159 * The channel died as a result of being pulled or it was
2160 * kicked. Leave it pointing to the original bridge.
2161 */
2162 continue;
2163 }
2164
2165 bridge_channel_moving(bridge_channel, bridge_channel->bridge, dst_bridge);
2166
2167 /* Point to new bridge.*/
2168 bridge_channel_change_bridge(bridge_channel, dst_bridge);
2169
2170 if (bridge_channel_internal_push(bridge_channel)) {
2171 ast_bridge_features_remove(bridge_channel->features,
2173 ast_bridge_channel_leave_bridge(bridge_channel,
2175 }
2176 }
2178
2179 if (kick_me) {
2180 /*
2181 * Now we can kick any channels in the dst_bridge without
2182 * potentially dissolving the bridge.
2183 */
2184 for (idx = 0; idx < num_kick; ++idx) {
2185 bridge_channel = kick_me[idx];
2186 ast_bridge_channel_lock(bridge_channel);
2187 if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
2190 bridge_channel_internal_pull(bridge_channel);
2191 }
2192 ast_bridge_channel_unlock(bridge_channel);
2193 }
2194 }
2195
2196 bridge_reconfigured(dst_bridge, !optimized);
2197 bridge_reconfigured(src_bridge, !optimized);
2198
2199 ast_debug(1, "Merged bridge %s into bridge %s\n",
2200 src_bridge->uniqueid, dst_bridge->uniqueid);
2201}
2202
2204 /*! Destination merge bridge. */
2206 /*! Source merge bridge. */
2208};
2209
2210/*!
2211 * \internal
2212 * \brief Determine which bridge should merge into the other.
2213 * \since 12.0.0
2214 *
2215 * \param bridge1 A bridge for merging
2216 * \param bridge2 A bridge for merging
2217 *
2218 * \note The two bridges are assumed already locked.
2219 *
2220 * \return Which bridge merges into which or NULL bridges if cannot merge.
2221 */
2222static struct merge_direction bridge_merge_determine_direction(struct ast_bridge *bridge1, struct ast_bridge *bridge2)
2223{
2224 struct merge_direction merge = { NULL, NULL };
2225 int bridge1_priority;
2226 int bridge2_priority;
2227
2228 if (!ast_test_flag(&bridge1->feature_flags,
2230 && !ast_test_flag(&bridge2->feature_flags,
2232 /*
2233 * Can merge either way. Merge to the higher priority merge
2234 * bridge. Otherwise merge to the larger bridge.
2235 */
2236 bridge1_priority = bridge1->v_table->get_merge_priority(bridge1);
2237 bridge2_priority = bridge2->v_table->get_merge_priority(bridge2);
2238 if (bridge2_priority < bridge1_priority) {
2239 merge.dest = bridge1;
2240 merge.src = bridge2;
2241 } else if (bridge1_priority < bridge2_priority) {
2242 merge.dest = bridge2;
2243 merge.src = bridge1;
2244 } else {
2245 /* Merge to the larger bridge. */
2246 if (bridge2->num_channels <= bridge1->num_channels) {
2247 merge.dest = bridge1;
2248 merge.src = bridge2;
2249 } else {
2250 merge.dest = bridge2;
2251 merge.src = bridge1;
2252 }
2253 }
2254 } else if (!ast_test_flag(&bridge1->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
2255 && !ast_test_flag(&bridge2->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
2256 /* Can merge only one way. */
2257 merge.dest = bridge1;
2258 merge.src = bridge2;
2259 } else if (!ast_test_flag(&bridge2->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
2260 && !ast_test_flag(&bridge1->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
2261 /* Can merge only one way. */
2262 merge.dest = bridge2;
2263 merge.src = bridge1;
2264 }
2265
2266 return merge;
2267}
2268
2269/*!
2270 * \internal
2271 * \brief Merge two bridges together
2272 * \since 12.0.0
2273 *
2274 * \param dst_bridge Destination bridge of merge.
2275 * \param src_bridge Source bridge of merge.
2276 * \param merge_best_direction TRUE if don't care about which bridge merges into the other.
2277 * \param kick_me Array of channels to kick from the bridges.
2278 * \param num_kick Number of channels in the kick_me array.
2279 *
2280 * \note The dst_bridge and src_bridge are assumed already locked.
2281 *
2282 * \retval 0 on success
2283 * \retval -1 on failure
2284 */
2285static int bridge_merge_locked(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, int merge_best_direction, struct ast_channel **kick_me, unsigned int num_kick)
2286{
2287 struct merge_direction merge;
2288 struct ast_bridge_channel **kick_them = NULL;
2289
2290 /* Sanity check. */
2291 ast_assert(dst_bridge && src_bridge && dst_bridge != src_bridge && (!num_kick || kick_me));
2292
2293 if (dst_bridge->dissolved || src_bridge->dissolved) {
2294 ast_debug(1, "Can't merge bridges %s and %s, at least one bridge is dissolved.\n",
2295 src_bridge->uniqueid, dst_bridge->uniqueid);
2296 return -1;
2297 }
2300 ast_debug(1, "Can't merge bridges %s and %s, masquerade only.\n",
2301 src_bridge->uniqueid, dst_bridge->uniqueid);
2302 return -1;
2303 }
2304 if (dst_bridge->inhibit_merge || src_bridge->inhibit_merge) {
2305 ast_debug(1, "Can't merge bridges %s and %s, merging temporarily inhibited.\n",
2306 src_bridge->uniqueid, dst_bridge->uniqueid);
2307 return -1;
2308 }
2309
2310 if (merge_best_direction) {
2311 merge = bridge_merge_determine_direction(dst_bridge, src_bridge);
2312 } else {
2313 merge.dest = dst_bridge;
2314 merge.src = src_bridge;
2315 }
2316
2317 if (!merge.dest
2320 ast_debug(1, "Can't merge bridges %s and %s, merging inhibited.\n",
2321 src_bridge->uniqueid, dst_bridge->uniqueid);
2322 return -1;
2323 }
2324 if (merge.src->num_channels < 2) {
2325 /*
2326 * For a two party bridge, a channel may be temporarily removed
2327 * from the source bridge or the initial bridge members have not
2328 * joined yet.
2329 */
2330 ast_debug(1, "Can't merge bridge %s into bridge %s, not enough channels in source bridge.\n",
2331 merge.src->uniqueid, merge.dest->uniqueid);
2332 return -1;
2333 }
2334 if (2 + num_kick < merge.dest->num_channels + merge.src->num_channels
2338 ast_debug(1, "Can't merge bridge %s into bridge %s, multimix is needed and it cannot be acquired.\n",
2339 merge.src->uniqueid, merge.dest->uniqueid);
2340 return -1;
2341 }
2342
2343 if (num_kick) {
2344 unsigned int num_to_kick = 0;
2345 unsigned int idx;
2346
2347 kick_them = ast_alloca(num_kick * sizeof(*kick_them));
2348 for (idx = 0; idx < num_kick; ++idx) {
2349 kick_them[num_to_kick] = bridge_find_channel(merge.src, kick_me[idx]);
2350 if (!kick_them[num_to_kick]) {
2351 kick_them[num_to_kick] = bridge_find_channel(merge.dest, kick_me[idx]);
2352 }
2353 if (kick_them[num_to_kick]) {
2354 ++num_to_kick;
2355 }
2356 }
2357
2358 if (num_to_kick != num_kick) {
2359 ast_debug(1, "Can't merge bridge %s into bridge %s, at least one kicked channel is not in either bridge.\n",
2360 merge.src->uniqueid, merge.dest->uniqueid);
2361 return -1;
2362 }
2363 }
2364
2365 bridge_do_merge(merge.dest, merge.src, kick_them, num_kick, 0);
2366 return 0;
2367}
2368
2369int ast_bridge_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, int merge_best_direction, struct ast_channel **kick_me, unsigned int num_kick)
2370{
2371 int res;
2372
2373 /* Sanity check. */
2374 ast_assert(dst_bridge && src_bridge);
2375
2376 ast_bridge_lock_both(dst_bridge, src_bridge);
2377 res = bridge_merge_locked(dst_bridge, src_bridge, merge_best_direction, kick_me, num_kick);
2378 ast_bridge_unlock(src_bridge);
2379 ast_bridge_unlock(dst_bridge);
2380 return res;
2381}
2382
2383int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel, int attempt_recovery,
2384 unsigned int optimized)
2385{
2386 struct ast_bridge *orig_bridge;
2387 int was_in_bridge;
2388 int res = 0;
2389
2390 if (bridge_channel->swap) {
2391 ast_debug(1, "Moving %p(%s) into bridge %s swapping with %s\n",
2392 bridge_channel, ast_channel_name(bridge_channel->chan), dst_bridge->uniqueid,
2393 ast_channel_name(bridge_channel->swap));
2394 } else {
2395 ast_debug(1, "Moving %p(%s) into bridge %s\n",
2396 bridge_channel, ast_channel_name(bridge_channel->chan), dst_bridge->uniqueid);
2397 }
2398
2399 orig_bridge = bridge_channel->bridge;
2400 was_in_bridge = bridge_channel->in_bridge;
2401
2402 bridge_channel_internal_pull(bridge_channel);
2403 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
2404 /*
2405 * The channel died as a result of being pulled. Leave it
2406 * pointing to the original bridge.
2407 *
2408 * Clear out the swap channel pointer. A ref is not held
2409 * by bridge_channel->swap at this point.
2410 */
2411 bridge_channel->swap = NULL;
2412 bridge_reconfigured(orig_bridge, 0);
2413 return -1;
2414 }
2415
2416 /* Point to new bridge.*/
2417 ao2_ref(orig_bridge, +1);/* Keep a ref in case the push fails. */
2418 bridge_channel_change_bridge(bridge_channel, dst_bridge);
2419
2420 bridge_channel_moving(bridge_channel, orig_bridge, dst_bridge);
2421
2422 if (bridge_channel_internal_push_full(bridge_channel, optimized)) {
2423 /* Try to put the channel back into the original bridge. */
2424 ast_bridge_features_remove(bridge_channel->features,
2426 if (attempt_recovery && was_in_bridge) {
2427 /* Point back to original bridge. */
2428 bridge_channel_change_bridge(bridge_channel, orig_bridge);
2429
2430 if (bridge_channel_internal_push(bridge_channel)) {
2431 ast_bridge_features_remove(bridge_channel->features,
2433 ast_bridge_channel_leave_bridge(bridge_channel,
2435 }
2436 } else {
2437 ast_bridge_channel_leave_bridge(bridge_channel,
2439 bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
2440 }
2441 res = -1;
2442 } else if (!optimized) {
2443 bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
2444 }
2445
2446 bridge_reconfigured(dst_bridge, !optimized);
2447 bridge_reconfigured(orig_bridge, !optimized);
2448 ao2_ref(orig_bridge, -1);
2449 return res;
2450}
2451
2452/*!
2453 * \internal
2454 * \brief Move a channel from one bridge to another.
2455 * \since 12.0.0
2456 *
2457 * \param dst_bridge Destination bridge of bridge channel move.
2458 * \param src_bridge Source bridge of bridge channel move.
2459 * \param chan Channel to move.
2460 * \param swap Channel to replace in dst_bridge.
2461 * \param attempt_recovery TRUE if failure attempts to push channel back into original bridge.
2462 *
2463 * \note The dst_bridge and src_bridge are assumed already locked.
2464 *
2465 * \retval 0 on success.
2466 * \retval -1 on failure.
2467 */
2468static int bridge_move_locked(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_channel *chan, struct ast_channel *swap, int attempt_recovery)
2469{
2470 struct ast_bridge_channel *bridge_channel;
2471
2472 if (dst_bridge->dissolved || src_bridge->dissolved) {
2473 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, at least one bridge is dissolved.\n",
2474 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2475 return -1;
2476 }
2479 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, masquerade only.\n",
2480 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2481 return -1;
2482 }
2483 if (dst_bridge->inhibit_merge || src_bridge->inhibit_merge) {
2484 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, temporarily inhibited.\n",
2485 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2486 return -1;
2487 }
2488
2489 bridge_channel = bridge_find_channel(src_bridge, chan);
2490 if (!bridge_channel) {
2491 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel not in bridge.\n",
2492 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2493 return -1;
2494 }
2495 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
2496 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel leaving bridge.\n",
2497 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2498 return -1;
2499 }
2500 if (ast_test_flag(&bridge_channel->features->feature_flags,
2502 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel immovable.\n",
2503 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2504 return -1;
2505 }
2506
2507 if (swap) {
2508 struct ast_bridge_channel *bridge_channel_swap;
2509
2510 bridge_channel_swap = bridge_find_channel(dst_bridge, swap);
2511 if (!bridge_channel_swap) {
2512 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, swap channel %s not in bridge.\n",
2513 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid,
2515 return -1;
2516 }
2517 if (bridge_channel_swap->state != BRIDGE_CHANNEL_STATE_WAIT) {
2518 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, swap channel %s leaving bridge.\n",
2519 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid,
2521 return -1;
2522 }
2523 }
2524
2525 bridge_channel->swap = swap;
2526 return bridge_do_move(dst_bridge, bridge_channel, attempt_recovery, 0);
2527}
2528
2529int ast_bridge_move(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_channel *chan, struct ast_channel *swap, int attempt_recovery)
2530{
2531 int res;
2532
2533 ast_bridge_lock_both(dst_bridge, src_bridge);
2534 res = bridge_move_locked(dst_bridge, src_bridge, chan, swap, attempt_recovery);
2535 ast_bridge_unlock(src_bridge);
2536 ast_bridge_unlock(dst_bridge);
2537 return res;
2538}
2539
2541 struct ast_bridge_features *features, int play_tone, const char *xfersound)
2542{
2543 RAII_VAR(struct ast_bridge *, chan_bridge, NULL, ao2_cleanup);
2544 RAII_VAR(struct ast_channel *, yanked_chan, NULL, ao2_cleanup);
2545
2547
2549 chan_bridge = ast_channel_get_bridge(chan);
2551
2552 if (chan_bridge) {
2553 struct ast_bridge_channel *bridge_channel;
2554
2555 /* The channel is in a bridge so it is not getting any new features. */
2557
2558 ast_bridge_lock_both(bridge, chan_bridge);
2559 bridge_channel = bridge_find_channel(chan_bridge, chan);
2560
2561 if (bridge_move_locked(bridge, chan_bridge, chan, NULL, 1)) {
2562 ast_bridge_unlock(chan_bridge);
2564 return -1;
2565 }
2566
2567 /*
2568 * bridge_move_locked() will implicitly ensure that
2569 * bridge_channel is not NULL.
2570 */
2571 ast_assert(bridge_channel != NULL);
2572
2573 /*
2574 * Additional checks if the channel we just stole dissolves the
2575 * original bridge.
2576 */
2577 bridge_dissolve_check_stolen(chan_bridge, bridge_channel);
2578 ast_bridge_unlock(chan_bridge);
2580 } else {
2581 int noanswer;
2582 const char *value;
2583 /* Slightly less easy case. We need to yank channel A from
2584 * where he currently is and impart him into our bridge.
2585 */
2586 yanked_chan = ast_channel_yank(chan);
2587 if (!yanked_chan) {
2588 ast_log(LOG_WARNING, "Could not gain control of channel %s\n", ast_channel_name(chan));
2590 return -1;
2591 }
2592
2594 value = pbx_builtin_getvar_helper(chan, "BRIDGE_NOANSWER");
2595 noanswer = !ast_strlen_zero(value) ? 1 : 0;
2597 if (noanswer) {
2598 ast_debug(3, "Skipping answer on bridge target channel %s\n", ast_channel_name(chan));
2599 } else if (ast_channel_state(yanked_chan) != AST_STATE_UP) {
2600 ast_answer(yanked_chan);
2601 }
2602
2603 ast_channel_ref(yanked_chan);
2604 if (ast_bridge_impart(bridge, yanked_chan, NULL, features,
2606 /* It is possible for us to yank a channel and have some other
2607 * thread start a PBX on the channel after we yanked it. In particular,
2608 * this can theoretically happen on the ;2 of a Local channel if we
2609 * yank it prior to the ;1 being answered. Make sure that it isn't
2610 * executing a PBX before hanging it up.
2611 */
2612 if (ast_channel_pbx(yanked_chan)) {
2613 ast_channel_unref(yanked_chan);
2614 } else {
2615 ast_hangup(yanked_chan);
2616 }
2617 return -1;
2618 }
2619 }
2620
2621 if (play_tone && !ast_strlen_zero(xfersound)) {
2622 struct ast_channel *play_chan = yanked_chan ?: chan;
2623 RAII_VAR(struct ast_bridge_channel *, play_bridge_channel, NULL, ao2_cleanup);
2624
2625 ast_channel_lock(play_chan);
2626 play_bridge_channel = ast_channel_get_bridge_channel(play_chan);
2627 ast_channel_unlock(play_chan);
2628
2629 if (!play_bridge_channel) {
2630 ast_log(LOG_WARNING, "Unable to play tone for channel %s. No longer in a bridge.\n",
2631 ast_channel_name(play_chan));
2632 } else {
2633 ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, xfersound, NULL);
2634 }
2635 }
2636 return 0;
2637}
2638
2640{
2641 return !(bridge->inhibit_merge
2642 || bridge->dissolved
2644}
2645
2646/*!
2647 * \internal
2648 * \brief Lock the unreal channel stack for chan and prequalify it.
2649 * \since 12.0.0
2650 *
2651 * \param chan Unreal channel writing a frame into the channel driver.
2652 *
2653 * \note It is assumed that chan is already locked.
2654 *
2655 * \return bridge on success with bridge and bridge_channel locked.
2656 * \retval NULL if cannot do optimization now.
2657 */
2659{
2660 struct ast_bridge *bridge;
2661 struct ast_bridge_channel *bridge_channel;
2662
2664 return NULL;
2665 }
2667 return NULL;
2668 }
2670 /* Channel has an active monitor, audiohook, or framehook. */
2671 return NULL;
2672 }
2673 bridge_channel = ast_channel_internal_bridge_channel(chan);
2674 if (!bridge_channel || ast_bridge_channel_trylock(bridge_channel)) {
2675 return NULL;
2676 }
2677 bridge = bridge_channel->bridge;
2678 if (bridge_channel->activity != BRIDGE_CHANNEL_THREAD_SIMPLE
2679 || bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT
2681 ast_bridge_channel_unlock(bridge_channel);
2682 return NULL;
2683 }
2684 if (!bridge_channel_internal_allows_optimization(bridge_channel) ||
2687 ast_bridge_channel_unlock(bridge_channel);
2688 return NULL;
2689 }
2690 return bridge;
2691}
2692
2693/*!
2694 * \internal
2695 * \brief Lock the unreal channel stack for peer and prequalify it.
2696 * \since 12.0.0
2697 *
2698 * \param peer Other unreal channel in the pair.
2699 *
2700 * \return bridge on success with bridge, bridge_channel, and peer locked.
2701 * \retval NULL if cannot do optimization now.
2702 */
2704{
2705 struct ast_bridge *bridge;
2706 struct ast_bridge_channel *bridge_channel;
2707
2708 if (ast_channel_trylock(peer)) {
2709 return NULL;
2710 }
2711 if (!AST_LIST_EMPTY(ast_channel_readq(peer))) {
2712 ast_channel_unlock(peer);
2713 return NULL;
2714 }
2716 ast_channel_unlock(peer);
2717 return NULL;
2718 }
2720 /* Peer has an active monitor, audiohook, or framehook. */
2721 ast_channel_unlock(peer);
2722 return NULL;
2723 }
2724 bridge_channel = ast_channel_internal_bridge_channel(peer);
2725 if (!bridge_channel || ast_bridge_channel_trylock(bridge_channel)) {
2726 ast_channel_unlock(peer);
2727 return NULL;
2728 }
2729 bridge = bridge_channel->bridge;
2730 if (bridge_channel->activity != BRIDGE_CHANNEL_THREAD_IDLE
2731 || bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT
2733 ast_bridge_channel_unlock(bridge_channel);
2734 ast_channel_unlock(peer);
2735 return NULL;
2736 }
2740 ast_bridge_channel_unlock(bridge_channel);
2741 ast_channel_unlock(peer);
2742 return NULL;
2743 }
2744 return bridge;
2745}
2746
2747/*!
2748 * \internal
2749 * \brief Indicates allowability of a swap optimization
2750 */
2752 /*! Bridges cannot allow for a swap optimization to occur */
2754 /*! Bridge swap optimization can occur into the chan_bridge */
2756 /*! Bridge swap optimization can occur into the peer_bridge */
2758};
2759
2760/*!
2761 * \internal
2762 * \brief Determine if two bridges allow for swap optimization to occur
2763 *
2764 * \param chan_bridge First bridge being tested
2765 * \param peer_bridge Second bridge being tested
2766 * \return Allowability of swap optimization
2767 */
2769 struct ast_bridge *peer_bridge)
2770{
2771 int chan_priority;
2772 int peer_priority;
2773
2774 if (!ast_test_flag(&chan_bridge->feature_flags,
2777 && !ast_test_flag(&peer_bridge->feature_flags,
2780 /*
2781 * Can swap either way. Swap to the higher priority merge
2782 * bridge.
2783 */
2784 chan_priority = chan_bridge->v_table->get_merge_priority(chan_bridge);
2785 peer_priority = peer_bridge->v_table->get_merge_priority(peer_bridge);
2786 if (chan_bridge->num_channels == 2
2787 && chan_priority <= peer_priority) {
2788 return SWAP_TO_PEER_BRIDGE;
2789 } else if (peer_bridge->num_channels == 2
2790 && peer_priority <= chan_priority) {
2791 return SWAP_TO_CHAN_BRIDGE;
2792 }
2793 } else if (chan_bridge->num_channels == 2
2796 /* Can swap optimize only one way. */
2797 return SWAP_TO_PEER_BRIDGE;
2798 } else if (peer_bridge->num_channels == 2
2801 /* Can swap optimize only one way. */
2802 return SWAP_TO_CHAN_BRIDGE;
2803 }
2804
2805 return SWAP_PROHIBITED;
2806}
2807
2808/*!
2809 * \internal
2810 * \brief Check and attempt to swap optimize out the unreal channels.
2811 * \since 12.0.0
2812 *
2813 * \param chan_bridge
2814 * \param chan_bridge_channel
2815 * \param peer_bridge
2816 * \param peer_bridge_channel
2817 * \param pvt Unreal data containing callbacks to call if the optimization actually
2818 * happens
2819 *
2820 * \retval 1 if unreal channels failed to optimize out.
2821 * \retval 0 if unreal channels were not optimized out.
2822 * \retval -1 if unreal channels were optimized out.
2823 */
2824static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
2825 struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge,
2826 struct ast_bridge_channel *peer_bridge_channel,
2827 struct ast_unreal_pvt *pvt)
2828{
2829 struct ast_bridge *dst_bridge;
2830 struct ast_bridge_channel *dst_bridge_channel;
2831 struct ast_bridge_channel *src_bridge_channel;
2832 struct ast_bridge_channel *other;
2833 int res = 1;
2834
2835 switch (bridges_allow_swap_optimization(chan_bridge, peer_bridge)) {
2837 dst_bridge = chan_bridge;
2838 dst_bridge_channel = chan_bridge_channel;
2839 src_bridge_channel = peer_bridge_channel;
2840 break;
2842 dst_bridge = peer_bridge;
2843 dst_bridge_channel = peer_bridge_channel;
2844 src_bridge_channel = chan_bridge_channel;
2845 break;
2846 case SWAP_PROHIBITED:
2847 default:
2848 return 0;
2849 }
2850
2851 other = ast_bridge_channel_peer(src_bridge_channel);
2852 if (other && other->state == BRIDGE_CHANNEL_STATE_WAIT) {
2853 unsigned int id;
2854
2855 if (ast_channel_trylock(other->chan)) {
2856 return 1;
2857 }
2858
2859 id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
2860
2861 ast_verb(4, "Move-swap optimizing %s <-- %s.\n",
2862 ast_channel_name(dst_bridge_channel->chan),
2863 ast_channel_name(other->chan));
2864
2865 if (pvt && !ast_test_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN) && pvt->callbacks
2867 pvt->callbacks->optimization_started(pvt, other->chan,
2868 dst_bridge_channel->chan == pvt->owner ? AST_UNREAL_OWNER : AST_UNREAL_CHAN,
2869 id);
2871 }
2872 other->swap = dst_bridge_channel->chan;
2873 if (!bridge_do_move(dst_bridge, other, 1, 1)) {
2874 ast_bridge_channel_leave_bridge(src_bridge_channel,
2876 res = -1;
2877 }
2878 if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
2879 pvt->callbacks->optimization_finished(pvt, res == 1, id);
2880 }
2881 ast_channel_unlock(other->chan);
2882 }
2883 return res;
2884}
2885
2886/*!
2887 * \internal
2888 * \brief Indicates allowability of a merge optimization
2889 */
2891 /*! Bridge properties prohibit merge optimization */
2893 /*! Merge optimization cannot occur because the source bridge has too few channels */
2895 /*! Merge optimization cannot occur because multimix capability could not be requested */
2897 /*! Merge optimization allowed between bridges */
2899};
2900
2901/*!
2902 * \internal
2903 * \brief Determines allowability of a merge optimization
2904 *
2905 * \note The merge output parameter is undefined if MERGE_PROHIBITED is returned. For success
2906 * and other failure returns, a merge direction was determined, and the parameter is safe to
2907 * access.
2908 *
2909 * \param chan_bridge First bridge being tested
2910 * \param peer_bridge Second bridge being tested
2911 * \param num_kick_channels The number of channels to remove from the bridges during merging
2912 * \param[out] merge Indicates the recommended direction for the bridge merge
2913 */
2915 struct ast_bridge *peer_bridge, int num_kick_channels, struct merge_direction *merge)
2916{
2917 *merge = bridge_merge_determine_direction(chan_bridge, peer_bridge);
2918 if (!merge->dest) {
2919 return MERGE_PROHIBITED;
2920 }
2921 if (merge->src->num_channels < 2) {
2923 } else if ((2 + num_kick_channels) < merge->dest->num_channels + merge->src->num_channels
2927 return MERGE_NO_MULTIMIX;
2928 }
2929
2930 return MERGE_ALLOWED;
2931}
2932
2933/*!
2934 * \internal
2935 * \brief Check and attempt to merge optimize out the unreal channels.
2936 * \since 12.0.0
2937 *
2938 * \param chan_bridge
2939 * \param chan_bridge_channel
2940 * \param peer_bridge
2941 * \param peer_bridge_channel
2942 * \param pvt Unreal data containing callbacks to call if the optimization actually
2943 * happens
2944 *
2945 * \retval 0 if unreal channels were not optimized out.
2946 * \retval -1 if unreal channels were optimized out.
2947 */
2948static int try_merge_optimize_out(struct ast_bridge *chan_bridge,
2949 struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge,
2950 struct ast_bridge_channel *peer_bridge_channel,
2951 struct ast_unreal_pvt *pvt)
2952{
2953 struct merge_direction merge;
2954 struct ast_bridge_channel *kick_me[] = {
2955 chan_bridge_channel,
2956 peer_bridge_channel,
2957 };
2958 unsigned int id;
2959
2960 switch (bridges_allow_merge_optimization(chan_bridge, peer_bridge, ARRAY_LEN(kick_me), &merge)) {
2961 case MERGE_ALLOWED:
2962 break;
2963 case MERGE_PROHIBITED:
2964 return 0;
2966 ast_debug(4, "Can't optimize %s -- %s out, not enough channels in bridge %s.\n",
2967 ast_channel_name(chan_bridge_channel->chan),
2968 ast_channel_name(peer_bridge_channel->chan),
2969 merge.src->uniqueid);
2970 return 0;
2971 case MERGE_NO_MULTIMIX:
2972 ast_debug(4, "Can't optimize %s -- %s out, multimix is needed and it cannot be acquired.\n",
2973 ast_channel_name(chan_bridge_channel->chan),
2974 ast_channel_name(peer_bridge_channel->chan));
2975 return 0;
2976 }
2977
2978 ast_verb(4, "Merge optimizing %s -- %s out.\n",
2979 ast_channel_name(chan_bridge_channel->chan),
2980 ast_channel_name(peer_bridge_channel->chan));
2981
2982 id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
2983
2984 if (pvt && !ast_test_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN) && pvt->callbacks
2988 id);
2990 }
2991 bridge_do_merge(merge.dest, merge.src, kick_me, ARRAY_LEN(kick_me), 1);
2992 if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
2993 pvt->callbacks->optimization_finished(pvt, 1, id);
2994 }
2995
2996 return -1;
2997}
2998
3000{
3001 struct ast_bridge *chan_bridge;
3002 struct ast_bridge *peer_bridge;
3003 struct ast_bridge_channel *chan_bridge_channel;
3004 struct ast_bridge_channel *peer_bridge_channel;
3005 int res = 0;
3006
3007 chan_bridge = optimize_lock_chan_stack(chan);
3008 if (!chan_bridge) {
3009 return res;
3010 }
3011 chan_bridge_channel = ast_channel_internal_bridge_channel(chan);
3012
3013 peer_bridge = optimize_lock_peer_stack(peer);
3014 if (peer_bridge) {
3015 peer_bridge_channel = ast_channel_internal_bridge_channel(peer);
3016
3017 res = try_swap_optimize_out(chan_bridge, chan_bridge_channel,
3018 peer_bridge, peer_bridge_channel, pvt);
3019 if (!res) {
3020 res = try_merge_optimize_out(chan_bridge, chan_bridge_channel,
3021 peer_bridge, peer_bridge_channel, pvt);
3022 } else if (0 < res) {
3023 res = 0;
3024 }
3025
3026 /* Release peer locks. */
3027 ast_bridge_unlock(peer_bridge);
3028 ast_bridge_channel_unlock(peer_bridge_channel);
3029 ast_channel_unlock(peer);
3030 }
3031
3032 /* Release chan locks. */
3033 ast_bridge_unlock(chan_bridge);
3034 ast_bridge_channel_unlock(chan_bridge_channel);
3035
3036 return res;
3037}
3038
3040 struct ast_bridge *peer_bridge)
3041{
3042 struct merge_direction merge;
3043
3044 if (!bridge_allows_optimization(chan_bridge) || !bridge_allows_optimization(peer_bridge)) {
3046 }
3047
3048 switch (bridges_allow_swap_optimization(chan_bridge, peer_bridge)) {
3053 case SWAP_PROHIBITED:
3054 default:
3055 break;
3056 }
3057
3058 /* Two channels will be kicked from the bridges, the unreal;1 and unreal;2 channels */
3059 if (bridges_allow_merge_optimization(chan_bridge, peer_bridge, 2, &merge) != MERGE_ALLOWED) {
3061 }
3062
3063 if (merge.dest == chan_bridge) {
3065 } else {
3067 }
3068}
3069
3071{
3072 int new_request;
3073
3074 new_request = bridge->inhibit_merge + request;
3075 ast_assert(0 <= new_request);
3076 bridge->inhibit_merge = new_request;
3077}
3078
3080{
3081 ast_bridge_lock(bridge);
3083 ast_bridge_unlock(bridge);
3084}
3085
3086int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan)
3087{
3088 struct ast_bridge_channel *bridge_channel;
3089/* XXX ASTERISK-21271 the case of a dissolved bridge while channel is suspended is not handled. */
3090/* XXX ASTERISK-21271 suspend/unsuspend needs to be rethought. The caller must block until it has successfully suspended the channel for temporary control. */
3091/* XXX ASTERISK-21271 external suspend/unsuspend needs to be eliminated. The channel may be playing a file at the time and stealing it then is not good. */
3092
3094
3095 if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
3097 return -1;
3098 }
3099
3101
3103
3104 return 0;
3105}
3106
3108{
3109 struct ast_bridge_channel *bridge_channel;
3110/* XXX ASTERISK-21271 the case of a dissolved bridge while channel is suspended is not handled. */
3111
3113
3114 if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
3116 return -1;
3117 }
3118
3120
3122
3123 return 0;
3124}
3125
3127{
3128 technology->suspended = 1;
3129}
3130
3132{
3133 /*
3134 * XXX We may want the act of unsuspending a bridge technology
3135 * to prod all existing bridges to see if they should start
3136 * using it.
3137 */
3138 technology->suspended = 0;
3139}
3140
3142{
3143 if (ARRAY_LEN(builtin_features_handlers) <= feature
3144 || builtin_features_handlers[feature]) {
3145 return -1;
3146 }
3147
3148 if (!ast_strlen_zero(dtmf)) {
3149 ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature]));
3150 }
3151
3153
3154 return 0;
3155}
3156
3158{
3159 if (ARRAY_LEN(builtin_features_handlers) <= feature
3160 || !builtin_features_handlers[feature]) {
3161 return -1;
3162 }
3163
3165
3166 return 0;
3167}
3168
3169int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
3170{
3172
3173 if (ARRAY_LEN(builtin_features_handlers) <= feature) {
3174 return -1;
3175 }
3176
3178 if (!callback) {
3179 return -1;
3180 }
3181 callback(bridge_channel, hook_pvt);
3182
3183 return 0;
3184}
3185
3187{
3188 if (ARRAY_LEN(builtin_interval_handlers) <= interval
3189 || builtin_interval_handlers[interval]) {
3190 return -1;
3191 }
3192
3194
3195 return 0;
3196}
3197
3199{
3200 if (ARRAY_LEN(builtin_interval_handlers) <= interval
3201 || !builtin_interval_handlers[interval]) {
3202 return -1;
3203 }
3204
3205 builtin_interval_handlers[interval] = NULL;
3206
3207 return 0;
3208
3209}
3210
3211/*!
3212 * \internal
3213 * \brief Bridge hook destructor.
3214 * \since 12.0.0
3215 *
3216 * \param vhook Object to destroy.
3217 */
3218static void bridge_hook_destroy(void *vhook)
3219{
3220 struct ast_bridge_hook *hook = vhook;
3221
3222 if (hook->destructor) {
3223 hook->destructor(hook->hook_pvt);
3224 }
3225}
3226
3227/*!
3228 * \internal
3229 * \brief Allocate and setup a generic bridge hook.
3230 * \since 12.0.0
3231 *
3232 * \param size How big an object to allocate.
3233 * \param callback Function to execute upon activation
3234 * \param hook_pvt Unique data
3235 * \param destructor Optional destructor callback for hook_pvt data
3236 * \param remove_flags Dictates what situations the hook should be removed.
3237 *
3238 * \return hook on success.
3239 * \retval NULL on error.
3240 */
3241static struct ast_bridge_hook *bridge_hook_generic(size_t size,
3243 void *hook_pvt,
3246{
3247 struct ast_bridge_hook *hook;
3248
3249 /* Allocate new hook and setup it's basic variables */
3251 if (hook) {
3252 hook->callback = callback;
3253 hook->destructor = destructor;
3254 hook->hook_pvt = hook_pvt;
3256 }
3257
3258 return hook;
3259}
3260
3262 const char *dtmf,
3264 void *hook_pvt,
3267{
3268 struct ast_bridge_hook_dtmf *hook;
3269 int res;
3270
3271 /* Allocate new hook and setup it's various variables */
3272 hook = (struct ast_bridge_hook_dtmf *) bridge_hook_generic(sizeof(*hook), callback,
3273 hook_pvt, destructor, remove_flags);
3274 if (!hook) {
3275 return -1;
3276 }
3278 ast_copy_string(hook->dtmf.code, dtmf, sizeof(hook->dtmf.code));
3279
3280 /* Once done we put it in the container. */
3281 res = ao2_link(features->dtmf_hooks, hook) ? 0 : -1;
3282 if (res) {
3283 /*
3284 * Could not link the hook into the container.
3285 *
3286 * Remove the hook_pvt destructor call from the hook since we
3287 * are returning failure to install the hook.
3288 */
3289 hook->generic.destructor = NULL;
3290 }
3291 ao2_ref(hook, -1);
3292
3293 return res;
3294}
3295
3296/*!
3297 * \internal
3298 * \brief Attach an other hook to a bridge features structure
3299 *
3300 * \param features Bridge features structure
3301 * \param callback Function to execute upon activation
3302 * \param hook_pvt Unique data
3303 * \param destructor Optional destructor callback for hook_pvt data
3304 * \param remove_flags Dictates what situations the hook should be removed.
3305 * \param type What type of hook is being attached.
3306 *
3307 * \retval 0 on success
3308 * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
3309 */
3310static int bridge_other_hook(struct ast_bridge_features *features,
3312 void *hook_pvt,
3314 enum ast_bridge_hook_remove_flags remove_flags,
3316{
3317 struct ast_bridge_hook *hook;
3318 int res;
3319
3320 /* Allocate new hook and setup it's various variables */
3321 hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor,
3322 remove_flags);
3323 if (!hook) {
3324 return -1;
3325 }
3326 hook->type = type;
3327
3328 /* Once done we put it in the container. */
3329 res = ao2_link(features->other_hooks, hook) ? 0 : -1;
3330 if (res) {
3331 /*
3332 * Could not link the hook into the container.
3333 *
3334 * Remove the hook_pvt destructor call from the hook since we
3335 * are returning failure to install the hook.
3336 */
3337 hook->destructor = NULL;
3338 }
3339 ao2_ref(hook, -1);
3340
3341 return res;
3342}
3343
3346 void *hook_pvt,
3349{
3352}
3353
3356 void *hook_pvt,
3359{
3362}
3363
3366 void *hook_pvt,
3369{
3372}
3373
3376 void *hook_pvt,
3379{
3381
3384}
3385
3388 void *hook_pvt,
3391{
3393
3396}
3397
3400 unsigned int interval,
3402 void *hook_pvt,
3405{
3406 struct ast_bridge_hook_timer *hook;
3407 int res;
3408
3409 if (!features ||!interval || !callback) {
3410 return -1;
3411 }
3412
3413 /* Allocate new hook and setup it's various variables */
3414 hook = (struct ast_bridge_hook_timer *) bridge_hook_generic(sizeof(*hook), callback,
3415 hook_pvt, destructor, remove_flags);
3416 if (!hook) {
3417 return -1;
3418 }
3420 hook->timer.interval = interval;
3421 hook->timer.trip_time = ast_tvadd(ast_tvnow(), ast_samp2tv(interval, 1000));
3422 hook->timer.seqno = ast_atomic_fetchadd_int((int *) &features->interval_sequence, +1);
3423 hook->timer.flags = flags;
3424
3425 ast_debug(1, "Putting interval hook %p with interval %u in the heap on features %p\n",
3426 hook, hook->timer.interval, features);
3428 res = ast_heap_push(features->interval_hooks, hook);
3430 if (res) {
3431 /*
3432 * Could not push the hook into the heap
3433 *
3434 * Remove the hook_pvt destructor call from the hook since we
3435 * are returning failure to install the hook.
3436 */
3437 hook->generic.destructor = NULL;
3438 ao2_ref(hook, -1);
3439 }
3440
3441 return res ? -1 : 0;
3442}
3443
3445 enum ast_bridge_builtin_feature feature,
3446 const char *dtmf,
3447 void *config,
3449 enum ast_bridge_hook_remove_flags remove_flags)
3450{
3451 if (ARRAY_LEN(builtin_features_handlers) <= feature
3452 || !builtin_features_handlers[feature]) {
3453 return -1;
3454 }
3455
3456 /* If no alternate DTMF stream was provided use the default one */
3457 if (ast_strlen_zero(dtmf)) {
3458 dtmf = builtin_features_dtmf[feature];
3459 /* If no DTMF is still available (ie: it has been disabled) then error out now */
3460 if (ast_strlen_zero(dtmf)) {
3461 ast_debug(1, "Failed to enable built in feature %u on %p, no DTMF string is available for it.\n",
3462 feature, features);
3463 return -1;
3464 }
3465 }
3466
3467 /*
3468 * The rest is basically pretty easy. We create another hook
3469 * using the built in feature's DTMF callback. Easy as pie.
3470 */
3471 return ast_bridge_dtmf_hook(features, dtmf, builtin_features_handlers[feature],
3472 config, destructor, remove_flags);
3473}
3474
3476{
3477 memset(limits, 0, sizeof(*limits));
3478
3479 if (ast_string_field_init(limits, 256)) {
3480 return -1;
3481 }
3482
3483 return 0;
3484}
3485
3487{
3489}
3490
3493 enum ast_bridge_hook_remove_flags remove_flags)
3494{
3497
3499 return callback(features, limits, remove_flags);
3500 }
3501
3502 ast_log(LOG_ERROR, "Attempted to set limits without an AST_BRIDGE_BUILTIN_INTERVAL_LIMITS callback registered.\n");
3503 return -1;
3504}
3505
3506void ast_bridge_features_set_flag(struct ast_bridge_features *features, unsigned int flag)
3507{
3508 ast_set_flag(&features->feature_flags, flag);
3509 features->usable = 1;
3510}
3511
3512/*!
3513 * \internal
3514 * \brief ao2 object match hooks with appropriate remove_flags.
3515 * \since 12.0.0
3516 *
3517 * \param obj Feature hook object.
3518 * \param arg Removal flags
3519 * \param flags Not used
3520 *
3521 * \retval CMP_MATCH if hook's remove_flags match the removal flags set.
3522 * \retval 0 if not match.
3523 */
3524static int hook_remove_match(void *obj, void *arg, int flags)
3525{
3526 struct ast_bridge_hook *hook = obj;
3528
3529 if (ast_test_flag(&hook->remove_flags, *remove_flags)) {
3530 return CMP_MATCH;
3531 } else {
3532 return 0;
3533 }
3534}
3535
3536/*!
3537 * \internal
3538 * \brief Remove all hooks with appropriate remove_flags in the container.
3539 * \since 12.0.0
3540 *
3541 * \param hooks Hooks container to work on.
3542 * \param remove_flags Determinator for whether hook is removed
3543 */
3545{
3548}
3549
3550/*!
3551 * \internal
3552 * \brief Remove all hooks in the heap with appropriate remove_flags set.
3553 * \since 12.0.0
3554 *
3555 * \param hooks Hooks heap to work on.
3556 * \param remove_flags Determinator for whether hook is removed
3557 */
3559{
3560 struct ast_bridge_hook *hook;
3561 int changed;
3562
3563 ast_heap_wrlock(hooks);
3564 do {
3565 int idx;
3566
3567 changed = 0;
3568 for (idx = ast_heap_size(hooks); idx; --idx) {
3569 hook = ast_heap_peek(hooks, idx);
3571 ast_heap_remove(hooks, hook);
3572 ao2_ref(hook, -1);
3573 changed = 1;
3574 }
3575 }
3576 } while (changed);
3577 ast_heap_unlock(hooks);
3578}
3579
3581{
3585}
3586
3587static int interval_hook_time_cmp(void *a, void *b)
3588{
3589 struct ast_bridge_hook_timer *hook_a = a;
3590 struct ast_bridge_hook_timer *hook_b = b;
3591 int cmp;
3592
3593 cmp = ast_tvcmp(hook_b->timer.trip_time, hook_a->timer.trip_time);
3594 if (cmp) {
3595 return cmp;
3596 }
3597
3598 cmp = hook_b->timer.seqno - hook_a->timer.seqno;
3599 return cmp;
3600}
3601
3602/*!
3603 * \internal
3604 * \brief DTMF hook container sort comparison function.
3605 * \since 12.0.0
3606 *
3607 * \param obj_left pointer to the (user-defined part) of an object.
3608 * \param obj_right pointer to the (user-defined part) of an object.
3609 * \param flags flags from ao2_callback()
3610 * OBJ_POINTER - if set, 'obj_right', is an object.
3611 * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
3612 * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
3613 *
3614 * \retval <0 if obj_left < obj_right
3615 * \retval =0 if obj_left == obj_right
3616 * \retval >0 if obj_left > obj_right
3617 */
3618static int bridge_dtmf_hook_sort(const void *obj_left, const void *obj_right, int flags)
3619{
3620 const struct ast_bridge_hook_dtmf *hook_left = obj_left;
3621 const struct ast_bridge_hook_dtmf *hook_right = obj_right;
3622 const char *right_key = obj_right;
3623 int cmp;
3624
3625 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
3626 default:
3627 case OBJ_POINTER:
3628 right_key = hook_right->dtmf.code;
3629 /* Fall through */
3630 case OBJ_KEY:
3631 cmp = strcasecmp(hook_left->dtmf.code, right_key);
3632 break;
3633 case OBJ_PARTIAL_KEY:
3634 cmp = strncasecmp(hook_left->dtmf.code, right_key, strlen(right_key));
3635 break;
3636 }
3637 return cmp;
3638}
3639
3640/*! \brief Callback for merging hook ao2_containers */
3641static int merge_container_cb(void *obj, void *data, int flags)
3642{
3643 ao2_link(data, obj);
3644 return 0;
3645}
3646
3647/*! \brief Wrapper for interval hooks that calls into the wrapped hook */
3648static int interval_wrapper_cb(struct ast_bridge_channel *bridge_channel, void *obj)
3649{
3650 struct ast_bridge_hook_timer *hook = obj;
3651
3652 return hook->generic.callback(bridge_channel, hook->generic.hook_pvt);
3653}
3654
3655/*! \brief Destructor for the hook wrapper */
3656static void interval_wrapper_pvt_dtor(void *obj)
3657{
3658 ao2_cleanup(obj);
3659}
3660
3661/*! \brief Wrap the provided interval hook and add it to features */
3662static void wrap_hook(struct ast_bridge_features *features, struct ast_bridge_hook_timer *hook)
3663{
3664 /* Break out of the current wrapper if it exists to avoid multiple layers */
3665 if (hook->generic.callback == interval_wrapper_cb) {
3666 hook = hook->generic.hook_pvt;
3667 }
3668
3669 ast_bridge_interval_hook(features, hook->timer.flags, hook->timer.interval,
3671 hook->generic.remove_flags.flags);
3672}
3673
3675{
3676 struct ast_bridge_hook_timer *hook;
3677 int idx;
3678
3679 /* Merge hook containers */
3682
3683 /* Merge hook heaps */
3685 for (idx = 1; (hook = ast_heap_peek(from->interval_hooks, idx)); idx++) {
3686 wrap_hook(into, hook);
3687 }
3689
3690 /* Merge feature flags */
3691 into->feature_flags.flags |= from->feature_flags.flags;
3692 into->usable |= from->usable;
3693
3694 into->mute |= from->mute;
3695 into->dtmf_passthrough |= from->dtmf_passthrough;
3696}
3697
3698/* XXX ASTERISK-21271 make ast_bridge_features_init() static when make ast_bridge_join() requires features to be allocated. */
3700{
3701 /* Zero out the structure */
3702 memset(features, 0, sizeof(*features));
3703
3704 /* Initialize the DTMF hooks container */
3707 if (!features->dtmf_hooks) {
3708 return -1;
3709 }
3710
3711 /* Initialize the miscellaneous other hooks container */
3713 NULL);
3714 if (!features->other_hooks) {
3715 return -1;
3716 }
3717
3718 /* Initialize the interval hooks heap */
3720 offsetof(struct ast_bridge_hook_timer, timer.heap_index));
3721 if (!features->interval_hooks) {
3722 return -1;
3723 }
3724
3725 features->dtmf_passthrough = 1;
3726 features->text_messaging = 1;
3727
3728 return 0;
3729}
3730
3731/* XXX ASTERISK-21271 make ast_bridge_features_cleanup() static when make ast_bridge_join() requires features to be allocated. */
3733{
3734 struct ast_bridge_hook_timer *hook;
3735
3736 /* Destroy the interval hooks heap. */
3737 if (features->interval_hooks) {
3738 while ((hook = ast_heap_pop(features->interval_hooks))) {
3739 ao2_ref(hook, -1);
3740 }
3741 features->interval_hooks = ast_heap_destroy(features->interval_hooks);
3742 }
3743
3744 /* Destroy the miscellaneous other hooks container. */
3745 ao2_cleanup(features->other_hooks);
3746 features->other_hooks = NULL;
3747
3748 /* Destroy the DTMF hooks container. */
3749 ao2_cleanup(features->dtmf_hooks);
3750 features->dtmf_hooks = NULL;
3751}
3752
3754{
3755 if (!features) {
3756 return;
3757 }
3759 ast_free(features);
3760}
3761
3763{
3764 struct ast_bridge_features *features;
3765
3766 features = ast_malloc(sizeof(*features));
3767 if (features) {
3768 if (ast_bridge_features_init(features)) {
3770 features = NULL;
3771 }
3772 }
3773
3774 return features;
3775}
3776
3777void ast_bridge_set_mixing_interval(struct ast_bridge *bridge, unsigned int mixing_interval)
3778{
3779 ast_bridge_lock(bridge);
3780 bridge->softmix.internal_mixing_interval = mixing_interval;
3781 ast_bridge_unlock(bridge);
3782}
3783
3784void ast_bridge_set_binaural_active(struct ast_bridge *bridge, unsigned int binaural_active)
3785{
3786 ast_bridge_lock(bridge);
3787 bridge->softmix.binaural_active = binaural_active;
3788 ast_bridge_unlock(bridge);
3789}
3790
3791void ast_bridge_set_internal_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
3792{
3793 ast_bridge_lock(bridge);
3794 bridge->softmix.internal_sample_rate = sample_rate;
3795 ast_bridge_unlock(bridge);
3796}
3797
3798void ast_bridge_set_maximum_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
3799{
3800 ast_bridge_lock(bridge);
3801 bridge->softmix.maximum_sample_rate = sample_rate;
3802 ast_bridge_unlock(bridge);
3803}
3804
3805static void cleanup_video_mode(struct ast_bridge *bridge)
3806{
3807 switch (bridge->softmix.video_mode.mode) {
3809 break;
3813 }
3814 break;
3818 }
3821 }
3823 break;
3824 }
3825 memset(&bridge->softmix.video_mode, 0, sizeof(bridge->softmix.video_mode));
3826}
3827
3828void ast_bridge_set_single_src_video_mode(struct ast_bridge *bridge, struct ast_channel *video_src_chan)
3829{
3830 ast_bridge_lock(bridge);
3831 cleanup_video_mode(bridge);
3833 if (video_src_chan) {
3835 ast_verb(5, "Video source in bridge '%s' (%s) is now '%s' (%s)\n",
3836 bridge->name, bridge->uniqueid,
3837 ast_channel_name(video_src_chan),
3838 ast_channel_uniqueid(video_src_chan));
3839 ast_indicate(video_src_chan, AST_CONTROL_VIDUPDATE);
3840 }
3842 ast_bridge_unlock(bridge);
3843}
3844
3846{
3847 ast_bridge_lock(bridge);
3848 cleanup_video_mode(bridge);
3850 ast_bridge_unlock(bridge);
3851}
3852
3854{
3855 ast_bridge_lock(bridge);
3856 cleanup_video_mode(bridge);
3858 ast_bridge_unlock(bridge);
3859}
3860
3861void ast_bridge_set_video_update_discard(struct ast_bridge *bridge, unsigned int video_update_discard)
3862{
3863 ast_bridge_lock(bridge);
3864 bridge->softmix.video_mode.video_update_discard = video_update_discard;
3865 ast_bridge_unlock(bridge);
3866}
3867
3868void ast_bridge_set_remb_send_interval(struct ast_bridge *bridge, unsigned int remb_send_interval)
3869{
3871
3872 ast_bridge_lock(bridge);
3873 bridge->softmix.video_mode.mode_data.sfu_data.remb_send_interval = remb_send_interval;
3874 ast_bridge_unlock(bridge);
3875}
3876
3878{
3880
3881 ast_bridge_lock(bridge);
3883 ast_bridge_unlock(bridge);
3884}
3885
3886void ast_bridge_set_remb_estimated_bitrate(struct ast_bridge *bridge, float estimated_bitrate)
3887{
3889
3890 ast_bridge_lock(bridge);
3891 bridge->softmix.video_mode.mode_data.sfu_data.estimated_bitrate = estimated_bitrate;
3892 ast_bridge_unlock(bridge);
3893}
3894
3895void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyframe)
3896{
3898
3899 /* If the channel doesn't support video, we don't care about it */
3901 return;
3902 }
3903
3904 ast_bridge_lock(bridge);
3906
3907 if (data->chan_vsrc == chan) {
3908 data->average_talking_energy = talker_energy;
3909 } else if ((data->average_talking_energy < talker_energy) && is_keyframe) {
3910 if (data->chan_old_vsrc) {
3912 }
3913 if (data->chan_vsrc) {
3914 data->chan_old_vsrc = data->chan_vsrc;
3916 }
3917 data->chan_vsrc = ast_channel_ref(chan);
3918 data->average_talking_energy = talker_energy;
3919 ast_verb(5, "Video source in bridge '%s' (%s) is now '%s' (%s)\n",
3920 bridge->name, bridge->uniqueid,
3925 } else if ((data->average_talking_energy < talker_energy) && !is_keyframe) {
3927 } else if (!data->chan_vsrc && is_keyframe) {
3928 data->chan_vsrc = ast_channel_ref(chan);
3929 data->average_talking_energy = talker_energy;
3930 ast_verb(5, "Video source in bridge '%s' (%s) is now '%s' (%s)\n",
3931 bridge->name, bridge->uniqueid,
3936 } else if (!data->chan_old_vsrc && is_keyframe) {
3937 data->chan_old_vsrc = ast_channel_ref(chan);
3939 }
3940 ast_bridge_unlock(bridge);
3941}
3942
3944{
3945 int res = 0;
3946
3947 ast_bridge_lock(bridge);
3948 switch (bridge->softmix.video_mode.mode) {
3950 break;
3953 res = 1;
3954 }
3955 break;
3958 res++;
3959 }
3961 res++;
3962 }
3964 break;
3965 }
3966 ast_bridge_unlock(bridge);
3967 return res;
3968}
3969
3970int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
3971{
3972 int res = 0;
3973
3974 ast_bridge_lock(bridge);
3975 switch (bridge->softmix.video_mode.mode) {
3977 break;
3980 res = 1;
3981 }
3982 break;
3985 res = 1;
3986 } else if (bridge->softmix.video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
3987 res = 2;
3988 }
3990 break;
3991 }
3992 ast_bridge_unlock(bridge);
3993 return res;
3994}
3995
3996void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
3997{
3998 ast_bridge_lock(bridge);
3999 switch (bridge->softmix.video_mode.mode) {
4001 break;
4006 }
4008 }
4009 break;
4014 }
4017 }
4021 }
4023 }
4025 break;
4026 }
4027 ast_bridge_unlock(bridge);
4028}
4029
4031{
4032 switch (video_mode) {
4034 return "talker";
4036 return "single";
4038 return "sfu";
4040 default:
4041 return "none";
4042 }
4043}
4044
4045void ast_bridge_set_send_sdp_label(struct ast_bridge *bridge, unsigned int send_sdp_label)
4046{
4047 ast_bridge_lock(bridge);
4048 bridge->softmix.send_sdp_label = send_sdp_label;
4049 ast_bridge_unlock(bridge);
4050}
4051
4052static int channel_hash(const void *obj, int flags)
4053{
4054 const struct ast_channel *chan = obj;
4055 const char *name = obj;
4056 int hash;
4057
4058 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
4059 default:
4060 case OBJ_POINTER:
4061 name = ast_channel_name(chan);
4062 /* Fall through */
4063 case OBJ_KEY:
4064 hash = ast_str_hash(name);
4065 break;
4066 case OBJ_PARTIAL_KEY:
4067 /* Should never happen in hash callback. */
4068 ast_assert(0);
4069 hash = 0;
4070 break;
4071 }
4072 return hash;
4073}
4074
4075static int channel_cmp(void *obj, void *arg, int flags)
4076{
4077 const struct ast_channel *left = obj;
4078 const struct ast_channel *right = arg;
4079 const char *right_name = arg;
4080 int cmp;
4081
4082 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
4083 default:
4084 case OBJ_POINTER:
4085 right_name = ast_channel_name(right);
4086 /* Fall through */
4087 case OBJ_KEY:
4088 cmp = strcmp(ast_channel_name(left), right_name);
4089 break;
4090 case OBJ_PARTIAL_KEY:
4091 cmp = strncmp(ast_channel_name(left), right_name, strlen(right_name));
4092 break;
4093 }
4094 return cmp ? 0 : CMP_MATCH;
4095}
4096
4098{
4099 struct ao2_container *channels;
4100 struct ast_bridge_channel *iter;
4101
4104 if (!channels) {
4105 return NULL;
4106 }
4107
4109 ao2_link(channels, iter->chan);
4110 }
4111
4112 return channels;
4113}
4114
4116{
4117 struct ao2_container *channels;
4118
4119 ast_bridge_lock(bridge);
4121 ast_bridge_unlock(bridge);
4122
4123 return channels;
4124}
4125
4127{
4128 struct ast_channel *peer = NULL;
4129 struct ast_bridge_channel *iter;
4130
4131 /* Asking for the peer channel only makes sense on a two-party bridge. */
4132 if (bridge->num_channels == 2
4135 int in_bridge = 0;
4136
4138 if (iter->chan != chan) {
4139 peer = iter->chan;
4140 } else {
4141 in_bridge = 1;
4142 }
4143 }
4144 if (in_bridge && peer) {
4145 ast_channel_ref(peer);
4146 } else {
4147 peer = NULL;
4148 }
4149 }
4150
4151 return peer;
4152}
4153
4155{
4156 struct ast_channel *peer;
4157
4159 peer = ast_bridge_peer_nolock(bridge, chan);
4161
4162 return peer;
4163}
4164
4165/*!
4166 * \internal
4167 * \brief Transfer an entire bridge to a specific destination.
4168 *
4169 * This creates a local channel to dial out and swaps the called local channel
4170 * with the transferer channel. By doing so, all participants in the bridge are
4171 * connected to the specified destination.
4172 *
4173 * While this means of transferring would work for both two-party and multi-party
4174 * bridges, this method is only used for multi-party bridges since this method would
4175 * be less efficient for two-party bridges.
4176 *
4177 * \param is_external Whether the transfer is externally initiated
4178 * \param transferer The channel performing a transfer
4179 * \param bridge The bridge where the transfer is being performed
4180 * \param exten The destination extension for the blind transfer
4181 * \param context The destination context for the blind transfer
4182 * \param transferee The party being transferred if there is only one
4183 * \param new_channel_cb Callback to call on channel that is created to
4184 * facilitate the blind transfer.
4185 * \param user_data_wrapper User-provided data needed in new_channel_cb
4186 * \param transfer_message The Stasis publication for this transfer.
4187 *
4188 * \return The success or failure of the operation
4189 */
4190static enum ast_transfer_result blind_transfer_bridge(int is_external,
4191 struct ast_channel *transferer, struct ast_bridge *bridge,
4192 const char *exten, const char *context, struct ast_channel *transferee,
4193 transfer_channel_cb new_channel_cb,
4194 struct transfer_channel_data *user_data_wrapper,
4195 struct ast_blind_transfer_message *transfer_message)
4196{
4197 struct ast_channel *local;
4198 char chan_name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
4199 int cause;
4200 struct ast_format_cap *caps;
4201
4202 ast_channel_lock(transferer);
4203 caps = ao2_bump(ast_channel_nativeformats(transferer));
4204 ast_channel_unlock(transferer);
4205
4206 snprintf(chan_name, sizeof(chan_name), "%s@%s", exten, context);
4207 local = ast_request("Local", caps, NULL, transferer,
4208 chan_name, &cause);
4209
4210 ao2_cleanup(caps);
4211
4212 if (!local) {
4214 }
4215
4216 ast_channel_lock_both(local, transferer);
4218
4220 if (!transfer_message->replace_channel) {
4221 ast_hangup(local);
4223 }
4224
4226 ast_channel_unlock(local);
4227 ast_channel_unlock(transferer);
4228
4229 if (new_channel_cb) {
4230 new_channel_cb(local, user_data_wrapper, AST_BRIDGE_TRANSFER_MULTI_PARTY);
4231 }
4232
4233 if (ast_call(local, chan_name, 0)) {
4234 ast_hangup(local);
4236 }
4237
4238 if (ast_bridge_impart(bridge, local, transferer, NULL,
4240 ast_hangup(local);
4242 }
4243
4245}
4246
4247/*!
4248 * \internal
4249 * \brief Get the transferee channel
4250 *
4251 * This is only applicable to cases where a transfer is occurring on a
4252 * two-party bridge. The channels container passed in is expected to only
4253 * contain two channels, the transferer and the transferee. The transferer
4254 * channel is passed in as a parameter to ensure we don't return it as
4255 * the transferee channel.
4256 *
4257 * \param channels A two-channel container containing the transferer and transferee
4258 * \param transferer The party that is transferring the call
4259 * \return The party that is being transferred
4260 */
4261static struct ast_channel *get_transferee(struct ao2_container *channels, struct ast_channel *transferer)
4262{
4263 struct ao2_iterator channel_iter;
4264 struct ast_channel *transferee;
4265
4266 for (channel_iter = ao2_iterator_init(channels, 0);
4267 (transferee = ao2_iterator_next(&channel_iter));
4268 ao2_cleanup(transferee)) {
4269 if (transferee != transferer) {
4270 break;
4271 }
4272 }
4273
4274 ao2_iterator_destroy(&channel_iter);
4275 return transferee;
4276}
4277
4278/*!
4279 * \brief Perform an attended transfer of a bridge
4280 *
4281 * This performs an attended transfer of an entire bridge to a target.
4282 * The target varies, depending on what bridges exist during the transfer
4283 * attempt.
4284 *
4285 * If two bridges exist, then a local channel is created to link the two
4286 * bridges together.
4287 *
4288 * If only one bridge exists, then a local channel is created with one end
4289 * placed into the existing bridge and the other end masquerading into
4290 * the unbridged channel.
4291 *
4292 * \param chan1 Transferer channel. Guaranteed to be bridged.
4293 * \param chan2 Other transferer channel. May or may not be bridged.
4294 * \param bridge1 Bridge that chan1 is in. Guaranteed to be non-NULL.
4295 * \param bridge2 Bridge that chan2 is in. If NULL, then chan2 is not bridged.
4296 * \param transfer_msg Data to publish for a stasis attended transfer message.
4297 * \retval AST_BRIDGE_TRANSFER_FAIL Internal error occurred
4298 * \retval AST_BRIDGE_TRANSFER_SUCCESS Successfully transferred the bridge
4299 */
4301 struct ast_channel *chan2, struct ast_bridge *bridge1, struct ast_bridge *bridge2,
4302 struct ast_attended_transfer_message *transfer_msg)
4303{
4304#define BRIDGE_LOCK_ONE_OR_BOTH(b1, b2) \
4305 do { \
4306 if (b2) { \
4307 ast_bridge_lock_both(b1, b2); \
4308 } else { \
4309 ast_bridge_lock(b1); \
4310 } \
4311 } while (0)
4312
4313 static const char *dest = "_attended@transfer/m";
4314 struct ast_channel *local_chan;
4315 int cause;
4316 int res;
4317 const char *app = NULL;
4318 struct ast_format_cap *caps;
4319
4320 ast_channel_lock(chan1);
4321 caps = ao2_bump(ast_channel_nativeformats(chan1));
4322 ast_channel_unlock(chan1);
4323
4324 local_chan = ast_request("Local", caps, NULL, chan1, dest, &cause);
4325
4326 ao2_cleanup(caps);
4327
4328 if (!local_chan) {
4330 }
4331
4332 ast_channel_lock_both(local_chan, chan1);
4335 ast_channel_unlock(local_chan);
4336 ast_channel_unlock(chan1);
4337
4338 if (bridge2) {
4339 res = ast_local_setup_bridge(local_chan, bridge2, chan2, NULL);
4340 } else {
4342 res = ast_local_setup_masquerade(local_chan, chan2);
4343 }
4344
4345 if (res) {
4346 ast_hangup(local_chan);
4348 }
4349
4350 /*
4351 * Since bridges need to be unlocked before entering ast_bridge_impart and
4352 * core_local may call into it then the bridges need to be unlocked here.
4353 */
4354 ast_bridge_unlock(bridge1);
4355 if (bridge2) {
4356 ast_bridge_unlock(bridge2);
4357 }
4358
4359 if (ast_call(local_chan, dest, 0)) {
4360 ast_hangup(local_chan);
4361 BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2);
4363 }
4364
4365 /* Get a ref for use later since this one is being stolen */
4366 ao2_ref(local_chan, +1);
4367 if (ast_bridge_impart(bridge1, local_chan, chan1, NULL,
4369 ast_hangup(local_chan);
4370 ao2_cleanup(local_chan);
4371 BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2);
4373 }
4374 BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2);
4375
4376 if (bridge2) {
4377 void *tech;
4378 struct ast_channel *locals[2];
4379
4380 /* Have to lock everything just in case a hangup comes in early */
4381 ast_local_lock_all(local_chan, &tech, &locals[0], &locals[1]);
4382 if (!locals[0] || !locals[1]) {
4383 ast_log(LOG_ERROR, "Transfer failed probably due to an early hangup - "
4384 "missing other half of '%s'\n", ast_channel_name(local_chan));
4386 ao2_cleanup(local_chan);
4388 }
4389
4390 /* Make sure the peer is properly set */
4391 if (local_chan != locals[0]) {
4392 SWAP(locals[0], locals[1]);
4393 }
4394
4397 } else {
4398 ast_attended_transfer_message_add_app(transfer_msg, app, local_chan);
4399 }
4400
4401 ao2_cleanup(local_chan);
4403}
4404
4405static enum ast_transfer_result try_parking(struct ast_channel *transferer,
4406 const char *context, const char *exten, transfer_channel_cb new_channel_cb,
4407 struct transfer_channel_data *user_data_wrapper)
4408{
4409 RAII_VAR(struct ast_bridge_channel *, transferer_bridge_channel, NULL, ao2_cleanup);
4410
4413 }
4414
4415 ast_channel_lock(transferer);
4416 transferer_bridge_channel = ast_channel_get_bridge_channel(transferer);
4417 ast_channel_unlock(transferer);
4418
4419 if (!transferer_bridge_channel) {
4421 }
4422
4423 if (ast_parking_blind_transfer_park(transferer_bridge_channel,
4424 context, exten, new_channel_cb, user_data_wrapper)) {
4426 }
4427
4429}
4430
4431void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int attended)
4432{
4433 char *writevar;
4434 char *erasevar;
4435
4436 if (attended) {
4437 writevar = ATTENDEDTRANSFER;
4438 erasevar = BLINDTRANSFER;
4439 } else {
4440 writevar = BLINDTRANSFER;
4441 erasevar = ATTENDEDTRANSFER;
4442 }
4443
4444 pbx_builtin_setvar_helper(chan, writevar, value);
4445 pbx_builtin_setvar_helper(chan, erasevar, NULL);
4446}
4447
4448/*!
4449 * \internal
4450 * \brief Set the transfer variable as appropriate on channels involved in the transfer
4451 *
4452 * The transferer channel will have its variable set the same as its BRIDGEPEER
4453 * variable. This will account for all channels that it is bridged to. The other channels
4454 * involved in the transfer will have their variable set to the transferer
4455 * channel's name.
4456 *
4457 * \param transferer The channel performing the transfer
4458 * \param channels The channels belonging to the bridge
4459 * \param is_attended false set BLINDTRANSFER and unset ATTENDEDTRANSFER
4460 * true set ATTENDEDTRANSFER and unset BLINDTRANSFER
4461 */
4462static void set_transfer_variables_all(struct ast_channel *transferer, struct ao2_container *channels, int is_attended)
4463{
4464 struct ao2_iterator iter;
4465 struct ast_channel *chan;
4466 const char *transferer_name;
4467 const char *transferer_bridgepeer;
4468
4469 ast_channel_lock(transferer);
4470 transferer_name = ast_strdupa(ast_channel_name(transferer));
4471 transferer_bridgepeer = ast_strdupa(S_OR(pbx_builtin_getvar_helper(transferer, "BRIDGEPEER"), ""));
4472 ast_channel_unlock(transferer);
4473
4474 for (iter = ao2_iterator_init(channels, 0);
4475 (chan = ao2_iterator_next(&iter));
4476 ao2_cleanup(chan)) {
4477 if (chan == transferer) {
4478 ast_bridge_set_transfer_variables(chan, transferer_bridgepeer, is_attended);
4479 } else {
4480 ast_bridge_set_transfer_variables(chan, transferer_name, is_attended);
4481 }
4482 }
4483
4484 ao2_iterator_destroy(&iter);
4485}
4486
4488{
4489 struct ast_bridge *bridge;
4490
4491 ast_channel_lock(chan);
4492 bridge = ast_channel_get_bridge(chan);
4493 ast_channel_unlock(chan);
4494
4495 if (bridge && ast_test_flag(&bridge->feature_flags,
4497 ao2_ref(bridge, -1);
4498 bridge = NULL;
4499 }
4500
4501 return bridge;
4502}
4503
4505 struct ast_channel *transferer, const char *exten, const char *context,
4506 transfer_channel_cb new_channel_cb, void *user_data)
4507{
4508 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
4509 RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
4511 RAII_VAR(struct ast_channel *, transferee, NULL, ast_channel_cleanup);
4512 RAII_VAR(struct transfer_channel_data *, user_data_wrapper, NULL, ao2_cleanup);
4513 RAII_VAR(struct ast_blind_transfer_message *, transfer_message, NULL, ao2_cleanup);
4514 int do_bridge_transfer;
4515 int transfer_prohibited;
4516 enum ast_transfer_result transfer_result;
4517
4518 transfer_message = ast_blind_transfer_message_create(is_external, transferer, exten, context);
4519 if (!transfer_message) {
4520 /* Out of memory. Not even possible to publish a Stasis message about the
4521 * failure
4522 */
4523 ast_log(LOG_ERROR, "Unable to allocate memory for blind transfer publication from %s\n",
4524 ast_channel_name(transferer));
4526 }
4527
4528 bridge = ast_bridge_transfer_acquire_bridge(transferer);
4529 if (!bridge) {
4530 transfer_result = AST_BRIDGE_TRANSFER_INVALID;
4531 goto publish;
4532 }
4533
4534 ast_bridge_lock(bridge);
4535 transfer_message->bridge = ast_bridge_snapshot_create(bridge);
4536 ast_bridge_unlock(bridge);
4537 if (!transfer_message->bridge) {
4538 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4539 goto publish;
4540 }
4541
4542 transferee = ast_bridge_peer(bridge, transferer);
4543 if (transferee) {
4544 transfer_message->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee));
4545 if (!transfer_message->transferee) {
4546 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4547 goto publish;
4548 }
4549 }
4550
4551 ast_channel_lock(transferer);
4552 bridge_channel = ast_channel_get_bridge_channel(transferer);
4553 ast_channel_unlock(transferer);
4554 if (!bridge_channel) {
4555 transfer_result = AST_BRIDGE_TRANSFER_INVALID;
4556 goto publish;
4557 }
4558
4559 user_data_wrapper = ao2_alloc(sizeof(*user_data_wrapper), NULL);
4560 if (!user_data_wrapper) {
4561 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4562 goto publish;
4563 }
4564
4565 user_data_wrapper->data = user_data;
4566
4567 /* Take off hold if they are on hold. */
4568 ast_bridge_channel_write_unhold(bridge_channel);
4569
4570 transfer_result = try_parking(transferer, context, exten, new_channel_cb, user_data_wrapper);
4571 if (transfer_result == AST_BRIDGE_TRANSFER_SUCCESS) {
4572 goto publish;
4573 }
4574
4575 /* Since parking didn't take control of the user_data_wrapper, we are just going to raise the completed flag now. */
4576 user_data_wrapper->completed = 1;
4577
4578 {
4580
4582 if (!channels) {
4583 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4584 goto publish;
4585 }
4586 if (ao2_container_count(channels) <= 1) {
4587 transfer_result = AST_BRIDGE_TRANSFER_INVALID;
4588 goto publish;
4589 }
4590 transfer_prohibited = ast_test_flag(&bridge->feature_flags,
4592 do_bridge_transfer = ast_test_flag(&bridge->feature_flags,
4595 }
4596
4597 if (transfer_prohibited) {
4598 transfer_result = AST_BRIDGE_TRANSFER_NOT_PERMITTED;
4599 goto publish;
4600 }
4601
4602 set_transfer_variables_all(transferer, channels, 0);
4603
4604 if (do_bridge_transfer) {
4605 transfer_result = blind_transfer_bridge(is_external, transferer, bridge,
4606 exten, context, transferee, new_channel_cb, user_data_wrapper, transfer_message);
4607 goto publish;
4608 }
4609
4610 /* Reaching this portion means that we're dealing with a two-party bridge */
4611
4612 if (!transferee) {
4613 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4614 goto publish;
4615 }
4616
4618 new_channel_cb, user_data_wrapper)) {
4619 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4620 goto publish;
4621 }
4622
4623 ast_bridge_remove(bridge, transferer);
4624 transfer_result = AST_BRIDGE_TRANSFER_SUCCESS;
4625
4626publish:
4627 transfer_message->result = transfer_result;
4628 ast_bridge_publish_blind_transfer(transfer_message);
4629 return transfer_result;
4630}
4631
4632/*!
4633 * \internal
4634 * \brief Performs an attended transfer by moving a channel from one bridge to another
4635 *
4636 * The channel that is bridged to the source_channel is moved into the dest_bridge from
4637 * the source_bridge_channel's bridge. The swap_channel is swapped out of the dest_bridge and placed in
4638 * the source_bridge_channel's bridge.
4639 *
4640 * \note dest_bridge and source_bridge_channel's bridge MUST be locked before calling this function.
4641 *
4642 * \param dest_bridge The final bridge for the attended transfer
4643 * \param source_bridge_channel Channel who is bridged to the channel that will move
4644 * \param swap_channel Channel to be swapped out of the dest_bridge
4645 * \return The success or failure of the swap attempt
4646 */
4648 struct ast_bridge_channel *source_bridge_channel, struct ast_channel *swap_channel)
4649{
4650 struct ast_bridge_channel *bridged_to_source;
4651
4652 bridged_to_source = ast_bridge_channel_peer(source_bridge_channel);
4653 if (bridged_to_source
4654 && bridged_to_source->state == BRIDGE_CHANNEL_STATE_WAIT
4655 && !ast_test_flag(&bridged_to_source->features->feature_flags,
4657 bridged_to_source->swap = swap_channel;
4658 if (bridge_do_move(dest_bridge, bridged_to_source, 1, 0)) {
4660 }
4661 /* Must kick the source channel out of its bridge. */
4662 ast_bridge_channel_leave_bridge(source_bridge_channel,
4665 } else {
4667 }
4668}
4669
4670/*!
4671 * \internal
4672 * \brief Function that performs an attended transfer when both transferer channels are bridged
4673 *
4674 * The method by which the transfer is performed is dependent on whether the bridges allow for
4675 * optimization to occur between them. If no optimization is permitted, then an unreal channel
4676 * is placed as a link between the two bridges. If optimization is permitted, then that means
4677 * we are free to perform move or merge operations in order to perform the transfer.
4678 *
4679 * \note to_transferee_bridge and to_target_bridge MUST be locked before calling this function
4680 *
4681 * \param to_transferee The channel that is bridged to the transferee
4682 * \param to_transferee_bridge_channel to_transferee's bridge_channel
4683 * \param to_transfer_target The channel that is bridged to the transfer target
4684 * \param to_target_bridge_channel to_transfer_target's bridge_channel
4685 * \param to_transferee_bridge The bridge between to_transferee and the transferee
4686 * \param to_target_bridge The bridge between to_transfer_target and the transfer_target
4687 * \param transfer_msg Data to publish for a stasis attended transfer message
4688 * \return The success or failure of the attended transfer
4689 */
4691 struct ast_bridge_channel *to_transferee_bridge_channel,
4692 struct ast_channel *to_transfer_target,
4693 struct ast_bridge_channel *to_target_bridge_channel,
4694 struct ast_bridge *to_transferee_bridge, struct ast_bridge *to_target_bridge,
4695 struct ast_attended_transfer_message *transfer_msg)
4696{
4697 struct ast_bridge_channel *kick_me[] = {
4698 to_transferee_bridge_channel,
4699 to_target_bridge_channel,
4700 };
4701 enum ast_transfer_result res;
4702 struct ast_bridge *final_bridge = NULL;
4704
4705 channels = ast_bridge_peers_nolock(to_transferee_bridge);
4706
4707 if (!channels) {
4709 goto end;
4710 }
4711
4712 set_transfer_variables_all(to_transferee, channels, 1);
4713
4714 switch (ast_bridges_allow_optimization(to_transferee_bridge, to_target_bridge)) {
4716 final_bridge = to_transferee_bridge;
4717 res = bridge_swap_attended_transfer(to_transferee_bridge, to_target_bridge_channel, to_transferee);
4718 goto end;
4720 final_bridge = to_target_bridge;
4721 res = bridge_swap_attended_transfer(to_target_bridge, to_transferee_bridge_channel, to_transfer_target);
4722 goto end;
4724 final_bridge = to_transferee_bridge;
4725 bridge_do_merge(to_transferee_bridge, to_target_bridge, kick_me, ARRAY_LEN(kick_me), 0);
4727 goto end;
4729 final_bridge = to_target_bridge;
4730 bridge_do_merge(to_target_bridge, to_transferee_bridge, kick_me, ARRAY_LEN(kick_me), 0);
4732 goto end;
4734 default:
4735 /* Just because optimization wasn't doable doesn't necessarily mean
4736 * that we can actually perform the transfer. Some reasons for non-optimization
4737 * indicate bridge invalidity, so let's check those before proceeding.
4738 */
4739 if (to_transferee_bridge->inhibit_merge || to_transferee_bridge->dissolved ||
4740 to_target_bridge->inhibit_merge || to_target_bridge->dissolved) {
4742 }
4743
4744 return attended_transfer_bridge(to_transferee, to_transfer_target,
4745 to_transferee_bridge, to_target_bridge, transfer_msg);
4746 }
4747
4748end:
4749 if (res == AST_BRIDGE_TRANSFER_SUCCESS) {
4750 ast_attended_transfer_message_add_merge(transfer_msg, final_bridge);
4751 }
4752
4753 return res;
4754}
4755
4757 struct ast_channel *to_transfer_target)
4758{
4759 RAII_VAR(struct ast_bridge *, to_transferee_bridge, NULL, ao2_cleanup);
4760 RAII_VAR(struct ast_bridge *, to_target_bridge, NULL, ao2_cleanup);
4761 RAII_VAR(struct ast_bridge_channel *, to_transferee_bridge_channel, NULL, ao2_cleanup);
4762 RAII_VAR(struct ast_bridge_channel *, to_target_bridge_channel, NULL, ao2_cleanup);
4764 RAII_VAR(struct ast_channel *, transferee, NULL, ao2_cleanup);
4765 RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
4766 struct ast_bridge *the_bridge = NULL;
4767 struct ast_channel *chan_bridged;
4768 struct ast_channel *chan_unbridged;
4769 int transfer_prohibited;
4770 int do_bridge_transfer;
4771 enum ast_transfer_result res;
4772 const char *app = NULL;
4773 int hangup_target = 0;
4774
4775 to_transferee_bridge = ast_bridge_transfer_acquire_bridge(to_transferee);
4776 to_target_bridge = ast_bridge_transfer_acquire_bridge(to_transfer_target);
4777
4778 transfer_msg = ast_attended_transfer_message_create(1, to_transferee, to_transferee_bridge,
4779 to_transfer_target, to_target_bridge, NULL, NULL);
4780 if (!transfer_msg) {
4781 ast_log(LOG_ERROR, "Unable to create Stasis publication for attended transfer from %s\n",
4782 ast_channel_name(to_transferee));
4784 }
4785
4786 /* They can't both be unbridged, you silly goose! */
4787 if (!to_transferee_bridge && !to_target_bridge) {
4789 goto end;
4790 }
4791
4792 ast_channel_lock(to_transferee);
4793 to_transferee_bridge_channel = ast_channel_get_bridge_channel(to_transferee);
4794 ast_channel_unlock(to_transferee);
4795
4796 ast_channel_lock(to_transfer_target);
4797 to_target_bridge_channel = ast_channel_get_bridge_channel(to_transfer_target);
4798 ast_channel_unlock(to_transfer_target);
4799
4800 if (to_transferee_bridge_channel) {
4801 /* Take off hold if they are on hold. */
4802 if (ast_bridge_channel_write_unhold(to_transferee_bridge_channel)) {
4803 ast_log(LOG_ERROR, "Transferee channel disappeared during transfer!\n");
4805 goto end;
4806 }
4807 }
4808
4809 if (to_target_bridge_channel) {
4810 const char *target_complete_sound;
4811
4812 /* Take off hold if they are on hold. */
4813 if (ast_bridge_channel_write_unhold(to_target_bridge_channel)) {
4814 ast_log(LOG_ERROR, "Target channel disappeared during transfer!\n");
4816 goto end;
4817 }
4818
4819 /* Is there a courtesy sound to play to the target? */
4820 ast_channel_lock(to_transfer_target);
4821 target_complete_sound = pbx_builtin_getvar_helper(to_transfer_target,
4822 "ATTENDED_TRANSFER_COMPLETE_SOUND");
4823 if (!ast_strlen_zero(target_complete_sound)) {
4824 target_complete_sound = ast_strdupa(target_complete_sound);
4825 } else {
4826 target_complete_sound = NULL;
4827 }
4828 ast_channel_unlock(to_transfer_target);
4829 if (!target_complete_sound) {
4830 ast_channel_lock(to_transferee);
4831 target_complete_sound = pbx_builtin_getvar_helper(to_transferee,
4832 "ATTENDED_TRANSFER_COMPLETE_SOUND");
4833 if (!ast_strlen_zero(target_complete_sound)) {
4834 target_complete_sound = ast_strdupa(target_complete_sound);
4835 } else {
4836 target_complete_sound = NULL;
4837 }
4838 ast_channel_unlock(to_transferee);
4839 }
4840 if (target_complete_sound) {
4841 ast_bridge_channel_write_playfile(to_target_bridge_channel, NULL,
4842 target_complete_sound, NULL);
4843 }
4844 }
4845
4846 /* Let's get the easy one out of the way first */
4847 if (to_transferee_bridge && to_target_bridge) {
4848
4849 if (!to_transferee_bridge_channel || !to_target_bridge_channel) {
4851 goto end;
4852 }
4853
4854 ast_bridge_lock_both(to_transferee_bridge, to_target_bridge);
4855 res = two_bridge_attended_transfer(to_transferee, to_transferee_bridge_channel,
4856 to_transfer_target, to_target_bridge_channel,
4857 to_transferee_bridge, to_target_bridge, transfer_msg);
4858 ast_bridge_unlock(to_transferee_bridge);
4859 ast_bridge_unlock(to_target_bridge);
4860
4861 hangup_target = 1;
4862 goto end;
4863 }
4864
4865 the_bridge = to_transferee_bridge ?: to_target_bridge;
4866 chan_bridged = to_transferee_bridge ? to_transferee : to_transfer_target;
4867 chan_unbridged = to_transferee_bridge ? to_transfer_target : to_transferee;
4868
4869 /*
4870 * Race condition makes it possible for app to be NULL, so get the app prior to
4871 * transferring with a fallback of "unknown".
4872 */
4873 app = ast_strdupa(ast_channel_appl(chan_unbridged) ?: "unknown");
4874
4875 {
4876 int chan_count;
4878
4879 channels = ast_bridge_peers_nolock(the_bridge);
4880 if (!channels) {
4882 goto end;
4883 }
4884 chan_count = ao2_container_count(channels);
4885 if (chan_count <= 1) {
4887 goto end;
4888 }
4889 transfer_prohibited = ast_test_flag(&the_bridge->feature_flags,
4891 do_bridge_transfer = ast_test_flag(&the_bridge->feature_flags,
4893 chan_count > 2;
4894 }
4895
4896 if (transfer_prohibited) {
4898 goto end;
4899 }
4900
4901 set_transfer_variables_all(to_transferee, channels, 1);
4902
4903 if (do_bridge_transfer) {
4904 /*
4905 * Hang up the target if it was bridged. Note, if it is not bridged
4906 * it is hung up during the masquerade.
4907 */
4908 hangup_target = chan_bridged == to_transfer_target;
4909 ast_bridge_lock(the_bridge);
4910 res = attended_transfer_bridge(chan_bridged, chan_unbridged, the_bridge, NULL, transfer_msg);
4911 ast_bridge_unlock(the_bridge);
4912 goto end;
4913 }
4914
4915 transferee = get_transferee(channels, chan_bridged);
4916 if (!transferee) {
4918 goto end;
4919 }
4920
4921 if (bridge_channel_internal_queue_attended_transfer(transferee, chan_unbridged)) {
4923 goto end;
4924 }
4925
4926 ast_bridge_remove(the_bridge, chan_bridged);
4927
4930
4931end:
4932 if ((res == AST_BRIDGE_TRANSFER_SUCCESS && hangup_target) || res == AST_BRIDGE_TRANSFER_FAIL) {
4933 ast_softhangup(to_transfer_target, AST_SOFTHANGUP_DEV);
4934 }
4935
4936 transfer_msg->result = res;
4938 return res;
4939}
4940
4941/*!
4942 * \internal
4943 * \brief Service the bridge manager request.
4944 * \since 12.0.0
4945 *
4946 * \param bridge requesting service.
4947 */
4949{
4951 if (bridge->callid) {
4953 }
4954
4955 /* Do any pending bridge actions. */
4958}
4959
4960/*!
4961 * \internal
4962 * \brief Bridge manager service thread.
4963 * \since 12.0.0
4964 */
4965static void *bridge_manager_thread(void *data)
4966{
4967 struct bridge_manager_controller *manager = data;
4969
4970 ao2_lock(manager);
4971 while (!manager->stop) {
4973 if (!request) {
4974 ast_cond_wait(&manager->cond, ao2_object_get_lockaddr(manager));
4975 continue;
4976 }
4977 ao2_unlock(manager);
4978
4979 /* Service the bridge. */
4981 ao2_ref(request->bridge, -1);
4983
4984 ao2_lock(manager);
4985 }
4986 ao2_unlock(manager);
4987
4988 return NULL;
4989}
4990
4991/*!
4992 * \internal
4993 * \brief Destroy the bridge manager controller.
4994 * \since 12.0.0
4995 *
4996 * \param obj Bridge manager to destroy.
4997 */
4998static void bridge_manager_destroy(void *obj)
4999{
5000 struct bridge_manager_controller *manager = obj;
5002
5003 if (manager->thread != AST_PTHREADT_NULL) {
5004 /* Stop the manager thread. */
5005 ao2_lock(manager);
5006 manager->stop = 1;
5007 ast_cond_signal(&manager->cond);
5008 ao2_unlock(manager);
5009 ast_debug(1, "Waiting for bridge manager thread to die.\n");
5010 pthread_join(manager->thread, NULL);
5011 }
5012
5013 /* Destroy the service request queue. */
5014 while ((request = AST_LIST_REMOVE_HEAD(&manager->service_requests, node))) {
5015 ao2_ref(request->bridge, -1);
5017 }
5018
5019 ast_cond_destroy(&manager->cond);
5020}
5021
5022/*!
5023 * \internal
5024 * \brief Create the bridge manager controller.
5025 * \since 12.0.0
5026 *
5027 * \return manager on success.
5028 * \retval NULL on error.
5029 */
5031{
5032 struct bridge_manager_controller *manager;
5033
5034 manager = ao2_alloc(sizeof(*manager), bridge_manager_destroy);
5035 if (!manager) {
5036 /* Well. This isn't good. */
5037 return NULL;
5038 }
5039 ast_cond_init(&manager->cond, NULL);
5041
5042 /* Create the bridge manager thread. */
5043 if (ast_pthread_create(&manager->thread, NULL, bridge_manager_thread, manager)) {
5044 /* Well. This isn't good either. */
5045 manager->thread = AST_PTHREADT_NULL;
5046 ao2_ref(manager, -1);
5047 manager = NULL;
5048 }
5049
5050 return manager;
5051}
5052
5053/*!
5054 * \internal
5055 * \brief Bridge ao2 container sort function.
5056 * \since 12.0.0
5057 *
5058 * \param obj_left pointer to the (user-defined part) of an object.
5059 * \param obj_right pointer to the (user-defined part) of an object.
5060 * \param flags flags from ao2_callback()
5061 * OBJ_POINTER - if set, 'obj_right', is an object.
5062 * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
5063 * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
5064 *
5065 * \retval <0 if obj_left < obj_right
5066 * \retval =0 if obj_left == obj_right
5067 * \retval >0 if obj_left > obj_right
5068 */
5069static int bridge_sort_cmp(const void *obj_left, const void *obj_right, int flags)
5070{
5071 const struct ast_bridge *bridge_left = obj_left;
5072 const struct ast_bridge *bridge_right = obj_right;
5073 const char *right_key = obj_right;
5074 int cmp;
5075
5076 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
5077 default:
5078 case OBJ_POINTER:
5079 right_key = bridge_right->uniqueid;
5080 /* Fall through */
5081 case OBJ_KEY:
5082 cmp = strcmp(bridge_left->uniqueid, right_key);
5083 break;
5084 case OBJ_PARTIAL_KEY:
5085 cmp = strncmp(bridge_left->uniqueid, right_key, strlen(right_key));
5086 break;
5087 }
5088 return cmp;
5089}
5090
5091struct ast_bridge *ast_bridge_find_by_id(const char *bridge_id)
5092{
5093 return ao2_find(bridges, bridge_id, OBJ_SEARCH_KEY);
5094}
5095
5096static int complete_bridge_live_search(void *obj, void *arg, int flags)
5097{
5098 struct ast_bridge *bridge = obj;
5099
5101 return CMP_STOP;
5102 }
5103
5104 return 0;
5105}
5106
5107static char *complete_bridge_live(const char *word)
5108{
5111
5112 return NULL;
5113}
5114
5115static char *handle_bridge_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5116{
5117#define FORMAT_HDR "%-36s %-36s %5s %-15s %-15s %s\n"
5118#define FORMAT_ROW "%-36s %-36s %5u %-15s %-15s %s\n"
5119
5120 struct ao2_iterator iter;
5121 struct ast_bridge *bridge;
5122
5123 switch (cmd) {
5124 case CLI_INIT:
5125 e->command = "bridge show all";
5126 e->usage =
5127 "Usage: bridge show all\n"
5128 " List all bridges\n";
5129 return NULL;
5130 case CLI_GENERATE:
5131 return NULL;
5132 }
5133
5134 ast_cli(a->fd, FORMAT_HDR, "Bridge-ID", "Name", "Chans", "Type", "Technology", "Duration");
5135
5136 iter = ao2_iterator_init(bridges, 0);
5137 for (; (bridge = ao2_iterator_next(&iter)); ao2_ref(bridge, -1)) {
5138 struct ast_bridge_snapshot *snapshot = ast_bridge_get_snapshot(bridge);
5139 char print_time[32];
5140
5141 if (snapshot) {
5142 ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, sizeof(print_time));
5143 ast_cli(a->fd, FORMAT_ROW,
5144 bridge->uniqueid,
5145 S_OR(bridge->name, "<unknown>"),
5146 snapshot->num_channels,
5147 S_OR(snapshot->subclass, "<unknown>"),
5148 S_OR(snapshot->technology, "<unknown>"),
5149 print_time);
5150 ao2_ref(snapshot, -1);
5151 }
5152 }
5153 ao2_iterator_destroy(&iter);
5154
5155 return CLI_SUCCESS;
5156
5157#undef FORMAT_HDR
5158#undef FORMAT_ROW
5159}
5160
5161/*! \brief Internal callback function for sending channels in a bridge to the CLI */
5162static int bridge_show_specific_print_channel(void *obj, void *arg, int flags)
5163{
5164 const char *uniqueid = obj;
5165 struct ast_cli_args *a = arg;
5166 struct ast_channel_snapshot *snapshot;
5167
5168 snapshot = ast_channel_snapshot_get_latest(uniqueid);
5169 if (!snapshot) {
5170 return 0;
5171 }
5172
5173 ast_cli(a->fd, "Channel: %s\n", snapshot->base->name);
5174 ao2_ref(snapshot, -1);
5175
5176 return 0;
5177}
5178
5179static char *handle_bridge_show_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5180{
5181 struct ast_bridge_snapshot *snapshot;
5182 char print_time[32];
5183
5184 switch (cmd) {
5185 case CLI_INIT:
5186 e->command = "bridge show";
5187 e->usage =
5188 "Usage: bridge show <bridge-id>\n"
5189 " Show information about the <bridge-id> bridge\n";
5190 return NULL;
5191 case CLI_GENERATE:
5192 if (a->pos == 2) {
5193 return complete_bridge_live(a->word);
5194 }
5195 return NULL;
5196 }
5197
5198 if (a->argc != 3) {
5199 return CLI_SHOWUSAGE;
5200 }
5201
5202 snapshot = ast_bridge_get_snapshot_by_uniqueid(a->argv[2]);
5203 if (!snapshot) {
5204 ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
5205 return CLI_SUCCESS;
5206 }
5207
5208 ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, sizeof(print_time));
5209
5210 ast_cli(a->fd, "Id: %s\n", snapshot->uniqueid);
5211 ast_cli(a->fd, "Type: %s\n", S_OR(snapshot->subclass, "<unknown>"));
5212 ast_cli(a->fd, "Technology: %s\n", S_OR(snapshot->technology, "<unknown>"));
5213 ast_cli(a->fd, "Subclass: %s\n", snapshot->subclass);
5214 ast_cli(a->fd, "Creator: %s\n", snapshot->creator);
5215 ast_cli(a->fd, "Name: %s\n", snapshot->name);
5216 ast_cli(a->fd, "Video-Mode: %s\n", ast_bridge_video_mode_to_string(snapshot->video_mode));
5217 ast_cli(a->fd, "Video-Source-Id: %s\n", snapshot->video_source_id);
5218 ast_cli(a->fd, "Num-Channels: %u\n", snapshot->num_channels);
5219 ast_cli(a->fd, "Num-Active: %u\n", snapshot->num_active);
5220 ast_cli(a->fd, "Duration: %s\n", print_time);
5222 ao2_ref(snapshot, -1);
5223
5224 return CLI_SUCCESS;
5225}
5226
5227#ifdef AST_DEVMODE
5228static char *handle_bridge_destroy_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5229{
5230 struct ast_bridge *bridge;
5231
5232 switch (cmd) {
5233 case CLI_INIT:
5234 e->command = "bridge destroy";
5235 e->usage =
5236 "Usage: bridge destroy <bridge-id>\n"
5237 " Destroy the <bridge-id> bridge\n";
5238 return NULL;
5239 case CLI_GENERATE:
5240 if (a->pos == 2) {
5241 return complete_bridge_live(a->word);
5242 }
5243 return NULL;
5244 }
5245
5246 if (a->argc != 3) {
5247 return CLI_SHOWUSAGE;
5248 }
5249
5250 bridge = ast_bridge_find_by_id(a->argv[2]);
5251 if (!bridge) {
5252 ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
5253 return CLI_SUCCESS;
5254 }
5255
5256 ast_cli(a->fd, "Destroying bridge '%s'\n", a->argv[2]);
5257 ast_bridge_destroy(bridge, 0);
5258
5259 return CLI_SUCCESS;
5260}
5261#endif
5262
5263static char *complete_bridge_participant(const char *bridge_name, const char *word)
5264{
5265 struct ast_bridge *bridge;
5266 struct ast_bridge_channel *bridge_channel;
5267 int wordlen;
5268
5269 bridge = ast_bridge_find_by_id(bridge_name);
5270 if (!bridge) {
5271 return NULL;
5272 }
5273
5274 wordlen = strlen(word);
5275
5277 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
5278 if (!strncasecmp(ast_channel_name(bridge_channel->chan), word, wordlen)) {
5279 if (ast_cli_completion_add(ast_strdup(ast_channel_name(bridge_channel->chan)))) {
5280 break;
5281 }
5282 }
5283 }
5285
5286 ao2_ref(bridge, -1);
5287
5288 return NULL;
5289}
5290
5291static char *handle_bridge_kick_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5292{
5293 static const char * const completions[] = { "all", NULL };
5294 struct ast_bridge *bridge;
5295
5296 switch (cmd) {
5297 case CLI_INIT:
5298 e->command = "bridge kick";
5299 e->usage =
5300 "Usage: bridge kick <bridge-id> <channel-name | all>\n"
5301 " Kick the <channel-name> channel out of the <bridge-id> bridge\n"
5302 " If all is specified as the channel name then all channels will be\n"
5303 " kicked out of the bridge.\n";
5304 return NULL;
5305 case CLI_GENERATE:
5306 if (a->pos == 2) {
5307 return complete_bridge_live(a->word);
5308 }
5309 if (a->pos == 3) {
5310 ast_cli_complete(a->word, completions, -1);
5311 return complete_bridge_participant(a->argv[2], a->word);
5312 }
5313 return NULL;
5314 }
5315
5316 if (a->argc != 4) {
5317 return CLI_SHOWUSAGE;
5318 }
5319
5320 bridge = ast_bridge_find_by_id(a->argv[2]);
5321 if (!bridge) {
5322 ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
5323 return CLI_SUCCESS;
5324 }
5325
5326 if (!strcasecmp(a->argv[3], "all")) {
5327 struct ast_bridge_channel *bridge_channel;
5328
5329 ast_cli(a->fd, "Kicking all channels from bridge '%s'\n", a->argv[2]);
5330
5332 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
5333 ast_bridge_channel_queue_callback(bridge_channel, 0, kick_it, NULL, 0);
5334 }
5336 } else {
5337 struct ast_channel *chan;
5338
5339 chan = ast_channel_get_by_name_prefix(a->argv[3], strlen(a->argv[3]));
5340 if (!chan) {
5341 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[3]);
5342 ao2_ref(bridge, -1);
5343 return CLI_SUCCESS;
5344 }
5345
5346 ast_cli(a->fd, "Kicking channel '%s' from bridge '%s'\n",
5347 ast_channel_name(chan), a->argv[2]);
5348 ast_bridge_kick(bridge, chan);
5349 ast_channel_unref(chan);
5350 }
5351
5352 ao2_ref(bridge, -1);
5353 return CLI_SUCCESS;
5354}
5355
5356/*! Bridge technology capabilities to string. */
5357static const char *tech_capability2str(uint32_t capabilities)
5358{
5359 const char *type;
5360
5361 if (capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
5362 type = "Holding";
5363 } else if (capabilities & AST_BRIDGE_CAPABILITY_EARLY) {
5364 type = "Early";
5365 } else if (capabilities & AST_BRIDGE_CAPABILITY_NATIVE) {
5366 type = "Native";
5367 } else if (capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
5368 type = "1to1Mix";
5369 } else if (capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
5370 type = "MultiMix";
5371 } else {
5372 type = "<Unknown>";
5373 }
5374 return type;
5375}
5376
5377static char *handle_bridge_technology_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5378{
5379#define FORMAT_HDR "%-20s %-20s %8s %s\n"
5380#define FORMAT_ROW "%-20s %-20s %8u %s\n"
5381
5382 struct ast_bridge_technology *cur;
5383
5384 switch (cmd) {
5385 case CLI_INIT:
5386 e->command = "bridge technology show";
5387 e->usage =
5388 "Usage: bridge technology show\n"
5389 " List registered bridge technologies\n";
5390 return NULL;
5391 case CLI_GENERATE:
5392 return NULL;
5393 }
5394
5395 ast_cli(a->fd, FORMAT_HDR, "Name", "Type", "Priority", "Suspended");
5398 const char *type;
5399
5400 /* Decode type for display */
5402
5403 ast_cli(a->fd, FORMAT_ROW, cur->name, type, cur->preference,
5404 AST_CLI_YESNO(cur->suspended));
5405 }
5407 return CLI_SUCCESS;
5408
5409#undef FORMAT
5410}
5411
5412static char *complete_bridge_technology(const char *word)
5413{
5414 struct ast_bridge_technology *cur;
5415 int wordlen;
5416
5417 wordlen = strlen(word);
5420 if (!strncasecmp(cur->name, word, wordlen)) {
5422 break;
5423 }
5424 }
5425 }
5427
5428 return NULL;
5429}
5430
5431static char *handle_bridge_technology_suspend(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5432{
5433 struct ast_bridge_technology *cur;
5434 int suspend;
5435 int successful;
5436
5437 switch (cmd) {
5438 case CLI_INIT:
5439 e->command = "bridge technology {suspend|unsuspend}";
5440 e->usage =
5441 "Usage: bridge technology {suspend|unsuspend} <technology-name>\n"
5442 " Suspend or unsuspend a bridge technology.\n";
5443 return NULL;
5444 case CLI_GENERATE:
5445 if (a->pos == 3) {
5446 return complete_bridge_technology(a->word);
5447 }
5448 return NULL;
5449 }
5450
5451 if (a->argc != 4) {
5452 return CLI_SHOWUSAGE;
5453 }
5454
5455 suspend = !strcasecmp(a->argv[2], "suspend");
5456 successful = 0;
5459 if (!strcasecmp(cur->name, a->argv[3])) {
5460 successful = 1;
5461 if (suspend) {
5463 } else {
5465 }
5466 break;
5467 }
5468 }
5470
5471 if (successful) {
5472 if (suspend) {
5473 ast_cli(a->fd, "Suspended bridge technology '%s'\n", a->argv[3]);
5474 } else {
5475 ast_cli(a->fd, "Unsuspended bridge technology '%s'\n", a->argv[3]);
5476 }
5477 } else {
5478 ast_cli(a->fd, "Bridge technology '%s' not found\n", a->argv[3]);
5479 }
5480
5481 return CLI_SUCCESS;
5482}
5483
5484static struct ast_cli_entry bridge_cli[] = {
5485 AST_CLI_DEFINE(handle_bridge_show_all, "List all bridges"),
5486 AST_CLI_DEFINE(handle_bridge_show_specific, "Show information about a bridge"),
5487#ifdef AST_DEVMODE
5488 AST_CLI_DEFINE(handle_bridge_destroy_specific, "Destroy a bridge"),
5489#endif
5490 AST_CLI_DEFINE(handle_bridge_kick_channel, "Kick a channel from a bridge"),
5491 AST_CLI_DEFINE(handle_bridge_technology_show, "List registered bridge technologies"),
5492 AST_CLI_DEFINE(handle_bridge_technology_suspend, "Suspend/unsuspend a bridge technology"),
5493};
5494
5495
5496static int handle_manager_bridge_tech_suspend(struct mansession *s, const struct message *m, int suspend)
5497{
5498 const char *name = astman_get_header(m, "BridgeTechnology");
5499 struct ast_bridge_technology *cur;
5500 int successful = 0;
5501
5502 if (ast_strlen_zero(name)) {
5503 astman_send_error(s, m, "BridgeTechnology must be provided");
5504 return 0;
5505 }
5506
5509
5510 if (!strcasecmp(cur->name, name)) {
5511 successful = 1;
5512 if (suspend) {
5514 } else {
5516 }
5517 break;
5518 }
5519 }
5521 if (!successful) {
5522 astman_send_error(s, m, "BridgeTechnology not found");
5523 return 0;
5524 }
5525
5526 astman_send_ack(s, m, (suspend ? "Suspended bridge technology" : "Unsuspended bridge technology"));
5527 return 0;
5528}
5529
5530static int manager_bridge_tech_suspend(struct mansession *s, const struct message *m)
5531{
5532 return handle_manager_bridge_tech_suspend(s, m, 1);
5533}
5534
5535static int manager_bridge_tech_unsuspend(struct mansession *s, const struct message *m)
5536{
5537 return handle_manager_bridge_tech_suspend(s, m, 0);
5538}
5539
5540static int manager_bridge_tech_list(struct mansession *s, const struct message *m)
5541{
5542 const char *id = astman_get_header(m, "ActionID");
5543 RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free);
5544 struct ast_bridge_technology *cur;
5545 int num_items = 0;
5546
5547 if (!id_text) {
5548 astman_send_error(s, m, "Internal error");
5549 return -1;
5550 }
5551
5552 if (!ast_strlen_zero(id)) {
5553 ast_str_set(&id_text, 0, "ActionID: %s\r\n", id);
5554 }
5555
5556 astman_send_listack(s, m, "Bridge technology listing will follow", "start");
5557
5560 const char *type;
5561
5563
5564 astman_append(s,
5565 "Event: BridgeTechnologyListItem\r\n"
5566 "BridgeTechnology: %s\r\n"
5567 "BridgeType: %s\r\n"
5568 "BridgePriority: %u\r\n"
5569 "BridgeSuspended: %s\r\n"
5570 "%s"
5571 "\r\n",
5572 cur->name, type, cur->preference, AST_YESNO(cur->suspended),
5573 ast_str_buffer(id_text));
5574 ++num_items;
5575 }
5577
5578 astman_send_list_complete_start(s, m, "BridgeTechnologyListComplete", num_items);
5580
5581 return 0;
5582}
5583
5584/*!
5585 * \internal
5586 * \brief Print bridge object key (name).
5587 * \since 12.0.0
5588 *
5589 * \param v_obj A pointer to the object we want the key printed.
5590 * \param where User data needed by prnt to determine where to put output.
5591 * \param prnt Print output callback function to use.
5592 */
5593static void bridge_prnt_obj(void *v_obj, void *where, ao2_prnt_fn *prnt)
5594{
5595 struct ast_bridge *bridge = v_obj;
5596
5597 if (!bridge) {
5598 return;
5599 }
5600 prnt(where, "%s %s chans:%u",
5601 bridge->uniqueid, bridge->v_table->name, bridge->num_channels);
5602}
5603
5604/*!
5605 * \internal
5606 * \brief Shutdown the bridging system. Stuff to do on graceful shutdown.
5607 * \since 13.3.0
5608 */
5609static void bridge_cleanup(void)
5610{
5611 ast_manager_unregister("BridgeTechnologyList");
5612 ast_manager_unregister("BridgeTechnologySuspend");
5613 ast_manager_unregister("BridgeTechnologyUnsuspend");
5615 ao2_container_unregister("bridges");
5616
5618 bridges = NULL;
5621}
5622
5624{
5626
5628 return -1;
5629 }
5630
5632 if (!bridge_manager) {
5633 return -1;
5634 }
5635
5638 if (!bridges) {
5639 return -1;
5640 }
5642
5644
5646
5647 ast_manager_register_xml_core("BridgeTechnologyList", 0, manager_bridge_tech_list);
5648 ast_manager_register_xml_core("BridgeTechnologySuspend", 0, manager_bridge_tech_suspend);
5649 ast_manager_register_xml_core("BridgeTechnologyUnsuspend", 0, manager_bridge_tech_unsuspend);
5650
5651 return 0;
5652}
Prototypes for public functions only of internal interest,.
static const char app[]
Definition: app_adsiprog.c:56
static int play_file(struct ast_bridge_channel *bridge_channel, struct ast_channel *channel, const char *filename)
Playback the given filename and monitor for any dtmf interrupts.
@ noanswer
enum queue_result id
Definition: app_queue.c:1767
ast_cond_t cond
Definition: app_sla.c:336
ast_mutex_t lock
Definition: app_sla.c:337
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#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
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define OBJ_KEY
Definition: astobj2.h:1151
#define OBJ_POINTER
Definition: astobj2.h:1150
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
Definition: astobj2.h:1349
#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
#define ao2_t_bump(obj, tag)
Definition: astobj2.h:483
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1152
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_t_cleanup(obj, tag)
Definition: astobj2.h:1935
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
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_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_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
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
Definition: astobj2.h:1435
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE
Replace objects with duplicate keys in container.
Definition: astobj2.h:1211
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition: bridge.c:1975
void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int attended)
Set the relevant transfer variables for a single channel.
Definition: bridge.c:4431
void ast_bridge_set_remb_estimated_bitrate(struct ast_bridge *bridge, float estimated_bitrate)
Force the REMB report estimated bitrate to a specific max value.
Definition: bridge.c:3886
static struct ast_channel * get_transferee(struct ao2_container *channels, struct ast_channel *transferer)
Definition: bridge.c:4261
struct ao2_container * ast_bridges(void)
Returns the global bridges container.
Definition: bridge.c:185
static struct bridge_manager_controller * bridge_manager
Definition: bridge.c:183
void ast_bridge_set_talker_src_video_mode(struct ast_bridge *bridge)
Set the bridge to pick the strongest talker supporting video as the single source video feed.
Definition: bridge.c:3845
int ast_bridging_init(void)
Initialize the bridging system.
Definition: bridge.c:5623
struct ast_bridge * ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Create a new base class bridge.
Definition: bridge.c:999
static void bridge_channel_complete_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Definition: bridge.c:452
int ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, struct ast_bridge_tech_optimizations *tech_args, enum ast_bridge_join_flags flags)
Join a channel to a bridge (blocking)
Definition: bridge.c:1690
static int bridge_base_push_peek(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
Definition: bridge.c:983
static enum ast_transfer_result two_bridge_attended_transfer(struct ast_channel *to_transferee, struct ast_bridge_channel *to_transferee_bridge_channel, struct ast_channel *to_transfer_target, struct ast_bridge_channel *to_target_bridge_channel, struct ast_bridge *to_transferee_bridge, struct ast_bridge *to_target_bridge, struct ast_attended_transfer_message *transfer_msg)
Definition: bridge.c:4690
static int manager_bridge_tech_list(struct mansession *s, const struct message *m)
Definition: bridge.c:5540
static void bridge_channel_impart_ds_head_signal(struct bridge_channel_impart_ds_head *ds_head)
Definition: bridge.c:1563
static int channel_hash(const void *obj, int flags)
Definition: bridge.c:4052
int ast_bridge_hangup_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a hangup hook to a bridge features structure.
Definition: bridge.c:3344
void ast_bridge_set_binaural_active(struct ast_bridge *bridge, unsigned int binaural_active)
Activates the use of binaural signals in a conference bridge.
Definition: bridge.c:3784
void ast_bridge_technology_unsuspend(struct ast_bridge_technology *technology)
Unsuspend a bridge technology.
Definition: bridge.c:3131
static void hooks_remove_heap(struct ast_heap *hooks, enum ast_bridge_hook_remove_flags remove_flags)
Definition: bridge.c:3558
struct ast_channel * ast_bridge_peer_nolock(struct ast_bridge *bridge, struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: bridge.c:4126
int ast_bridge_features_set_limits(struct ast_bridge_features *features, struct ast_bridge_features_limits *limits, enum ast_bridge_hook_remove_flags remove_flags)
Limit the amount of time a channel may stay in the bridge and optionally play warning messages as tim...
Definition: bridge.c:3491
int ast_bridge_number_video_src(struct ast_bridge *bridge)
Returns the number of video sources currently active in the bridge.
Definition: bridge.c:3943
struct ao2_container * ast_bridge_peers_nolock(struct ast_bridge *bridge)
Get a container of all channels in the bridge.
Definition: bridge.c:4097
static void set_bridge_peer_vars_2party(struct ast_channel *c0, struct ast_channel *c1)
Definition: bridge.c:1300
static char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING]
Definition: bridge.c:155
static void bridge_channel_impart_ds_head_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: bridge.c:1592
#define UPDATE_BRIDGE_VARS_GET(chan, name, pvtid)
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3699
void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_bridge_channel **kick_me, unsigned int num_kick, unsigned int optimized)
Definition: bridge.c:2117
static void bridge_queue_action_nodup(struct ast_bridge *bridge, struct ast_frame *action)
Definition: bridge.c:303
void ast_bridge_set_sfu_video_mode(struct ast_bridge *bridge)
Set the bridge to be a selective forwarding unit.
Definition: bridge.c:3853
static int manager_bridge_tech_suspend(struct mansession *s, const struct message *m)
Definition: bridge.c:5530
static enum ast_transfer_result bridge_swap_attended_transfer(struct ast_bridge *dest_bridge, struct ast_bridge_channel *source_bridge_channel, struct ast_channel *swap_channel)
Definition: bridge.c:4647
static void bridge_manager_service(struct ast_bridge *bridge)
Definition: bridge.c:4948
int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature)
Unregister a handler for a built in feature.
Definition: bridge.c:3157
static unsigned int optimization_id
Definition: bridge.c:138
static int bridge_other_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags, enum ast_bridge_hook_type type)
Definition: bridge.c:3310
static void bridge_base_dissolving(struct ast_bridge *self)
Definition: bridge.c:893
int ast_bridge_features_limits_construct(struct ast_bridge_features_limits *limits)
Constructor function for ast_bridge_features_limits.
Definition: bridge.c:3475
void ast_bridge_set_maximum_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
Adjust the maximum mixing sample rate of a bridge used during multimix mode.
Definition: bridge.c:3798
static int hook_remove_match(void *obj, void *arg, int flags)
Definition: bridge.c:3524
void bridge_dissolve(struct ast_bridge *bridge, int cause)
Definition: bridge.c:326
static int manager_bridge_tech_unsuspend(struct mansession *s, const struct message *m)
Definition: bridge.c:5535
int ast_bridge_interval_hook(struct ast_bridge_features *features, enum ast_bridge_hook_timer_option flags, unsigned int interval, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach an interval hook to a bridge features structure.
Definition: bridge.c:3398
static void bridge_channel_impart_wait(struct bridge_channel_impart_cond *cond)
Definition: bridge.c:1670
static struct ast_cli_entry bridge_cli[]
Definition: bridge.c:5484
#define FORMAT_ROW
static int interval_hook_time_cmp(void *a, void *b)
Definition: bridge.c:3587
#define BLINDTRANSFER
Definition: bridge.c:147
void ast_bridge_set_video_update_discard(struct ast_bridge *bridge, unsigned int video_update_discard)
Set the amount of time to discard subsequent video updates after a video update has been sent.
Definition: bridge.c:3861
int ast_bridge_move_hook(struct ast_bridge_features *features, ast_bridge_move_indicate_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a bridge channel move detection hook to a bridge features structure.
Definition: bridge.c:3386
static const char * tech_capability2str(uint32_t capabilities)
Definition: bridge.c:5357
int ast_bridge_talk_detector_hook(struct ast_bridge_features *features, ast_bridge_talking_indicate_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a bridge channel talk detection hook to a bridge features structure.
Definition: bridge.c:3374
void ast_bridge_features_remove(struct ast_bridge_features *features, enum ast_bridge_hook_remove_flags remove_flags)
Remove marked bridge channel feature hooks.
Definition: bridge.c:3580
int ast_bridge_dtmf_hook(struct ast_bridge_features *features, const char *dtmf, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a DTMF hook to a bridge features structure.
Definition: bridge.c:3261
static void bridge_hook_destroy(void *vhook)
Definition: bridge.c:3218
static int channel_cmp(void *obj, void *arg, int flags)
Definition: bridge.c:4075
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)
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1947
int ast_bridge_queue_action(struct ast_bridge *bridge, struct ast_frame *action)
Put an action onto the specified bridge.
Definition: bridge.c:314
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:1009
static int bridge_sort_cmp(const void *obj_left, const void *obj_right, int flags)
Definition: bridge.c:5069
static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *chan1, struct ast_channel *chan2, struct ast_bridge *bridge1, struct ast_bridge *bridge2, struct ast_attended_transfer_message *transfer_msg)
Perform an attended transfer of a bridge.
Definition: bridge.c:4300
static int handle_manager_bridge_tech_suspend(struct mansession *s, const struct message *m, int suspend)
Definition: bridge.c:5496
static void bridge_manager_destroy(void *obj)
Definition: bridge.c:4998
static int bridge_dtmf_hook_sort(const void *obj_left, const void *obj_right, int flags)
Definition: bridge.c:3618
static void check_bridge_play_sounds(struct ast_bridge *bridge)
Definition: bridge.c:1272
static int try_merge_optimize_out(struct ast_bridge *chan_bridge, struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge, struct ast_bridge_channel *peer_bridge_channel, struct ast_unreal_pvt *pvt)
Definition: bridge.c:2948
void ast_bridge_features_set_flag(struct ast_bridge_features *features, unsigned int flag)
Set a flag on a bridge channel features structure.
Definition: bridge.c:3506
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:988
int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Invoke a built in feature hook now.
Definition: bridge.c:3169
void ast_brige_set_remb_behavior(struct ast_bridge *bridge, enum ast_bridge_video_sfu_remb_behavior behavior)
Set the REMB report generation behavior on a bridge.
Definition: bridge.c:3877
static void * bridge_manager_thread(void *data)
Definition: bridge.c:4965
struct ast_bridge * ast_bridge_transfer_acquire_bridge(struct ast_channel *chan)
Acquire the channel's bridge for transfer purposes.
Definition: bridge.c:4487
int ast_bridge_join_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a bridge channel join hook to a bridge features structure.
Definition: bridge.c:3354
static struct ast_bridge * optimize_lock_chan_stack(struct ast_channel *chan)
Definition: bridge.c:2658
static int complete_bridge_live_search(void *obj, void *arg, int flags)
Definition: bridge.c:5096
struct ast_bridge * bridge_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Definition: bridge.c:713
static int bridge_merge_locked(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, int merge_best_direction, struct ast_channel **kick_me, unsigned int num_kick)
Definition: bridge.c:2285
static enum bridge_allow_merge bridges_allow_merge_optimization(struct ast_bridge *chan_bridge, struct ast_bridge *peer_bridge, int num_kick_channels, struct merge_direction *merge)
Definition: bridge.c:2914
static int bridge_move_locked(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_channel *chan, struct ast_channel *swap, int attempt_recovery)
Definition: bridge.c:2468
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3762
static void bridge_channel_impart_ds_head_dtor(void *doomed)
Definition: bridge.c:1577
int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
Remove a channel from a bridge.
Definition: bridge.c:2020
void ast_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
Sets BRIDGECHANNEL and BRIDGEPVTCALLID for a channel.
Definition: bridge.c:1281
struct ast_bridge * bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Initialize the base class of the bridge.
Definition: bridge.c:783
void ast_bridge_merge_inhibit(struct ast_bridge *bridge, int request)
Adjust the bridge merge inhibit request count.
Definition: bridge.c:3079
static void fill_bridgepeer_buf(char *buf, unsigned int cur_idx, const char *names[], unsigned int num_names)
Definition: bridge.c:1338
void bridge_reconfigured(struct ast_bridge *bridge, unsigned int colp_update)
Definition: bridge.c:1472
static char * handle_bridge_technology_suspend(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: bridge.c:5431
int ast_bridge_kick(struct ast_bridge *bridge, struct ast_channel *chan)
Kick a channel from a bridge.
Definition: bridge.c:2048
static int smart_bridge_operation(struct ast_bridge *bridge)
Definition: bridge.c:1041
void bridge_channel_impart_signal(struct ast_channel *chan)
Definition: bridge.c:1651
static int bridge_base_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
Definition: bridge.c:917
static int bridge_base_get_merge_priority(struct ast_bridge *self)
Definition: bridge.c:963
static ast_bridge_builtin_set_limits_fn builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_END]
Definition: bridge.c:161
static ast_bridge_hook_callback builtin_features_handlers[AST_BRIDGE_BUILTIN_END]
Definition: bridge.c:158
static int merge_container_cb(void *obj, void *data, int flags)
Callback for merging hook ao2_containers.
Definition: bridge.c:3641
static char * handle_bridge_technology_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: bridge.c:5377
struct ast_bridge * ast_bridge_find_by_id(const char *bridge_id)
Find bridge by id.
Definition: bridge.c:5091
struct ast_channel * ast_bridge_peer(struct ast_bridge *bridge, struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: bridge.c:4154
struct ast_bridge_channel * bridge_find_channel(struct ast_bridge *bridge, struct ast_channel *chan)
Definition: bridge.c:1498
static char * handle_bridge_kick_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: bridge.c:5291
int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan)
Suspend a channel temporarily from a bridge.
Definition: bridge.c:3086
static void bridge_prnt_obj(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: bridge.c:5593
static const struct ast_datastore_info bridge_channel_impart_ds_info
Definition: bridge.c:1601
void ast_bridge_set_single_src_video_mode(struct ast_bridge *bridge, struct ast_channel *video_src_chan)
Set a bridge to feed a single video source to all participants.
Definition: bridge.c:3828
void ast_bridge_set_mixing_interval(struct ast_bridge *bridge, unsigned int mixing_interval)
Adjust the internal mixing interval of a bridge used during multimix mode.
Definition: bridge.c:3777
static struct ast_bridge * optimize_lock_peer_stack(struct ast_channel *peer)
Definition: bridge.c:2703
struct ao2_container * ast_bridge_peers(struct ast_bridge *bridge)
Get a container of all channels in the bridge.
Definition: bridge.c:4115
#define MAX_BRIDGEPEER_CHANS
static void set_transfer_variables_all(struct ast_channel *transferer, struct ao2_container *channels, int is_attended)
Definition: bridge.c:4462
static void bridge_base_destroy(struct ast_bridge *self)
Definition: bridge.c:880
void ast_bridge_features_merge(struct ast_bridge_features *into, const struct ast_bridge_features *from)
Merge one ast_bridge_features into another.
Definition: bridge.c:3674
static int try_swap_optimize_out(struct ast_bridge *chan_bridge, struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge, struct ast_bridge_channel *peer_bridge_channel, struct ast_unreal_pvt *pvt)
Definition: bridge.c:2824
static void wrap_hook(struct ast_bridge_features *features, struct ast_bridge_hook_timer *hook)
Wrap the provided interval hook and add it to features.
Definition: bridge.c:3662
struct ast_bridge * bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
Definition: bridge.c:747
void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
remove a channel as a source of video for the bridge.
Definition: bridge.c:3996
enum ast_transfer_result ast_bridge_transfer_blind(int is_external, struct ast_channel *transferer, const char *exten, const char *context, transfer_channel_cb new_channel_cb, void *user_data)
Blind transfer target to the extension and context provided.
Definition: bridge.c:4504
static void destroy_bridge(void *obj)
Definition: bridge.c:659
bridge_allow_swap
Definition: bridge.c:2751
@ SWAP_PROHIBITED
Definition: bridge.c:2753
@ SWAP_TO_PEER_BRIDGE
Definition: bridge.c:2757
@ SWAP_TO_CHAN_BRIDGE
Definition: bridge.c:2755
static int interval_wrapper_cb(struct ast_bridge_channel *bridge_channel, void *obj)
Wrapper for interval hooks that calls into the wrapped hook.
Definition: bridge.c:3648
const char * ast_bridge_video_mode_to_string(enum ast_bridge_video_mode_type video_mode)
Converts an enum representation of a bridge video mode to string.
Definition: bridge.c:4030
static void hooks_remove_container(struct ao2_container *hooks, enum ast_bridge_hook_remove_flags remove_flags)
Definition: bridge.c:3544
static void bridge_reconfigured_connected_line_update(struct ast_bridge *bridge)
Definition: bridge.c:404
static void cleanup_video_mode(struct ast_bridge *bridge)
Definition: bridge.c:3805
int ast_bridge_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, int merge_best_direction, struct ast_channel **kick_me, unsigned int num_kick)
Merge two bridges together.
Definition: bridge.c:2369
#define BRIDGE_LOCK_ONE_OR_BOTH(b1, b2)
static enum ast_transfer_result try_parking(struct ast_channel *transferer, const char *context, const char *exten, transfer_channel_cb new_channel_cb, struct transfer_channel_data *user_data_wrapper)
Definition: bridge.c:4405
static struct ao2_container * bridges
Definition: bridge.c:132
int ast_bridge_leave_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a bridge channel leave hook to a bridge features structure.
Definition: bridge.c:3364
int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan)
Unsuspend a channel from a bridge.
Definition: bridge.c:3107
void ast_bridge_set_send_sdp_label(struct ast_bridge *bridge, unsigned int send_sdp_label)
Controls whether to send a "label" attribute in each stream in an SDP.
Definition: bridge.c:4045
int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_bridge_features *features, int play_tone, const char *xfersound)
Add an arbitrary channel to a bridge.
Definition: bridge.c:2540
int ast_bridge_interval_register(enum ast_bridge_builtin_interval interval, ast_bridge_builtin_set_limits_fn callback)
Register a handler for a built in interval feature.
Definition: bridge.c:3186
static void set_bridge_peer_vars_multiparty(struct ast_bridge *bridge)
Definition: bridge.c:1375
static char * complete_bridge_live(const char *word)
Definition: bridge.c:5107
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3732
static void bridge_action_bridge(struct ast_bridge *bridge, struct ast_frame *action)
Definition: bridge.c:607
bridge_allow_merge
Definition: bridge.c:2890
@ MERGE_ALLOWED
Definition: bridge.c:2898
@ MERGE_NOT_ENOUGH_CHANNELS
Definition: bridge.c:2894
@ MERGE_NO_MULTIMIX
Definition: bridge.c:2896
@ MERGE_PROHIBITED
Definition: bridge.c:2892
static enum ast_transfer_result blind_transfer_bridge(int is_external, struct ast_channel *transferer, struct ast_bridge *bridge, const char *exten, const char *context, struct ast_channel *transferee, transfer_channel_cb new_channel_cb, struct transfer_channel_data *user_data_wrapper, struct ast_blind_transfer_message *transfer_message)
Definition: bridge.c:4190
static struct ast_bridge_hook * bridge_hook_generic(size_t size, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Definition: bridge.c:3241
void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyframe)
Update information about talker energy for talker src video mode.
Definition: bridge.c:3895
static void bridge_cleanup(void)
Definition: bridge.c:5609
static void bridge_channel_change_bridge(struct ast_bridge_channel *bridge_channel, struct ast_bridge *new_bridge)
Definition: bridge.c:2076
static struct bridge_manager_controller * bridge_manager_create(void)
Definition: bridge.c:5030
static char * handle_bridge_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: bridge.c:5115
static void bridge_handle_actions(struct ast_bridge *bridge)
Definition: bridge.c:641
static int bridge_impart_internal(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags, struct bridge_channel_impart_cond *cond)
Definition: bridge.c:1846
static void * bridge_channel_depart_thread(void *data)
Thread responsible for imparted bridged channels to be departed.
Definition: bridge.c:1780
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition: bridge.c:274
static void bridge_complete_join(struct ast_bridge *bridge)
Definition: bridge.c:493
int ast_bridge_interval_unregister(enum ast_bridge_builtin_interval interval)
Unregisters a handler for a built in interval feature.
Definition: bridge.c:3198
#define ATTENDEDTRANSFER
Definition: bridge.c:150
int ast_bridge_unreal_optimize_out(struct ast_channel *chan, struct ast_channel *peer, struct ast_unreal_pvt *pvt)
Check and optimize out the unreal channels between bridges.
Definition: bridge.c:2999
static void kick_it(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
Definition: bridge.c:2043
static char * complete_bridge_participant(const char *bridge_name, const char *word)
Definition: bridge.c:5263
void ast_bridge_technology_suspend(struct ast_bridge_technology *technology)
Suspend a bridge technology from consideration.
Definition: bridge.c:3126
int __ast_bridge_technology_register(struct ast_bridge_technology *technology, struct ast_module *module)
Register a bridge technology for use.
Definition: bridge.c:223
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3753
int ast_bridge_features_enable(struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Enable a built in feature on a bridge features structure.
Definition: bridge.c:3444
enum ast_bridge_optimization ast_bridges_allow_optimization(struct ast_bridge *chan_bridge, struct ast_bridge *peer_bridge)
Determine if bridges allow for optimization to occur betweem them.
Definition: bridge.c:3039
static void check_bridge_play_sound(struct ast_bridge_channel *bridge_channel)
Definition: bridge.c:1244
int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel, int attempt_recovery, unsigned int optimized)
Definition: bridge.c:2383
static void set_bridge_peer_vars(struct ast_bridge *bridge)
Definition: bridge.c:1455
static int bridge_channel_impart_add(struct ast_channel *chan, struct bridge_channel_impart_cond *cond)
Definition: bridge.c:1618
int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
Determine if a channel is a video src for the bridge.
Definition: bridge.c:3970
static void bridge_channel_moving(struct ast_bridge_channel *bridge_channel, struct ast_bridge *src, struct ast_bridge *dst)
Definition: bridge.c:2091
static struct ast_bridge_technology * find_best_technology(uint32_t capabilities, struct ast_bridge *bridge)
Helper function used to find the "best" bridge technology given specified capabilities.
Definition: bridge.c:518
static void bridge_manager_service_req(struct ast_bridge *bridge)
Definition: bridge.c:197
static char * complete_bridge_technology(const char *word)
Definition: bridge.c:5412
void ast_bridge_features_limits_destroy(struct ast_bridge_features_limits *limits)
Destructor function for ast_bridge_features_limits.
Definition: bridge.c:3486
void bridge_merge_inhibit_nolock(struct ast_bridge *bridge, int request)
Definition: bridge.c:3070
int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_hook_callback callback, const char *dtmf)
Register a handler for a built in feature.
Definition: bridge.c:3141
static struct merge_direction bridge_merge_determine_direction(struct ast_bridge *bridge1, struct ast_bridge *bridge2)
Definition: bridge.c:2222
static void bridge_base_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
Definition: bridge.c:932
static void bridge_dissolve_check_stolen(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Definition: bridge.c:374
void ast_bridge_set_remb_send_interval(struct ast_bridge *bridge, unsigned int remb_send_interval)
Set the interval at which a combined REMB frame will be sent to video sources.
Definition: bridge.c:3868
static enum bridge_allow_swap bridges_allow_swap_optimization(struct ast_bridge *chan_bridge, struct ast_bridge *peer_bridge)
Definition: bridge.c:2768
static char * handle_bridge_show_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: bridge.c:5179
void ast_bridge_notify_masquerade(struct ast_channel *chan)
Notify bridging that this channel was just masqueraded.
Definition: bridge.c:1511
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4756
static int bridge_show_specific_print_channel(void *obj, void *arg, int flags)
Internal callback function for sending channels in a bridge to the CLI.
Definition: bridge.c:5162
int ast_bridge_move(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_channel *chan, struct ast_channel *swap, int attempt_recovery)
Move a channel from one bridge to another.
Definition: bridge.c:2529
static void bridge_tech_deferred_destroy(struct ast_bridge *bridge, struct ast_frame *action)
Definition: bridge.c:579
static void bridge_base_notify_masquerade(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
Definition: bridge.c:947
static int bridge_allows_optimization(struct ast_bridge *bridge)
Definition: bridge.c:2639
void ast_bridge_set_internal_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
Adjust the internal mixing sample rate of a bridge used during multimix mode.
Definition: bridge.c:3791
static ast_mutex_t bridge_init_lock
Definition: bridge.c:136
static void interval_wrapper_pvt_dtor(void *obj)
Destructor for the hook wrapper.
Definition: bridge.c:3656
#define FORMAT_HDR
static void * bridge_channel_ind_thread(void *data)
Thread responsible for independent imparted bridged channels.
Definition: bridge.c:1811
static void set_bridge_peer_vars_holding(struct ast_bridge *bridge)
Definition: bridge.c:1435
Bridging API.
#define ast_bridge_lock_both(bridge1, bridge2)
Lock two bridges.
Definition: bridge.h:492
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:485
ast_bridge_optimization
Tells, if optimization is allowed, how the optimization would be performed.
Definition: bridge.h:878
@ AST_BRIDGE_OPTIMIZE_PROHIBITED
Definition: bridge.h:888
@ AST_BRIDGE_OPTIMIZE_MERGE_TO_CHAN_BRIDGE
Definition: bridge.h:884
@ AST_BRIDGE_OPTIMIZE_SWAP_TO_PEER_BRIDGE
Definition: bridge.h:882
@ AST_BRIDGE_OPTIMIZE_MERGE_TO_PEER_BRIDGE
Definition: bridge.h:886
@ AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE
Definition: bridge.h:880
ast_bridge_video_sfu_remb_behavior
REMB report behaviors.
Definition: bridge.h:135
#define ast_bridge_trylock(bridge)
Try locking the bridge.
Definition: bridge.h:463
@ AST_BRIDGE_CAPABILITY_EARLY
Definition: bridge.h:92
@ AST_BRIDGE_CAPABILITY_MULTIMIX
Definition: bridge.h:98
@ AST_BRIDGE_CAPABILITY_NATIVE
Definition: bridge.h:94
@ AST_BRIDGE_CAPABILITY_1TO1MIX
Definition: bridge.h:96
@ AST_BRIDGE_CAPABILITY_HOLDING
Definition: bridge.h:90
@ AST_BRIDGE_TRANSFER_MULTI_PARTY
Definition: bridge.h:1117
void(* transfer_channel_cb)(struct ast_channel *chan, struct transfer_channel_data *user_data, enum ast_transfer_type transfer_type)
Callback function type called during blind transfers.
Definition: bridge.h:1147
ast_transfer_result
Definition: bridge.h:1102
@ AST_BRIDGE_TRANSFER_NOT_PERMITTED
Definition: bridge.h:1106
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1104
@ AST_BRIDGE_TRANSFER_INVALID
Definition: bridge.h:1108
@ AST_BRIDGE_TRANSFER_FAIL
Definition: bridge.h:1110
ast_bridge_video_mode_type
Video source modes.
Definition: bridge.h:102
@ AST_BRIDGE_VIDEO_MODE_SINGLE_SRC
Definition: bridge.h:106
@ AST_BRIDGE_VIDEO_MODE_TALKER_SRC
Definition: bridge.h:109
@ AST_BRIDGE_VIDEO_MODE_NONE
Definition: bridge.h:104
@ AST_BRIDGE_VIDEO_MODE_SFU
Definition: bridge.h:113
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:474
ast_bridge_impart_flags
Definition: bridge.h:588
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
Definition: bridge.h:592
@ AST_BRIDGE_IMPART_CHAN_MASK
Definition: bridge.h:590
@ AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP
Definition: bridge.h:596
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:594
#define BRIDGE_PRINTF_VARS(bridge)
Definition: bridge.h:80
ast_bridge_join_flags
Definition: bridge.h:537
@ AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP
Definition: bridge.h:541
@ AST_BRIDGE_JOIN_PASS_REFERENCE
Definition: bridge.h:539
#define BRIDGE_PRINTF_SPEC
Definition: bridge.h:79
After Bridge Execution API.
void ast_bridge_discard_after_callback(struct ast_channel *chan, enum ast_bridge_after_cb_reason reason)
Run discarding any after bridge callbacks.
Definition: bridge_after.c:239
@ AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED
Definition: bridge_after.h:49
@ AST_BRIDGE_AFTER_CB_REASON_DEPART
Definition: bridge_after.h:45
void ast_bridge_run_after_goto(struct ast_channel *chan)
Run a PBX on any after bridge goto location.
Definition: bridge_after.c:525
int ast_bridge_setup_after_goto(struct ast_channel *chan)
Setup any after bridge goto location to begin execution.
Definition: bridge_after.c:435
void ast_bridge_run_after_callback(struct ast_channel *chan)
Run any after bridge callback.
Definition: bridge_after.c:212
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
Definition: bridge_after.c:384
Basic bridge subclass API.
void ast_bridging_init_basic(void)
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
Write an unhold frame into the bridge.
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel, int cause)
Kick the channel out of the bridge.
void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel)
Maps a channel's stream topology to and from the bridge.
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.
#define ast_bridge_channel_trylock(bridge_channel)
Try locking the bridge_channel.
struct ast_bridge_channel * ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel)
Get the peer bridge channel of a two party bridge.
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
@ BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE
@ BRIDGE_CHANNEL_STATE_WAIT
@ BRIDGE_CHANNEL_STATE_END
int ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame onto the bridge channel with data.
int ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
Queue a bridge action play file frame onto the bridge channel.
int ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
Write a bridge action play file frame into the bridge.
@ BRIDGE_CHANNEL_THREAD_SIMPLE
@ BRIDGE_CHANNEL_THREAD_IDLE
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
int ast_bridge_channel_queue_callback(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_custom_callback_option flags, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size)
Queue a bridge action custom callback frame onto the bridge channel.
Private Bridging Channel API.
void bridge_channel_internal_unsuspend_nolock(struct ast_bridge_channel *bridge_channel)
void bridge_channel_internal_suspend_nolock(struct ast_bridge_channel *bridge_channel)
void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct ast_bridge_channel *bridge_channel)
int bridge_channel_internal_push_full(struct ast_bridge_channel *bridge_channel, int optimized)
int bridge_channel_internal_queue_blind_transfer(struct ast_channel *transferee, const char *exten, const char *context, transfer_channel_cb new_channel_cb, void *user_data)
int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel)
int bridge_channel_internal_allows_optimization(struct ast_bridge_channel *bridge_channel)
int bridge_channel_internal_queue_attended_transfer(struct ast_channel *transferee, struct ast_channel *unbridged_chan)
struct ast_bridge_channel * bridge_channel_internal_alloc(struct ast_bridge *bridge)
void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel)
int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel)
@ BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY
@ BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING
void bridge_channel_queue_deferred_frames(struct ast_bridge_channel *bridge_channel)
Channel Bridging API.
int(* ast_bridge_move_indicate_callback)(struct ast_bridge_channel *bridge_channel, void *hook_pvt, struct ast_bridge *src, struct ast_bridge *dst)
Move indicator callback.
ast_bridge_hook_type
@ AST_BRIDGE_HOOK_TYPE_JOIN
@ AST_BRIDGE_HOOK_TYPE_HANGUP
@ AST_BRIDGE_HOOK_TYPE_MOVE
@ AST_BRIDGE_HOOK_TYPE_DTMF
@ AST_BRIDGE_HOOK_TYPE_LEAVE
@ AST_BRIDGE_HOOK_TYPE_TALK
@ AST_BRIDGE_HOOK_TYPE_TIMER
ast_bridge_hook_remove_flags
@ AST_BRIDGE_HOOK_REMOVE_ON_PULL
ast_bridge_builtin_feature
Built in DTMF features.
@ AST_BRIDGE_BUILTIN_END
@ AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY
@ AST_BRIDGE_FLAG_SWAP_INHIBIT_TO
@ AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM
@ AST_BRIDGE_FLAG_TRANSFER_PROHIBITED
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO
@ AST_BRIDGE_FLAG_SMART
@ AST_BRIDGE_FLAG_MASQUERADE_ONLY
@ AST_BRIDGE_FLAG_DISSOLVE_HANGUP
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
@ AST_BRIDGE_FLAG_INVISIBLE
#define MAXIMUM_DTMF_FEATURE_STRING
Maximum length of a DTMF feature string.
ast_bridge_hook_timer_option
int(* ast_bridge_builtin_set_limits_fn)(struct ast_bridge_features *features, struct ast_bridge_features_limits *limits, enum ast_bridge_hook_remove_flags remove_flags)
Attach interval hooks to a bridge features structure.
int(* ast_bridge_talking_indicate_callback)(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
Talking indicator callback.
@ AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE
@ AST_BRIDGE_CHANNEL_FLAG_LONELY
@ AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP
int(* ast_bridge_hook_callback)(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Hook callback type.
void(* ast_bridge_hook_pvt_destructor)(void *hook_pvt)
Hook pvt destructor callback.
ast_bridge_builtin_interval
@ AST_BRIDGE_BUILTIN_INTERVAL_LIMITS
@ AST_BRIDGE_BUILTIN_INTERVAL_END
static void deferred_action(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
Private Bridging API.
Channel Bridging API.
Internal Asterisk hangup causes.
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
static void suspend(struct cc_core_instance *core_instance)
Definition: ccss.c:3166
static struct ast_timer * timer
Definition: chan_iax2.c:388
static const char type[]
Definition: chan_ooh323.c:109
static const char config[]
Definition: chan_ooh323.c:111
static int request(void *obj)
Definition: chan_pjsip.c:2619
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_bridge * ast_channel_internal_bridge(const struct ast_channel *chan)
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6429
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2355
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2511
@ AST_CHANNEL_REQUESTOR_REPLACEMENT
Definition: channel.h:1527
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2040
void ast_channel_internal_bridge_channel_set(struct ast_channel *chan, struct ast_bridge_channel *value)
#define ast_channel_lock(chan)
Definition: channel.h:2972
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition: channel.c:10607
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2979
@ AST_FLAG_ZOMBIE
Definition: channel.h:1007
@ AST_FLAG_EMULATE_DTMF
Definition: channel.h:1024
const char * ast_channel_uniqueid(const struct ast_channel *chan)
void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
Definition: channel.c:6402
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:459
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1381
#define ast_channel_trylock(chan)
Definition: channel.h:2974
const char * ast_channel_appl(const struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_internal_bridge_channel(const struct ast_channel *chan)
void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value)
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10548
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1146
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2441
struct ast_readq_list * ast_channel_readq(struct ast_channel *chan)
int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Build the connected line information data frame.
Definition: channel.c:8711
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
#define AST_MAX_CONTEXT
Definition: channel.h:135
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:1990
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10596
const char * ast_cause2str(int cause) attribute_pure
Gives the string form of a given cause code.
Definition: channel.c:612
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8307
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2428
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3019
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2776
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4243
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition: channel.c:6322
#define ast_channel_unlock(chan)
Definition: channel.h:2973
#define AST_MAX_EXTENSION
Definition: channel.h:134
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2369
int ast_channel_has_audio_frame_or_monitor(struct ast_channel *chan)
Check if the channel has active audiohooks, active framehooks, or a monitor.
Definition: channel.c:2488
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
size_t current
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition: cli.h:71
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2737
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1823
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
@ AST_MEDIA_TYPE_END
Definition: codec.h:36
static struct channel_usage channels
short word
static struct ao2_container * locals
Definition: core_local.c:150
Local proxy channel special access.
void ast_local_unlock_all(void *tech_pvt, struct ast_channel *base_chan, struct ast_channel *base_owner)
Remove a reference to the given local channel's private tech, unlock the given local channel's privat...
Definition: core_local.c:268
int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)
Setup the outgoing local channel to join a bridge on ast_call().
Definition: core_local.c:613
void ast_local_lock_all(struct ast_channel *chan, void **tech_pvt, struct ast_channel **base_chan, struct ast_channel **base_owner)
Add a reference to the local channel's private tech, lock the local channel's private base,...
Definition: core_local.c:253
int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq)
Setup the outgoing local channel to masquerade into a channel on ast_call().
Definition: core_local.c:655
Unreal channel derivative framework.
@ AST_UNREAL_CHAN
Definition: core_unreal.h:51
@ AST_UNREAL_OWNER
Definition: core_unreal.h:50
#define AST_UNREAL_OPTIMIZE_BEGUN
Definition: core_unreal.h:110
#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
char connected
Definition: eagi_proxy.c:82
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
long int flag
Definition: f2c.h:83
Call Parking and Pickup API Includes code and algorithms from the Zapata library.
Generic File Format Support. Should be included by clients of the file handling routines....
int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_media_type type)
Find out if the capabilities structure has any formats of a specific type.
Definition: format_cap.c:613
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2024
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1982
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2060
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2014
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1643
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2068
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1903
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7698
#define SCOPE_TRACE(__level,...)
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_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
Max Heap data structure.
struct ast_heap * ast_heap_destroy(struct ast_heap *h)
Destroy a max heap.
Definition: heap.c:146
#define ast_heap_create(init_height, cmp_fn, index_offset)
Create a max heap.
Definition: heap.h:100
#define ast_heap_unlock(h)
Definition: heap.h:249
void * ast_heap_pop(struct ast_heap *h)
Pop the max element off of the heap.
Definition: heap.c:262
void * ast_heap_remove(struct ast_heap *h, void *elm)
Remove a specific element from a heap.
Definition: heap.c:251
size_t ast_heap_size(struct ast_heap *h)
Get the current size of a heap.
Definition: heap.c:276
#define ast_heap_push(h, elm)
Push an element on to a heap.
Definition: heap.h:125
#define ast_heap_wrlock(h)
Definition: heap.h:247
void * ast_heap_peek(struct ast_heap *h, unsigned int index)
Peek at an element on a heap.
Definition: heap.c:267
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define ast_frdup(fr)
Copies a frame.
#define ast_frfree(fr)
@ AST_FRAME_BRIDGE_ACTION
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_CONNECTED_LINE
Support for logging to various files, console and syslog Configuration in file logger....
#define AST_LOG_WARNING
int ast_callid_threadassoc_change(ast_callid callid)
Sets what is stored in the thread storage to the given callid if it does not match what is already th...
Definition: logger.c:2277
#define ast_debug(level,...)
Log a DEBUG message.
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:2268
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:2290
#define LOG_ERROR
#define AST_LOG_NOTICE
#define ast_verb(level,...)
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:225
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
Definition: linkedlists.h:333
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
Asterisk locking-related definitions:
#define ast_cond_destroy(cond)
Definition: lock.h:209
#define ast_cond_wait(cond, mutex)
Definition: lock.h:212
#define AST_PTHREADT_NULL
Definition: lock.h:73
#define ast_cond_init(cond, attr)
Definition: lock.h:208
#define ast_mutex_init(pmutex)
Definition: lock.h:193
#define ast_mutex_unlock(a)
Definition: lock.h:197
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:764
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:590
pthread_cond_t ast_cond_t
Definition: lock.h:185
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
Definition: lock.h:596
#define ast_mutex_destroy(a)
Definition: lock.h:195
#define ast_mutex_lock(a)
Definition: lock.h:196
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:527
#define ast_cond_signal(cond)
Definition: lock.h:210
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:203
Asterisk module definitions.
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:469
Music on hold handling.
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7758
Options provided by main asterisk program.
Call Parking API.
int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
Perform a blind transfer to a parking extension.
Definition: parking.c:143
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
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.
unsigned char publish
Definition: res_corosync.c:241
#define NULL
Definition: resample.c:96
Say numbers and dates (maybe words one day too)
void ast_bridge_publish_merge(struct ast_bridge *to, struct ast_bridge *from)
Publish a bridge merge.
void ast_bridge_publish_attended_transfer(struct ast_attended_transfer_message *transfer_msg)
Publish an attended transfer.
void ast_bridge_publish_blind_transfer(struct ast_blind_transfer_message *transfer_message)
Publish a blind transfer event.
int ast_bridge_topic_exists(const char *uniqueid)
Check if a stasis topic exists for a bridge uniqueid.
int ast_attended_transfer_message_add_app(struct ast_attended_transfer_message *transfer_msg, const char *app, struct ast_channel *replace_channel)
Add details for an attended transfer to an application.
struct ast_bridge_snapshot * ast_bridge_get_snapshot(struct ast_bridge *bridge)
Returns the current snapshot for the bridge.
int bridge_topics_init(struct ast_bridge *bridge)
struct ast_bridge_snapshot * ast_bridge_get_snapshot_by_uniqueid(const char *bridge_id)
Returns the current snapshot for the bridge.
struct ast_bridge_snapshot * ast_bridge_snapshot_create(struct ast_bridge *bridge)
Generate a snapshot of the bridge state. This is an ao2 object, so ao2_cleanup() to deallocate.
void ast_bridge_publish_state(struct ast_bridge *bridge)
Publish the state of a bridge.
struct ast_attended_transfer_message * ast_attended_transfer_message_create(int is_external, struct ast_channel *to_transferee, struct ast_bridge *transferee_bridge, struct ast_channel *to_transfer_target, struct ast_bridge *target_bridge, struct ast_channel *transferee, struct ast_channel *transfer_target)
Create an Attended transfer message to be published.
int ast_attended_transfer_message_add_merge(struct ast_attended_transfer_message *transfer_msg, struct ast_bridge *final_bridge)
Add details for a bridge merge to an attended transfer message.
int ast_attended_transfer_message_add_link(struct ast_attended_transfer_message *transfer_msg, struct ast_channel *locals[2])
Add details for an attended transfer that has a link between bridges.
struct stasis_topic * ast_bridge_topic(struct ast_bridge *bridge)
A topic which publishes the events for a particular bridge.
int ast_stasis_bridging_init(void)
void bridge_topics_destroy(struct ast_bridge *bridge)
struct ast_blind_transfer_message * ast_blind_transfer_message_create(int is_external, struct ast_channel *transferer, const char *exten, const char *context)
Create a blind transfer message to be published.
Caching pattern for Stasis Message Bus API topics.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#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_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
#define AST_YESNO(x)
return Yes or No depending on the argument.
Definition: strings.h:143
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
Message representing attended transfer.
Message published during a blind transfer.
struct ast_channel_snapshot * replace_channel
Structure that contains information regarding a channel in a bridge.
unsigned int suspended
struct ast_channel * swap
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_bridge_features * features
unsigned int just_joined
struct ast_channel * chan
enum bridge_channel_state state
unsigned int inhibit_colp
unsigned int depart_wait
enum bridge_channel_thread_state activity
The bridge channel thread activity.
struct ast_bridge_tech_optimizations tech_args
struct ast_bridge_channel::@196 entry
unsigned int in_bridge
Structure that contains configuration information for the limits feature.
Structure that contains features information.
struct ao2_container * other_hooks
struct ao2_container * dtmf_hooks
unsigned int interval_sequence
unsigned int dtmf_passthrough
struct ast_heap * interval_hooks
unsigned int text_messaging
struct ast_flags feature_flags
char code[MAXIMUM_DTMF_FEATURE_STRING]
struct ast_bridge_hook generic
struct ast_bridge_hook_dtmf_parms dtmf
struct ast_bridge_hook generic
struct ast_bridge_hook_timer_parms timer
Structure that is the essence of a feature hook.
struct ast_flags remove_flags
ast_bridge_hook_pvt_destructor destructor
enum ast_bridge_hook_type type
ast_bridge_hook_callback callback
Bridge virtual methods table definition.
Definition: bridge.h:261
ast_bridge_dissolving_fn dissolving
Definition: bridge.h:267
ast_bridge_push_channel_fn push
Definition: bridge.h:269
const char * name
Definition: bridge.h:263
ast_bridge_notify_masquerade_fn notify_masquerade
Definition: bridge.h:273
ast_bridge_destructor_fn destroy
Definition: bridge.h:265
ast_bridge_merge_priority_fn get_merge_priority
Definition: bridge.h:275
ast_bridge_pull_channel_fn pull
Definition: bridge.h:271
ast_bridge_push_channel_fn push_peek
Definition: bridge.h:277
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:318
enum ast_bridge_video_mode_type video_mode
Definition: bridge.h:345
struct timeval creationtime
Definition: bridge.h:347
unsigned int num_active
Definition: bridge.h:343
const ast_string_field video_source_id
Definition: bridge.h:332
const ast_string_field creator
Definition: bridge.h:332
const ast_string_field uniqueid
Definition: bridge.h:332
unsigned int num_channels
Definition: bridge.h:341
const ast_string_field technology
Definition: bridge.h:332
const ast_string_field name
Definition: bridge.h:332
struct ao2_container * channels
Definition: bridge.h:335
const ast_string_field subclass
Definition: bridge.h:332
unsigned int send_sdp_label
Definition: bridge.h:304
unsigned int maximum_sample_rate
The maximum sample rate softmix uses to mix channels.
Definition: bridge.h:310
unsigned int internal_sample_rate
The internal sample rate softmix uses to mix channels.
Definition: bridge.h:289
unsigned int binaural_active
Definition: bridge.h:299
struct ast_bridge_video_mode video_mode
Definition: bridge.h:283
unsigned int internal_mixing_interval
The mixing interval indicates how quickly softmix mixing should occur to mix audio.
Definition: bridge.h:297
Structure specific to bridge technologies capable of performing talking optimizations.
Structure that is the essence of a bridge technology.
void(* destroy)(struct ast_bridge *bridge)
Destroy a bridging technology instance for a bridge.
int(* start)(struct ast_bridge *bridge)
Request a bridge technology instance start operations.
void(* stream_topology_changed)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Callback for when a stream topology changes on the channel.
struct ast_module * mod
int(* write)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
Write a frame into the bridging technology instance for a bridge.
int(* compatible)(struct ast_bridge *bridge)
Check if a bridge is compatible with the bridging technology.
void(* stop)(struct ast_bridge *bridge)
Request a bridge technology instance stop in preparation for being destroyed.
int(* join)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Add a channel to a bridging technology instance for a bridge.
int(* create)(struct ast_bridge *bridge)
Create a bridge technology instance for a bridge.
enum ast_bridge_preference preference
void(* leave)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Remove a channel from a bridging technology instance for a bridge.
union ast_bridge_video_mode::@194 mode_data
struct ast_bridge_video_single_src_data single_src_data
Definition: bridge.h:167
struct ast_bridge_video_talker_src_data talker_src_data
Definition: bridge.h:168
unsigned int video_update_discard
Definition: bridge.h:172
enum ast_bridge_video_mode_type mode
Definition: bridge.h:164
struct ast_bridge_video_sfu_data sfu_data
Definition: bridge.h:169
unsigned int remb_send_interval
Definition: bridge.h:155
enum ast_bridge_video_sfu_remb_behavior remb_behavior
Definition: bridge.h:157
struct ast_channel * chan_vsrc
Definition: bridge.h:120
This is used for both SINGLE_SRC_TALKER mode to set what channel should be the current single video f...
Definition: bridge.h:125
struct ast_channel * chan_old_vsrc
Definition: bridge.h:131
struct ast_channel * chan_vsrc
Definition: bridge.h:127
Structure that contains information about a bridge.
Definition: bridge.h:353
struct ast_bridge_softmix softmix
Definition: bridge.h:371
void * tech_pvt
Definition: bridge.h:361
struct ast_vector_int media_types
Definition: bridge.h:408
struct timeval creationtime
Definition: bridge.h:412
const struct ast_bridge_methods * v_table
Definition: bridge.h:355
unsigned int reconfigured
Definition: bridge.h:392
unsigned int num_active
Definition: bridge.h:379
ast_callid callid
Definition: bridge.h:365
const ast_string_field creator
Definition: bridge.h:405
const ast_string_field uniqueid
Definition: bridge.h:405
struct ast_bridge_channels_list channels
Definition: bridge.h:367
struct ast_bridge_snapshot * current_snapshot
Definition: bridge.h:410
unsigned int num_channels
Definition: bridge.h:377
unsigned int dissolved
Definition: bridge.h:394
int cause
Definition: bridge.h:390
struct ast_bridge_technology * technology
Definition: bridge.h:359
unsigned int construction_completed
Definition: bridge.h:396
struct ast_bridge::@195 action_queue
const ast_string_field name
Definition: bridge.h:405
unsigned int num_lonely
Definition: bridge.h:381
unsigned int inhibit_merge
Count of the active temporary requests to inhibit bridge merges. Zero if merges are allowed.
Definition: bridge.h:388
struct ast_flags feature_flags
Definition: bridge.h:373
uint32_t allowed_capabilities
Definition: bridge.h:375
const ast_string_field name
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_base * base
Main Channel structure associated with a channel.
struct ast_bridge_channel * bridge_channel
struct ast_bridge * bridge
char exten[AST_MAX_EXTENSION]
const char * data
const struct ast_channel_tech * tech
struct ast_flags flags
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
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
unsigned int flags
Definition: utils.h:218
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@231 data
Definition: heap.c:36
Structure for mutex and tracking information.
Definition: lock.h:142
Connected Line/Party information.
Definition: channel.h:458
Support for dynamic strings.
Definition: strings.h:623
void(*const optimization_started)(struct ast_unreal_pvt *p, struct ast_channel *source, enum ast_unreal_channel_indicator dest, unsigned int id)
Called when an optimization attempt has started.
Definition: core_unreal.h:69
void(*const optimization_finished)(struct ast_unreal_pvt *p, int success, unsigned int id)
Called when an optimization attempt completed successfully.
Definition: core_unreal.h:81
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
struct ast_unreal_pvt_callbacks * callbacks
Definition: core_unreal.h:92
struct ast_channel * owner
Definition: core_unreal.h:93
Internal bridge impart wait condition and associated conditional.
Definition: bridge.c:1544
struct bridge_channel_impart_cond::@314 node
unsigned int stop
Definition: bridge.c:179
struct bridge_manager_controller::@313 service_requests
struct ast_bridge * bridge
Definition: bridge.c:168
struct bridge_manager_request::@312 node
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:323
struct ast_bridge * src
Definition: bridge.c:2207
struct ast_bridge * dest
Definition: bridge.c:2205
Definition: test_heap.c:38
struct ast_bridge_technology * tech
Definition: bridge.c:565
AO2 object that wraps data for transfer_channel_cb.
Definition: bridge.h:1123
int value
Definition: syslog.c:37
Test Framework API.
static int hook_cb(struct ast_config *cfg)
Definition: test_config.c:875
static struct test_val b
static struct test_val a
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
void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
Formats a duration into HH:MM:SS.
Definition: utils.c:2333
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
Definition: time.h:137
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2280
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
Timing source management.
Utility functions.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:978
#define ast_assert(a)
Definition: utils.h:776
#define MIN(a, b)
Definition: utils.h:249
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:621
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:625
#define SWAP(a, b)
Definition: utils.h:253
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ARRAY_LEN(a)
Definition: utils.h:703
#define AST_UUID_STR_LEN
Definition: uuid.h:27
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:141
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:185
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:124