Asterisk - The Open Source Telephony Project GIT-master-6144b6b
Loading...
Searching...
No Matches
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
152/*!
153 * \brief Compare a bridge variable name with a given name.
154 *
155 * \param var_str The variable name to compare.
156 * \param name The name to compare against.
157 *
158 * \retval 0 if the names do not match.
159 * \retval 1 if the names match.
160 */
161#define BV_NAME_CMP(var_str, name) !strcmp(var_str, name)
162
163static void cleanup_video_mode(struct ast_bridge *bridge);
164
165/*! Default DTMF keys for built in features */
167
168/*! Function handlers for the built in features */
170
171/*! Function handlers for built in interval features */
173
174/*! Bridge manager service request */
176 /*! List of bridge service requests. */
178 /*! Refed bridge requesting service. */
180};
181
183 /*! Condition, used to wake up the bridge manager thread. */
185 /*! Queue of bridge service requests. */
187 /*! Manager thread */
188 pthread_t thread;
189 /*! TRUE if the manager needs to stop. */
190 unsigned int stop:1;
191};
192
193/*! Bridge manager controller. */
195
197{
198 return ao2_bump(bridges);
199}
200
201/*!
202 * \internal
203 * \brief Request service for a bridge from the bridge manager.
204 * \since 12.0.0
205 *
206 * \param bridge Requesting service.
207 */
208static void bridge_manager_service_req(struct ast_bridge *bridge)
209{
211
213 if (bridge_manager->stop) {
215 return;
216 }
217
218 /* Create the service request. */
219 request = ast_calloc(1, sizeof(*request));
220 if (!request) {
221 /* Well. This isn't good. */
223 return;
224 }
225 ao2_ref(bridge, +1);
226 request->bridge = bridge;
227
228 /* Put request into the queue and wake the bridge manager. */
232}
233
235{
237
238 /* Perform a sanity check to make sure the bridge technology conforms to our needed requirements */
239 if (ast_strlen_zero(technology->name)
240 || !technology->capabilities
241 || !technology->write) {
242 ast_log(LOG_WARNING, "Bridge technology %s failed registration sanity check.\n",
243 technology->name);
244 return -1;
245 }
246
248
249 /* Look for duplicate bridge technology already using this name, or already registered */
251 if ((!strcasecmp(current->name, technology->name)) || (current == technology)) {
252 ast_log(LOG_WARNING, "A bridge technology of %s already claims to exist in our world.\n",
253 technology->name);
255 return -1;
256 }
257 }
258
259 /* Copy module pointer so reference counting can keep the module from unloading */
260 technology->mod = module;
261
262 /* Find the correct position to insert the technology. */
264 /* Put the highest preference tech's first in the list. */
265 if (technology->preference >= current->preference) {
266 AST_RWLIST_INSERT_BEFORE_CURRENT(technology, entry);
267
268 break;
269 }
270 }
272
273 if (!current) {
274 /* Insert our new bridge technology to the end of the list. */
275 AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
276 }
277
279
280 ast_verb(5, "Registered bridge technology %s\n", technology->name);
281
282 return 0;
283}
284
286{
288
290
291 /* Ensure the bridge technology is registered before removing it */
293 if (current == technology) {
295 ast_verb(5, "Unregistered bridge technology %s\n", technology->name);
296 break;
297 }
298 }
300
302
303 return current ? 0 : -1;
304}
305
306/*!
307 * \internal
308 * \brief Put an action onto the specified bridge. Don't dup the action frame.
309 * \since 12.0.0
310 *
311 * \param bridge What to queue the action on.
312 * \param action What to do.
313 */
314static void bridge_queue_action_nodup(struct ast_bridge *bridge, struct ast_frame *action)
315{
316 ast_debug(1, "Bridge %s: queueing action type:%u sub:%d\n",
317 bridge->uniqueid, action->frametype, action->subclass.integer);
318
319 ast_bridge_lock(bridge);
321 ast_bridge_unlock(bridge);
323}
324
325int ast_bridge_queue_action(struct ast_bridge *bridge, struct ast_frame *action)
326{
327 struct ast_frame *dup;
328
329 dup = ast_frdup(action);
330 if (!dup) {
331 return -1;
332 }
333 bridge_queue_action_nodup(bridge, dup);
334 return 0;
335}
336
337void bridge_dissolve(struct ast_bridge *bridge, int cause)
338{
339 struct ast_bridge_channel *bridge_channel;
340 struct ast_frame action = {
343 };
344
345 if (bridge->dissolved) {
346 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": already dissolved\n",
347 BRIDGE_PRINTF_VARS(bridge));
348 return;
349 }
350 bridge->dissolved = 1;
351
352 if (cause <= 0) {
354 }
355 bridge->cause = cause;
356
357 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": dissolving with cause %d(%s)\n",
358 BRIDGE_PRINTF_VARS(bridge), cause, ast_cause2str(cause));
359
360 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
361 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": kicking channel %s\n",
362 BRIDGE_PRINTF_VARS(bridge),
363 ast_channel_name(bridge_channel->chan));
364 ast_bridge_channel_leave_bridge(bridge_channel,
366 }
367
368 /* Must defer dissolving bridge because it is already locked. */
369 ast_bridge_queue_action(bridge, &action);
370 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": DEFERRED_DISSOLVING queued. current refcound: %d\n",
371 BRIDGE_PRINTF_VARS(bridge), ao2_ref(bridge, 0));
372
373}
374
375/*!
376 * \internal
377 * \brief Check if a bridge should dissolve because of a stolen channel and do it.
378 * \since 12.0.0
379 *
380 * \param bridge Bridge to check.
381 * \param bridge_channel Stolen channel causing the check. It is not in the bridge to check and may be in another bridge.
382 *
383 * \note On entry, bridge and bridge_channel->bridge are already locked.
384 */
385static void bridge_dissolve_check_stolen(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
386{
387 if (bridge->dissolved) {
388 return;
389 }
390
391 if (bridge_channel->features->usable
392 && ast_test_flag(&bridge_channel->features->feature_flags,
394 /* The stolen channel controlled the bridge it was stolen from. */
395 bridge_dissolve(bridge, 0);
396 return;
397 }
398 if (bridge->num_channels < 2
400 /*
401 * The stolen channel has not left enough channels to keep the
402 * bridge alive. Assume the stolen channel hung up.
403 */
404 bridge_dissolve(bridge, 0);
405 return;
406 }
407}
408
409/*!
410 * \internal
411 * \brief Update connected line information after a bridge has been reconfigured.
412 *
413 * \param bridge The bridge itself.
414 */
416{
418 struct ast_bridge_channel *bridge_channel = AST_LIST_FIRST(&bridge->channels), *peer;
419 unsigned char data[1024];
420 size_t datalen;
421
422 if (!bridge_channel ||
424 !(peer = ast_bridge_channel_peer(bridge_channel)) ||
427 ast_check_hangup_locked(bridge_channel->chan) ||
428 ast_check_hangup_locked(peer->chan)) {
429 return;
430 }
431
433
434 ast_channel_lock(bridge_channel->chan);
436 ast_channel_unlock(bridge_channel->chan);
437
438 if ((datalen = ast_connected_line_build_data(data, sizeof(data), &connected, NULL)) != (size_t) -1) {
440 }
441
442 ast_channel_lock(peer->chan);
444 ast_channel_unlock(peer->chan);
445
446 if ((datalen = ast_connected_line_build_data(data, sizeof(data), &connected, NULL)) != (size_t) -1) {
448 }
449
451}
452
453/*!
454 * \internal
455 * \brief Complete joining a channel to the bridge.
456 * \since 12.0.0
457 *
458 * \param bridge What to operate upon.
459 * \param bridge_channel What is joining the bridge technology.
460 *
461 * \note On entry, bridge is already locked.
462 */
463static void bridge_channel_complete_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
464{
465 /* Tell the bridge technology we are joining so they set us up */
466 ast_debug(1, "Bridge %s: %p(%s) is joining %s technology\n",
467 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
470 && bridge->technology->join(bridge, bridge_channel)) {
471 /* We cannot leave the channel partially in the bridge so we must kick it out */
472 ast_debug(1, "Bridge %s: %p(%s) failed to join %s technology (Kicking it out)\n",
473 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
475 bridge_channel->just_joined = 1;
477 return;
478 }
479
480 bridge_channel->just_joined = 0;
481
482 /*
483 * When a channel joins the bridge its streams need to be mapped to the bridge's
484 * media types vector. This way all streams map to the same media type index for
485 * a given channel.
486 */
487 if (bridge_channel->bridge->technology->stream_topology_changed) {
488 bridge_channel->bridge->technology->stream_topology_changed(
489 bridge_channel->bridge, bridge_channel);
490 } else {
491 ast_bridge_channel_stream_map(bridge_channel);
492 }
493}
494
495/*!
496 * \internal
497 * \brief Complete joining new channels to the bridge.
498 * \since 12.0.0
499 *
500 * \param bridge Check for new channels on this bridge.
501 *
502 * \note On entry, bridge is already locked.
503 */
505{
506 struct ast_bridge_channel *bridge_channel;
507
508 if (bridge->dissolved) {
509 /*
510 * No sense in completing the join on channels for a dissolved
511 * bridge. They are just going to be removed soon anyway.
512 * However, we do have reason to abort here because the bridge
513 * technology may not be able to handle the number of channels
514 * still in the bridge.
515 */
516 return;
517 }
518
519 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
521 if (!bridge_channel->just_joined) {
522 continue;
523 }
524 bridge_channel_complete_join(bridge, bridge_channel);
525 }
526}
527
528/*! \brief Helper function used to find the "best" bridge technology given specified capabilities */
530{
533
536 if (current->suspended) {
537 ast_debug(2, "Bridge technology %s is suspended. Skipping.\n",
538 current->name);
539 continue;
540 }
541 if (!(current->capabilities & capabilities)) {
542 ast_debug(2, "Bridge technology %s does not have any capabilities we want.\n",
543 current->name);
544 continue;
545 }
546 if (best && current->preference <= best->preference) {
547 ast_debug(2, "Bridge technology %s has less preference than %s (%u <= %u). Skipping.\n",
548 current->name, best->name, current->preference, best->preference);
549 continue;
550 }
551 if (current->compatible && !current->compatible(bridge)) {
552 ast_debug(2, "Bridge technology %s is not compatible with properties of existing bridge.\n",
553 current->name);
554 continue;
555 }
556 if (!ast_module_running_ref(current->mod)) {
557 ast_debug(2, "Bridge technology %s is not running, skipping.\n", current->name);
558 continue;
559 }
560 if (best) {
562 }
563 best = current;
564 }
565
566 if (best) {
567 ast_debug(1, "Chose bridge technology %s\n", best->name);
568 }
569
571
572 return best;
573}
574
579
580/*!
581 * \internal
582 * \brief Deferred destruction of bridge tech private structure.
583 * \since 12.0.0
584 *
585 * \param bridge What to execute the action on.
586 * \param action Deferred bridge tech destruction.
587 *
588 * \note On entry, bridge must not be locked.
589 */
590static void bridge_tech_deferred_destroy(struct ast_bridge *bridge, struct ast_frame *action)
591{
592 struct tech_deferred_destroy *deferred = action->data.ptr;
593 struct ast_bridge dummy_bridge = {
594 .technology = deferred->tech,
595 .tech_pvt = deferred->tech_pvt,
596 .creator = bridge->creator,
597 .name = bridge->name,
598 .uniqueid = bridge->uniqueid,
599 };
600
601 ast_debug(1, "Bridge %s: calling %s technology destructor (deferred, dummy)\n",
602 dummy_bridge.uniqueid, dummy_bridge.technology->name);
603 dummy_bridge.technology->destroy(&dummy_bridge);
604 ast_module_unref(dummy_bridge.technology->mod);
605}
606
607/*!
608 * \internal
609 * \brief Handle bridge action frame.
610 * \since 12.0.0
611 *
612 * \param bridge What to execute the action on.
613 * \param action What to do.
614 *
615 * \note On entry, bridge is already locked.
616 * \note Can be called by the bridge destructor
617 */
618static void bridge_action_bridge(struct ast_bridge *bridge, struct ast_frame *action)
619{
620#if 0 /* In case we need to know when the destructor is calling us. */
621 int in_destructor = !ao2_ref(bridge, 0);
622#endif
623
624 switch (action->subclass.integer) {
626 ast_bridge_unlock(bridge);
627 bridge_tech_deferred_destroy(bridge, action);
628 ast_bridge_lock(bridge);
629 break;
631 ast_bridge_unlock(bridge);
632 bridge->v_table->dissolving(bridge);
633 ast_bridge_lock(bridge);
634 break;
635 default:
636 /* Unexpected deferred action type. Should never happen. */
637 ast_assert(0);
638 break;
639 }
640}
641
642/*!
643 * \internal
644 * \brief Do any pending bridge actions.
645 * \since 12.0.0
646 *
647 * \param bridge What to do actions on.
648 *
649 * \note On entry, bridge is already locked.
650 * \note Can be called by the bridge destructor.
651 */
652static void bridge_handle_actions(struct ast_bridge *bridge)
653{
654 struct ast_frame *action;
655
656 while ((action = AST_LIST_REMOVE_HEAD(&bridge->action_queue, frame_list))) {
657 switch (action->frametype) {
659 bridge_action_bridge(bridge, action);
660 break;
661 default:
662 /* Unexpected deferred frame type. Should never happen. */
663 ast_assert(0);
664 break;
665 }
666 ast_frfree(action);
667 }
668}
669
670static void destroy_bridge(void *obj)
671{
672 struct ast_bridge *bridge = obj;
673 struct ast_var_t *var;
674
675 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": actually destroying %s bridge, nobody wants it anymore\n",
676 BRIDGE_PRINTF_VARS(bridge), bridge->v_table->name);
677
678 if (bridge->construction_completed) {
679 bridge_topics_destroy(bridge);
680 }
681
682 /* Do any pending actions in the context of destruction. */
683 ast_bridge_lock(bridge);
684 bridge_handle_actions(bridge);
685 ast_bridge_unlock(bridge);
686
687 /* There should not be any channels left in the bridge. */
689
690 ast_debug(1, "Bridge %s: calling %s bridge destructor\n",
691 bridge->uniqueid, bridge->v_table->name);
692 bridge->v_table->destroy(bridge);
693
694 /* Pass off the bridge to the technology to destroy if needed */
695 if (bridge->technology) {
696 ast_debug(1, "Bridge %s: calling %s technology stop\n",
697 bridge->uniqueid, bridge->technology->name);
698 if (bridge->technology->stop) {
699 ast_bridge_lock(bridge);
700 bridge->technology->stop(bridge);
701 ast_bridge_unlock(bridge);
702 }
703 ast_debug(1, "Bridge %s: calling %s technology destructor\n",
704 bridge->uniqueid, bridge->technology->name);
705 if (bridge->technology->destroy) {
706 bridge->technology->destroy(bridge);
707 }
709 bridge->technology = NULL;
710 }
711
713
714 bridge->callid = 0;
715
716 cleanup_video_mode(bridge);
717
718 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": destroyed\n",
719 BRIDGE_PRINTF_VARS(bridge));
722 bridge->current_snapshot = NULL;
723 while ((var = AST_LIST_REMOVE_HEAD(&bridge->bridgevars, entries))) {
725 }
729}
730
731struct ast_bridge *bridge_register(struct ast_bridge *bridge)
732{
733 if (bridge) {
735 /*
736 * Although bridge_base_init() should have already checked for
737 * an existing bridge with the same uniqueid, bridge_base_init()
738 * and bridge_register() are two separate public APIs so we need
739 * to check again here.
740 */
741 struct ast_bridge *existing = ast_bridge_find_by_id(bridge->uniqueid);
742 if (existing) {
743 ast_log(LOG_WARNING, "Bridge " BRIDGE_PRINTF_SPEC ": already registered\n",
744 BRIDGE_PRINTF_VARS(bridge));
745 ao2_ref(existing, -1);
746 ast_bridge_destroy(bridge, 0);
747 return NULL;
748 }
749 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": registering\n",
750 BRIDGE_PRINTF_VARS(bridge));
751 bridge->construction_completed = 1;
752 ast_bridge_lock(bridge);
754 ast_bridge_unlock(bridge);
755 if (!ao2_link(bridges, bridge)) {
756 ast_log(LOG_WARNING, "Bridge " BRIDGE_PRINTF_SPEC ": failed to link\n",
757 BRIDGE_PRINTF_VARS(bridge));
758 ast_bridge_destroy(bridge, 0);
759 bridge = NULL;
760 }
761 }
762 return bridge;
763}
764
765struct ast_bridge *bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
766{
767 struct ast_bridge *bridge;
768
769 /* Check v_table that all methods are present. */
770 if (!v_table
771 || !v_table->name
772 || !v_table->destroy
774 || !v_table->push
775 || !v_table->pull
778 ast_log(LOG_ERROR, "Virtual method table for bridge class %s not complete.\n",
779 v_table && v_table->name ? v_table->name : "<unknown>");
780 ast_assert(0);
781 return NULL;
782 }
783
784 bridge = ao2_alloc(size, destroy_bridge);
785 if (!bridge) {
786 return NULL;
787 }
788
789 if (ast_string_field_init(bridge, 80)) {
790 ao2_cleanup(bridge);
791 return NULL;
792 }
793
794 bridge->v_table = v_table;
795
799
800 return bridge;
801}
802
803struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
804{
805 char uuid_hold[AST_UUID_STR_LEN];
806
807 if (!self) {
808 return NULL;
809 }
810
811 {
812 /*
813 * We need to ensure that another bridge with the same uniqueid
814 * doesn't get created before the previous bridge's destructor
815 * has run and deleted the existing topic.
816 */
818 if (!ast_strlen_zero(id)) {
819 if (ast_bridge_topic_exists(id)) {
820 ast_log(LOG_WARNING, "Bridge " BRIDGE_PRINTF_SPEC ": already registered\n",
821 BRIDGE_PRINTF_VARS(self));
822 ast_bridge_destroy(self, 0);
823 return NULL;
824 }
826 } else {
828 ast_string_field_set(self, uniqueid, uuid_hold);
829 }
830 if (!(flags & AST_BRIDGE_FLAG_INVISIBLE)) {
831 if (bridge_topics_init(self) != 0) {
832 ast_log(LOG_WARNING, "Bridge " BRIDGE_PRINTF_SPEC ": Could not initialize topics\n",
833 BRIDGE_PRINTF_VARS(self));
834 ao2_ref(self, -1);
835 return NULL;
836 }
837 }
838 }
839
841 if (!ast_strlen_zero(creator)) {
843 }
844 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": base_init\n",
845 BRIDGE_PRINTF_VARS(self));
846
847 ast_set_flag(&self->feature_flags, flags);
848 self->allowed_capabilities = capabilities;
849
850 /* Use our helper function to find the "best" bridge technology. */
851 self->technology = find_best_technology(capabilities, self);
852 if (!self->technology) {
853 ast_log(LOG_WARNING, "Bridge %s: Could not create class %s. No technology to support it.\n",
854 self->uniqueid, self->v_table->name);
855 ao2_ref(self, -1);
856 return NULL;
857 }
858
859 /* Pass off the bridge to the technology to manipulate if needed */
860 ast_debug(1, "Bridge %s: calling %s technology constructor\n",
861 self->uniqueid, self->technology->name);
862 if (self->technology->create && self->technology->create(self)) {
863 ast_log(LOG_WARNING, "Bridge %s: failed to setup bridge technology %s\n",
864 self->uniqueid, self->technology->name);
865 ao2_ref(self, -1);
866 return NULL;
867 }
868 ast_debug(1, "Bridge %s: calling %s technology start\n",
869 self->uniqueid, self->technology->name);
870 if (self->technology->start && self->technology->start(self)) {
871 ast_log(LOG_WARNING, "Bridge %s: failed to start bridge technology %s\n",
872 self->uniqueid, self->technology->name);
873 ao2_ref(self, -1);
874 return NULL;
875 }
876
877 if (!(flags & AST_BRIDGE_FLAG_INVISIBLE)) {
878 if (!ast_bridge_topic(self)) {
879 ao2_ref(self, -1);
880 return NULL;
881 }
882 }
883
884 self->creationtime = ast_tvnow();
885 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": base_init complete\n",
886 BRIDGE_PRINTF_VARS(self));
887
888 return self;
889}
890
891/*!
892 * \internal
893 * \brief ast_bridge base class destructor.
894 * \since 12.0.0
895 *
896 * \param self Bridge to operate upon.
897 *
898 * \note Stub because of nothing to do.
899 */
900static void bridge_base_destroy(struct ast_bridge *self)
901{
902 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": destroying bridge (noop)\n",
903 BRIDGE_PRINTF_VARS(self));
904}
905
906/*!
907 * \internal
908 * \brief The bridge is being dissolved.
909 * \since 12.0.0
910 *
911 * \param self Bridge to operate upon.
912 */
913static void bridge_base_dissolving(struct ast_bridge *self)
914{
915 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": unlinking bridge. Refcount: %d\n",
916 BRIDGE_PRINTF_VARS(self), ao2_ref(self, 0));
917 ao2_unlink(bridges, self);
918 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": unlinked bridge. Refcount: %d\n",
919 BRIDGE_PRINTF_VARS(self), ao2_ref(self, 0));
920}
921
922/*!
923 * \internal
924 * \brief ast_bridge base push method.
925 * \since 12.0.0
926 *
927 * \param self Bridge to operate upon.
928 * \param bridge_channel Bridge channel to push.
929 * \param swap Bridge channel to swap places with if not NULL.
930 *
931 * \note On entry, self is already locked.
932 * \note Stub because of nothing to do.
933 *
934 * \retval 0 on success
935 * \retval -1 on failure
936 */
937static int bridge_base_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
938{
939 return 0;
940}
941
942/*!
943 * \internal
944 * \brief ast_bridge base pull method.
945 * \since 12.0.0
946 *
947 * \param self Bridge to operate upon.
948 * \param bridge_channel Bridge channel to pull.
949 *
950 * \note On entry, self is already locked.
951 */
952static void bridge_base_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
953{
955}
956
957/*!
958 * \internal
959 * \brief ast_bridge base notify_masquerade method.
960 * \since 12.0.0
961 *
962 * \param self Bridge to operate upon.
963 * \param bridge_channel Bridge channel that was masqueraded.
964 *
965 * \note On entry, self is already locked.
966 */
967static void bridge_base_notify_masquerade(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
968{
969 self->reconfigured = 1;
970}
971
972/*!
973 * \internal
974 * \brief Get the merge priority of this bridge.
975 * \since 12.0.0
976 *
977 * \param self Bridge to operate upon.
978 *
979 * \note On entry, self is already locked.
980 *
981 * \return Merge priority
982 */
984{
985 return 0;
986}
987
988/*!
989 * \internal
990 * \brief ast_bridge base push_peek method.
991 * \since 13.2.0
992 *
993 * \param self Bridge to operate upon.
994 * \param bridge_channel Bridge channel to push.
995 * \param swap Bridge channel to swap places with if not NULL.
996 *
997 * \note On entry, self is already locked.
998 * \note Stub because of nothing to do.
999 *
1000 * \retval 0 on success
1001 * \retval -1 on failure
1002 */
1003static int bridge_base_push_peek(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
1004{
1005 return 0;
1006}
1007
1009 .name = "base",
1010 .destroy = bridge_base_destroy,
1011 .dissolving = bridge_base_dissolving,
1012 .push = bridge_base_push,
1013 .pull = bridge_base_pull,
1014 .notify_masquerade = bridge_base_notify_masquerade,
1015 .get_merge_priority = bridge_base_get_merge_priority,
1016 .push_peek = bridge_base_push_peek,
1017};
1018
1019struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
1020{
1021 void *bridge;
1022
1023 bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_base_v_table);
1024 bridge = bridge_base_init(bridge, capabilities, flags, creator, name, id);
1025 bridge = bridge_register(bridge);
1026 return bridge;
1027}
1028
1029int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
1030{
1031 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": destroying. current refcount: %d\n",
1032 BRIDGE_PRINTF_VARS(bridge), ao2_ref(bridge, 0));
1033 ast_bridge_lock(bridge);
1034 bridge_dissolve(bridge, cause);
1035 ast_bridge_unlock(bridge);
1036
1037 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": unreffing. current refcount: %d\n",
1038 BRIDGE_PRINTF_VARS(bridge), ao2_ref(bridge, 0));
1039
1040 ao2_ref(bridge, -1);
1041
1042 return 0;
1043}
1044
1045/*!
1046 * \internal
1047 * \brief Perform the smart bridge operation.
1048 * \since 12.0.0
1049 *
1050 * \param bridge Work on this bridge.
1051 *
1052 * \details
1053 * Basically see if a new bridge technology should be used instead
1054 * of the current one.
1055 *
1056 * \note On entry, bridge is already locked.
1057 *
1058 * \retval 0 on success.
1059 * \retval -1 on error.
1060 */
1061static int smart_bridge_operation(struct ast_bridge *bridge)
1062{
1063 uint32_t new_capabilities;
1066 struct ast_bridge_channel *bridge_channel;
1067 struct ast_frame *deferred_action;
1068 struct ast_bridge dummy_bridge = {
1069 .technology = bridge->technology,
1070 .tech_pvt = bridge->tech_pvt,
1071 .creator = bridge->creator,
1072 .name = bridge->name,
1073 .uniqueid = bridge->uniqueid,
1074 };
1075
1076 if (bridge->dissolved) {
1077 ast_debug(1, "Bridge %s is dissolved, not performing smart bridge operation.\n",
1078 bridge->uniqueid);
1079 return 0;
1080 }
1081
1082 /* Determine new bridge technology capabilities needed. */
1083 if (2 < bridge->num_channels) {
1084 new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
1085 new_capabilities &= bridge->allowed_capabilities;
1086 } else {
1088 new_capabilities &= bridge->allowed_capabilities;
1089 if (!new_capabilities
1091 /* Allow switching between different multimix bridge technologies. */
1092 new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
1093 }
1094 }
1095
1096 /* Find a bridge technology to satisfy the new capabilities. */
1097 new_technology = find_best_technology(new_capabilities, bridge);
1098 if (!new_technology) {
1099 int is_compatible = 0;
1100
1101 if (old_technology->compatible) {
1102 is_compatible = old_technology->compatible(bridge);
1103 } else if (old_technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
1104 is_compatible = 1;
1105 } else if (bridge->num_channels <= 2
1106 && (old_technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX)) {
1107 is_compatible = 1;
1108 }
1109
1110 if (is_compatible) {
1111 ast_debug(1, "Bridge %s could not get a new technology, staying with old technology.\n",
1112 bridge->uniqueid);
1113 return 0;
1114 }
1115 ast_log(LOG_WARNING, "Bridge %s has no technology available to support it.\n",
1116 bridge->uniqueid);
1117 return -1;
1118 }
1119 if (new_technology == old_technology) {
1120 ast_debug(1, "Bridge %s is already using the new technology.\n",
1121 bridge->uniqueid);
1122 ast_module_unref(old_technology->mod);
1123 return 0;
1124 }
1125
1126 if (old_technology->destroy) {
1127 struct tech_deferred_destroy deferred_tech_destroy = {
1128 .tech = dummy_bridge.technology,
1129 .tech_pvt = dummy_bridge.tech_pvt,
1130 };
1131 struct ast_frame action = {
1134 .data.ptr = &deferred_tech_destroy,
1135 .datalen = sizeof(deferred_tech_destroy),
1136 };
1137
1138 /*
1139 * We need to defer the bridge technology destroy callback
1140 * because we have the bridge locked.
1141 */
1142 deferred_action = ast_frdup(&action);
1143 if (!deferred_action) {
1144 ast_module_unref(new_technology->mod);
1145 return -1;
1146 }
1147 } else {
1149 }
1150
1151 /*
1152 * We are now committed to changing the bridge technology. We
1153 * must not release the bridge lock until we have installed the
1154 * new bridge technology.
1155 */
1156 ast_verb(4, "Bridge %s: switching from %s technology to %s\n",
1157 bridge->uniqueid, old_technology->name, new_technology->name);
1158
1159 /*
1160 * Since we are soon going to pass this bridge to a new
1161 * technology we need to NULL out the tech_pvt pointer but
1162 * don't worry as it still exists in dummy_bridge, ditto for the
1163 * old technology.
1164 */
1165 bridge->tech_pvt = NULL;
1166 bridge->technology = new_technology;
1167
1168 /* Setup the new bridge technology. */
1169 ast_debug(1, "Bridge %s: calling %s technology constructor\n",
1170 bridge->uniqueid, new_technology->name);
1171 if (new_technology->create && new_technology->create(bridge)) {
1172 ast_log(LOG_WARNING, "Bridge %s: failed to setup bridge technology %s\n",
1173 bridge->uniqueid, new_technology->name);
1174 bridge->tech_pvt = dummy_bridge.tech_pvt;
1175 bridge->technology = dummy_bridge.technology;
1176 ast_module_unref(new_technology->mod);
1177 return -1;
1178 }
1179
1180 /* To ensure that things are sane for the old technology move the channels it
1181 * expects to the dummy bridge
1182 */
1183 AST_LIST_TRAVERSE_SAFE_BEGIN(&bridge->channels, bridge_channel, entry) {
1184 if (bridge_channel->just_joined) {
1185 continue;
1186 }
1187 ast_debug(1, "Bridge %s: moving %p(%s) to dummy bridge temporarily\n",
1188 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
1190 AST_LIST_INSERT_TAIL(&dummy_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 /* Take all the channels out of the old technology */
1202 AST_LIST_TRAVERSE_SAFE_BEGIN(&dummy_bridge.channels, bridge_channel, entry) {
1203 ast_debug(1, "Bridge %s: %p(%s) is leaving %s technology (dummy)\n",
1204 dummy_bridge.uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
1205 old_technology->name);
1206 if (old_technology->leave) {
1207 old_technology->leave(&dummy_bridge, bridge_channel);
1208 }
1210 AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
1211 dummy_bridge.num_channels--;
1213 dummy_bridge.num_lonely--;
1214 }
1215 if (!bridge_channel->suspended) {
1216 dummy_bridge.num_active--;
1217 }
1218 }
1220
1221 ast_debug(1, "Bridge %s: calling %s technology stop\n",
1222 dummy_bridge.uniqueid, old_technology->name);
1223 if (old_technology->stop) {
1224 old_technology->stop(&dummy_bridge);
1225 }
1226
1227 /* Add any new channels or re-add existing channels to the bridge. */
1228 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1229 bridge_channel_complete_join(bridge, bridge_channel);
1230 }
1231
1232 ast_debug(1, "Bridge %s: calling %s technology start\n",
1233 bridge->uniqueid, new_technology->name);
1234 if (new_technology->start && new_technology->start(bridge)) {
1235 ast_log(LOG_WARNING, "Bridge %s: failed to start bridge technology %s\n",
1236 bridge->uniqueid, new_technology->name);
1237 }
1238
1239 /*
1240 * Now that all the channels have been moved over we need to get
1241 * rid of all the information the old technology may have left
1242 * around.
1243 */
1244 if (old_technology->destroy) {
1245 ast_debug(1, "Bridge %s: deferring %s technology destructor\n",
1246 dummy_bridge.uniqueid, old_technology->name);
1248 } else {
1249 ast_debug(1, "Bridge %s: calling %s technology destructor\n",
1250 dummy_bridge.uniqueid, old_technology->name);
1251 ast_module_unref(old_technology->mod);
1252 }
1253
1254 return 0;
1255}
1256
1257/*!
1258 * \internal
1259 * \brief Bridge channel to check if a BRIDGE_PLAY_SOUND needs to be played.
1260 * \since 12.0.0
1261 *
1262 * \param bridge_channel What to check.
1263 */
1264static void check_bridge_play_sound(struct ast_bridge_channel *bridge_channel)
1265{
1266 const char *play_file;
1267
1268 ast_channel_lock(bridge_channel->chan);
1269 play_file = pbx_builtin_getvar_helper(bridge_channel->chan, "BRIDGE_PLAY_SOUND");
1270 if (!ast_strlen_zero(play_file)) {
1272 pbx_builtin_setvar_helper(bridge_channel->chan, "BRIDGE_PLAY_SOUND", NULL);
1273 } else {
1274 play_file = NULL;
1275 }
1276 ast_channel_unlock(bridge_channel->chan);
1277
1278 if (play_file) {
1280 }
1281}
1282
1283/*!
1284 * \internal
1285 * \brief Check for any BRIDGE_PLAY_SOUND channel variables in the bridge.
1286 * \since 12.0.0
1287 *
1288 * \param bridge What to operate on.
1289 *
1290 * \note On entry, the bridge is already locked.
1291 */
1292static void check_bridge_play_sounds(struct ast_bridge *bridge)
1293{
1294 struct ast_bridge_channel *bridge_channel;
1295
1296 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1297 check_bridge_play_sound(bridge_channel);
1298 }
1299}
1300
1301void ast_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
1302{
1304 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", name);
1305 pbx_builtin_setvar_helper(chan, "BRIDGEPVTCALLID", pvtid);
1307}
1308
1309static int bridge_set_ari_var_reportable(struct ast_bridge *bridge, const char *variable,
1310 int report_events)
1311{
1312 char *var_str;
1313
1314 if (ast_strlen_zero(variable)) {
1315 return -1;
1316 }
1317
1318 if (!report_events) {
1321 return 0;
1322 }
1323
1325 return 0; /* already present */
1326 }
1327
1328 var_str = ast_strdup(variable);
1329 if (!var_str) {
1330 return -1;
1331 }
1332
1334 ast_free(var_str);
1335 return -1;
1336 }
1337
1338 return 0;
1339}
1340
1341int ast_bridge_set_variable(struct ast_bridge *bridge, const char *name, const char *value,
1342 int report_events)
1343{
1344 struct ast_var_t *var;
1345
1346 if (ast_strlen_zero(name)) {
1347 return -1;
1348 }
1349
1351 if (!strcmp(ast_var_name(var), name)) {
1354 break;
1355 }
1356 }
1358
1359 if (ast_strlen_zero(value)) {
1360 /* If the value is empty, remove the variable from the reportable list by
1361 forcing report_events to 0 */
1363 return 0;
1364 }
1365
1367 if (!var) {
1368 return -1;
1369 }
1370
1371 if (bridge_set_ari_var_reportable(bridge, name, report_events)) {
1373 return -1;
1374 }
1375
1377 return 0;
1378}
1379
1380const char *ast_bridge_get_variable(const struct ast_bridge *bridge, const char *name)
1381{
1382 return ast_var_find(&bridge->bridgevars, name);
1383}
1384
1386{
1387 struct varshead *ret;
1388 char *var_str;
1389 size_t i;
1390
1392 return NULL;
1393 }
1394
1395 ret = ast_var_list_create();
1396 if (!ret) {
1397 return NULL;
1398 }
1399
1400 for (i = 0; i < AST_VECTOR_SIZE(&bridge->ari_reportable_variable_names); ++i) {
1401 const char *val = NULL;
1402 struct ast_var_t *var;
1403
1404 var_str = AST_VECTOR_GET(&bridge->ari_reportable_variable_names, i);
1405 val = ast_bridge_get_variable(bridge, var_str);
1406
1407 var = ast_var_assign(var_str, val ? val : "");
1408 if (!var) {
1410 return NULL;
1411 }
1412
1414 }
1415
1416 return ret;
1417}
1418
1419/*!
1420 * \internal
1421 * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a 2 party bridge.
1422 * \since 12.0.0
1423 *
1424 * \param c0 Party of the first part.
1425 * \param c1 Party of the second part.
1426 *
1427 * \note On entry, the bridge is already locked.
1428 * \note The bridge is expected to have exactly two parties.
1429 */
1430static void set_bridge_peer_vars_2party(struct ast_channel *c0, struct ast_channel *c1)
1431{
1432 const char *c0_name;
1433 const char *c1_name;
1434 const char *c0_pvtid = NULL;
1435 const char *c1_pvtid = NULL;
1436#define UPDATE_BRIDGE_VARS_GET(chan, name, pvtid) \
1437 do { \
1438 name = ast_strdupa(ast_channel_name(chan)); \
1439 if (ast_channel_tech(chan)->get_pvt_uniqueid) { \
1440 pvtid = ast_strdupa(ast_channel_tech(chan)->get_pvt_uniqueid(chan)); \
1441 } \
1442 } while (0)
1443
1444 ast_channel_lock(c1);
1445 UPDATE_BRIDGE_VARS_GET(c1, c1_name, c1_pvtid);
1447
1448 ast_channel_lock(c0);
1449 ast_bridge_vars_set(c0, c1_name, c1_pvtid);
1450 UPDATE_BRIDGE_VARS_GET(c0, c0_name, c0_pvtid);
1452
1453 ast_channel_lock(c1);
1454 ast_bridge_vars_set(c1, c0_name, c0_pvtid);
1456}
1457
1458/*!
1459 * \internal
1460 * \brief Fill the BRIDGEPEER value buffer with a comma separated list of channel names.
1461 * \since 12.0.0
1462 *
1463 * \param buf Buffer to fill. The caller must guarantee the buffer is large enough.
1464 * \param cur_idx Which index into names[] to skip.
1465 * \param names Channel names to put in the buffer.
1466 * \param num_names Number of names in the array.
1467 */
1468static void fill_bridgepeer_buf(char *buf, unsigned int cur_idx, const char *names[], unsigned int num_names)
1469{
1470 int need_separator = 0;
1471 unsigned int idx;
1472 const char *src;
1473 char *pos;
1474
1475 pos = buf;
1476 for (idx = 0; idx < num_names; ++idx) {
1477 if (idx == cur_idx) {
1478 continue;
1479 }
1480
1481 if (need_separator) {
1482 *pos++ = ',';
1483 }
1484 need_separator = 1;
1485
1486 /* Copy name into buffer. */
1487 src = names[idx];
1488 while (*src) {
1489 *pos++ = *src++;
1490 }
1491 }
1492 *pos = '\0';
1493}
1494
1495/*!
1496 * \internal
1497 * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a multi-party bridge.
1498 * \since 12.0.0
1499 *
1500 * \param bridge What to operate on.
1501 *
1502 * \note On entry, the bridge is already locked.
1503 * \note The bridge is expected to have more than two parties.
1504 */
1506{
1507/*
1508 * Set a maximum number of channel names for the BRIDGEPEER
1509 * list. The plus one is for the current channel which is not
1510 * put in the list.
1511 */
1512#define MAX_BRIDGEPEER_CHANS (10 + 1)
1513
1514 unsigned int idx;
1515 unsigned int num_names;
1516 unsigned int len;
1517 const char **names;
1518 char *buf;
1519 struct ast_bridge_channel *bridge_channel;
1520
1521 /* Get first MAX_BRIDGEPEER_CHANS channel names. */
1523 names = ast_alloca(num_names * sizeof(*names));
1524 idx = 0;
1525 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1526 if (num_names <= idx) {
1527 break;
1528 }
1529 ast_channel_lock(bridge_channel->chan);
1530 names[idx++] = ast_strdupa(ast_channel_name(bridge_channel->chan));
1531 ast_channel_unlock(bridge_channel->chan);
1532 }
1533
1534 /* Determine maximum buf size needed. */
1535 len = num_names;
1536 for (idx = 0; idx < num_names; ++idx) {
1537 len += strlen(names[idx]);
1538 }
1539 buf = ast_alloca(len);
1540
1541 /* Set the bridge channel variables. */
1542 idx = 0;
1543 buf[0] = '\0';
1544 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1545 if (idx < num_names) {
1546 fill_bridgepeer_buf(buf, idx, names, num_names);
1547 }
1548 ++idx;
1549
1550 ast_channel_lock(bridge_channel->chan);
1551 ast_bridge_vars_set(bridge_channel->chan, buf, NULL);
1552 ast_channel_unlock(bridge_channel->chan);
1553 }
1554}
1555
1556/*!
1557 * \internal
1558 * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a holding bridge.
1559 * \since 12.0.0
1560 *
1561 * \param bridge What to operate on.
1562 *
1563 * \note On entry, the bridge is already locked.
1564 */
1566{
1567 struct ast_bridge_channel *bridge_channel;
1568
1569 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1570 ast_channel_lock(bridge_channel->chan);
1571 ast_bridge_vars_set(bridge_channel->chan, NULL, NULL);
1572 ast_channel_unlock(bridge_channel->chan);
1573 }
1574}
1575
1576/*!
1577 * \internal
1578 * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in the bridge.
1579 * \since 12.0.0
1580 *
1581 * \param bridge What to operate on.
1582 *
1583 * \note On entry, the bridge is already locked.
1584 */
1586{
1589 return;
1590 }
1591 if (bridge->num_channels < 2) {
1592 return;
1593 }
1594 if (bridge->num_channels == 2) {
1596 AST_LIST_LAST(&bridge->channels)->chan);
1597 } else {
1599 }
1600}
1601
1602void bridge_reconfigured(struct ast_bridge *bridge, unsigned int colp_update)
1603{
1604 if (!bridge->reconfigured) {
1605 return;
1606 }
1607 bridge->reconfigured = 0;
1610 /* Smart bridge failed. */
1612 return;
1613 }
1615
1616 if (bridge->dissolved) {
1617 return;
1618 }
1622
1623 if (colp_update) {
1625 }
1626}
1627
1629{
1630 struct ast_bridge_channel *bridge_channel;
1631
1632 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1633 if (bridge_channel->chan == chan) {
1634 break;
1635 }
1636 }
1637
1638 return bridge_channel;
1639}
1640
1642{
1643 struct ast_bridge_channel *bridge_channel;
1644 struct ast_bridge *bridge;
1645
1646 /* Safely get the bridge_channel pointer for the chan. */
1647 ast_channel_lock(chan);
1648 bridge_channel = ast_channel_get_bridge_channel(chan);
1649 ast_channel_unlock(chan);
1650 if (!bridge_channel) {
1651 /* Not in a bridge */
1652 return;
1653 }
1654
1655 ast_bridge_channel_lock_bridge(bridge_channel);
1656 bridge = bridge_channel->bridge;
1657 if (bridge_channel == bridge_find_channel(bridge, chan)) {
1658/*
1659 * XXX ASTERISK-22366 this needs more work. The channels need
1660 * to be made compatible again if the formats change. The
1661 * bridge_channel thread needs to monitor for this case.
1662 */
1663 /* The channel we want to notify is still in a bridge. */
1664 bridge->v_table->notify_masquerade(bridge, bridge_channel);
1665 bridge_reconfigured(bridge, 1);
1666 }
1667 ast_bridge_unlock(bridge);
1668 ao2_ref(bridge_channel, -1);
1669}
1670
1671/*!
1672 * \brief Internal bridge impart wait condition and associated conditional.
1673 */
1676 /*! Lock for the data structure */
1678 /*! Wait condition */
1680 /*! Wait until done */
1681 int done;
1682};
1683
1685
1686/*!
1687 * \internal
1688 * \brief Signal imparting threads to wake up.
1689 * \since 13.9.0
1690 *
1691 * \param ds_head List of imparting threads to wake up.
1692 */
1694{
1695 if (ds_head) {
1697
1698 while ((cond = AST_LIST_REMOVE_HEAD(ds_head, node))) {
1699 ast_mutex_lock(&cond->lock);
1700 cond->done = 1;
1701 ast_cond_signal(&cond->cond);
1702 ast_mutex_unlock(&cond->lock);
1703 }
1704 }
1705}
1706
1707static void bridge_channel_impart_ds_head_dtor(void *doomed)
1708{
1710 ast_free(doomed);
1711}
1712
1713/*!
1714 * \internal
1715 * \brief Fixup the bridge impart datastore.
1716 * \since 13.9.0
1717 *
1718 * \param data Bridge impart datastore data to fixup from old_chan.
1719 * \param old_chan The datastore is moving from this channel.
1720 * \param new_chan The datastore is moving to this channel.
1721 */
1722static void bridge_channel_impart_ds_head_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
1723{
1724 /*
1725 * Signal any waiting impart threads. The masquerade is going to kill
1726 * old_chan and we don't need to be waiting on new_chan.
1727 */
1729}
1730
1732 .type = "bridge-impart-ds",
1735};
1736
1737/*!
1738 * \internal
1739 * \brief Add impart wait datastore conditional to channel.
1740 * \since 13.9.0
1741 *
1742 * \param chan Channel to add the impart wait conditional.
1743 * \param cond Imparting conditional to add.
1744 *
1745 * \retval 0 on success.
1746 * \retval -1 on error.
1747 */
1749{
1750 struct ast_datastore *datastore;
1751 struct bridge_channel_impart_ds_head *ds_head;
1752
1753 ast_channel_lock(chan);
1754
1756 if (!datastore) {
1758 if (!datastore) {
1759 ast_channel_unlock(chan);
1760 return -1;
1761 }
1762 ds_head = ast_calloc(1, sizeof(*ds_head));
1763 if (!ds_head) {
1764 ast_channel_unlock(chan);
1765 ast_datastore_free(datastore);
1766 return -1;
1767 }
1768 datastore->data = ds_head;
1769 ast_channel_datastore_add(chan, datastore);
1770 } else {
1771 ds_head = datastore->data;
1772 ast_assert(ds_head != NULL);
1773 }
1774
1775 AST_LIST_INSERT_TAIL(ds_head, cond, node);
1776
1777 ast_channel_unlock(chan);
1778 return 0;
1779}
1780
1782{
1783 struct ast_datastore *datastore;
1784
1785 ast_channel_lock(chan);
1787 if (datastore) {
1789 }
1790 ast_channel_unlock(chan);
1791}
1792
1793/*!
1794 * \internal
1795 * \brief Block imparting channel thread until signaled.
1796 * \since 13.9.0
1797 *
1798 * \param cond Imparting conditional to wait for.
1799 */
1801{
1802 ast_mutex_lock(&cond->lock);
1803 while (!cond->done) {
1804 ast_cond_wait(&cond->cond, &cond->lock);
1805 }
1806 ast_mutex_unlock(&cond->lock);
1807}
1808
1809/*
1810 * XXX ASTERISK-21271 make ast_bridge_join() require features to be allocated just like ast_bridge_impart() and not expect the struct back.
1811 *
1812 * This change is really going to break ConfBridge. All other
1813 * users are easily changed. However, it is needed so the
1814 * bridging code can manipulate features on all channels
1815 * consistently no matter how they joined.
1816 *
1817 * Need to update the features parameter doxygen when this
1818 * change is made to be like ast_bridge_impart().
1819 */
1820int ast_bridge_join(struct ast_bridge *bridge,
1821 struct ast_channel *chan,
1822 struct ast_channel *swap,
1823 struct ast_bridge_features *features,
1824 struct ast_bridge_tech_optimizations *tech_args,
1825 enum ast_bridge_join_flags flags)
1826{
1827 struct ast_bridge_channel *bridge_channel;
1828 int res = 0;
1829 SCOPE_TRACE(1, "%s Bridge: %s\n", ast_channel_name(chan), bridge->uniqueid);
1830
1831 bridge_channel = bridge_channel_internal_alloc(bridge);
1832 if (flags & AST_BRIDGE_JOIN_PASS_REFERENCE) {
1833 ao2_ref(bridge, -1);
1834 }
1835 if (!bridge_channel) {
1836 ao2_t_cleanup(swap, "Error exit: bridge_channel alloc failed");
1837 res = -1;
1838 goto join_exit;
1839 }
1840/* 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. */
1842 if (!features) {
1843 ao2_ref(bridge_channel, -1);
1844 ao2_t_cleanup(swap, "Error exit: features is NULL");
1845 res = -1;
1846 goto join_exit;
1847 }
1848 if (tech_args) {
1849 bridge_channel->tech_args = *tech_args;
1850 }
1851
1854 res = -1;
1855 } else {
1857 }
1859 bridge_channel->thread = pthread_self();
1860 bridge_channel->chan = chan;
1861 bridge_channel->swap = swap;
1862 bridge_channel->features = features;
1863 bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP);
1864
1865 /* allow subclass to peek at upcoming push operation */
1866 if (bridge->v_table->push_peek && !res) {
1867 struct ast_bridge_channel *bcswap = NULL;
1868
1870 if (bridge_channel->swap) {
1871 bcswap = bridge_find_channel(bridge, bridge_channel->swap);
1872 }
1873 res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
1875 }
1876
1877 if (!res) {
1878 res = bridge_channel_internal_join(bridge_channel);
1879 }
1880
1881 /* Cleanup all the data in the bridge channel after it leaves the bridge. */
1885 /* Due to a race condition, we lock the bridge channel here for ast_bridge_channel_get_chan */
1886 ao2_lock(bridge_channel);
1887 bridge_channel->chan = NULL;
1888 ao2_unlock(bridge_channel);
1889 /* If bridge_channel->swap is not NULL then the join failed. */
1890 ao2_t_cleanup(bridge_channel->swap, "Bridge complete: join failed");
1891 bridge_channel->swap = NULL;
1892 bridge_channel->features = NULL;
1893
1894 ao2_ref(bridge_channel, -1);
1895
1896join_exit:
1901 /* Claim the after bridge goto is an async goto destination. */
1905 }
1906 return res;
1907}
1908
1909/*! \brief Thread responsible for imparted bridged channels to be departed */
1910static void *bridge_channel_depart_thread(void *data)
1911{
1912 struct ast_bridge_channel *bridge_channel = data;
1913 int res = 0;
1914
1915 if (bridge_channel->callid) {
1916 ast_callid_threadassoc_add(bridge_channel->callid);
1917 }
1918
1919 res = bridge_channel_internal_join(bridge_channel);
1920
1921 /*
1922 * cleanup
1923 *
1924 * If bridge_channel->swap is not NULL then the join failed.
1925 */
1926 ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Departable impart join failed");
1927 bridge_channel->swap = NULL;
1928 ast_bridge_features_destroy(bridge_channel->features);
1929 bridge_channel->features = NULL;
1930
1933 /* If join failed there will be impart threads waiting. */
1934 bridge_channel_impart_signal(bridge_channel->chan);
1935 ast_bridge_discard_after_goto(bridge_channel->chan);
1936
1937 return NULL;
1938}
1939
1940/*! \brief Thread responsible for independent imparted bridged channels */
1941static void *bridge_channel_ind_thread(void *data)
1942{
1943 struct ast_bridge_channel *bridge_channel = data;
1944 struct ast_channel *chan;
1945
1946 if (bridge_channel->callid) {
1948 }
1949
1951 chan = bridge_channel->chan;
1952
1953 /* cleanup */
1954 ast_channel_lock(chan);
1956 ast_channel_unlock(chan);
1957 /* Lock here for ast_bridge_channel_get_chan */
1961 /* If bridge_channel->swap is not NULL then the join failed. */
1962 ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Independent impart join failed");
1966
1968
1970 /* If join failed there will be impart threads waiting. */
1973 return NULL;
1974}
1975
1977 struct ast_channel *chan,
1978 struct ast_channel *swap,
1979 struct ast_bridge_features *features,
1982{
1983 int res = 0;
1984 struct ast_bridge_channel *bridge_channel;
1985
1986 /* Imparted channels cannot have a PBX. */
1987 if (ast_channel_pbx(chan)) {
1988 ast_log(AST_LOG_WARNING, "Channel %s has a PBX thread and cannot be imparted into bridge %s\n",
1991 return -1;
1992 }
1993
1994 /* Supply an empty features structure if the caller did not. */
1995 if (!features) {
1997 if (!features) {
1998 return -1;
1999 }
2000 }
2001
2002 /* Try to allocate a structure for the bridge channel */
2003 bridge_channel = bridge_channel_internal_alloc(bridge);
2004 if (!bridge_channel) {
2006 return -1;
2007 }
2008
2011 ast_log(AST_LOG_NOTICE, "Channel %s is a zombie and cannot be imparted into bridge %s\n",
2013 res = -1;
2014 } else {
2016 }
2018 bridge_channel->chan = chan;
2019 bridge_channel->swap = ao2_t_bump(swap, "Setting up bridge impart");
2020 bridge_channel->features = features;
2021 bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP);
2022 bridge_channel->depart_wait =
2024 bridge_channel->callid = ast_read_threadstorage_callid();
2025
2026 /* allow subclass to peek at swap channel before it can hangup */
2027 if (bridge->v_table->push_peek && !res) {
2028 struct ast_bridge_channel *bcswap = NULL;
2029
2031 if (bridge_channel->swap) {
2032 bcswap = bridge_find_channel(bridge, bridge_channel->swap);
2033 }
2034 res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
2036 }
2037
2038 /* Actually create the thread that will handle the channel */
2039 if (!res) {
2041 }
2042 if (!res) {
2044 res = ast_pthread_create_detached(&bridge_channel->thread, NULL,
2045 bridge_channel_ind_thread, bridge_channel);
2046 } else {
2047 res = ast_pthread_create(&bridge_channel->thread, NULL,
2048 bridge_channel_depart_thread, bridge_channel);
2049 }
2050
2051 if (!res) {
2053 }
2054 }
2055
2056 if (res) {
2057 /* cleanup */
2061 /* Lock here for ast_bridge_channel_get_chan */
2062 ao2_lock(bridge_channel);
2063 bridge_channel->chan = NULL;
2064 ao2_unlock(bridge_channel);
2065 ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Impart failed");
2066 bridge_channel->swap = NULL;
2067 ast_bridge_features_destroy(bridge_channel->features);
2068 bridge_channel->features = NULL;
2069
2070 ao2_ref(bridge_channel, -1);
2071 return -1;
2072 }
2073
2074 return 0;
2075}
2076
2078 struct ast_channel *chan,
2079 struct ast_channel *swap,
2081 enum ast_bridge_impart_flags flags)
2082{
2084 .done = 0,
2085 };
2086 int res;
2087 SCOPE_TRACE(1, "%s Bridge: %s\n", ast_channel_name(chan), bridge->uniqueid);
2088
2089 ast_mutex_init(&cond.lock);
2090 ast_cond_init(&cond.cond, NULL);
2091
2092 res = bridge_impart_internal(bridge, chan, swap, features, flags, &cond);
2093 if (res) {
2094 /* Impart failed. Signal any other waiting impart threads */
2097 }
2098
2099 ast_cond_destroy(&cond.cond);
2100 ast_mutex_destroy(&cond.lock);
2101
2102 return res;
2103}
2104
2106{
2107 struct ast_bridge_channel *bridge_channel;
2108 int departable;
2109 SCOPE_TRACE(1, "%s\n", ast_channel_name(chan));
2110
2112 bridge_channel = ast_channel_internal_bridge_channel(chan);
2113 departable = bridge_channel && bridge_channel->depart_wait;
2115 if (!departable) {
2116 ast_log(LOG_ERROR, "Channel %s cannot be departed.\n",
2118 /*
2119 * Should never happen. It likely means that
2120 * ast_bridge_depart() is called by two threads for the same
2121 * channel, the channel was never imparted to be departed, or it
2122 * has already been departed.
2123 */
2124 ast_assert(0);
2125 return -1;
2126 }
2127
2128 /*
2129 * We are claiming the bridge_channel reference held by
2130 * bridge_channel_depart_thread().
2131 */
2132
2133 ast_bridge_channel_leave_bridge(bridge_channel,
2135
2136 /* Wait for the depart thread to die */
2137 ast_debug(1, "Waiting for %p(%s) bridge thread to die.\n",
2138 bridge_channel, ast_channel_name(bridge_channel->chan));
2139 pthread_join(bridge_channel->thread, NULL);
2140
2144
2145 /* We can get rid of the bridge_channel after the depart thread has died. */
2146 ao2_ref(bridge_channel, -1);
2147 return 0;
2148}
2149
2151{
2152 struct ast_bridge_channel *bridge_channel;
2153
2154 ast_debug(1, "Removing channel %s from bridge %s\n",
2156
2158
2159 /* Try to find the channel that we want to remove */
2160 if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
2162 return -1;
2163 }
2164
2165 ast_bridge_channel_leave_bridge(bridge_channel,
2167
2169
2170 return 0;
2171}
2172
2173static void kick_it(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
2174{
2176}
2177
2179{
2180 struct ast_bridge_channel *bridge_channel;
2181 int res;
2182
2184
2185 /* Try to find the channel that we want to kick. */
2186 if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
2188 return -1;
2189 }
2190
2191 res = ast_bridge_channel_queue_callback(bridge_channel, 0, kick_it, NULL, 0);
2192
2194
2195 return res;
2196}
2197
2198/*!
2199 * \internal
2200 * \brief Point the bridge_channel to a new bridge.
2201 * \since 12.0.0
2202 *
2203 * \param bridge_channel What is to point to a new bridge.
2204 * \param new_bridge Where the bridge channel should point.
2205 */
2206static void bridge_channel_change_bridge(struct ast_bridge_channel *bridge_channel, struct ast_bridge *new_bridge)
2207{
2208 struct ast_bridge *old_bridge;
2209
2210 ao2_ref(new_bridge, +1);
2211 ast_bridge_channel_lock(bridge_channel);
2212 ast_channel_lock(bridge_channel->chan);
2213 old_bridge = bridge_channel->bridge;
2214 bridge_channel->bridge = new_bridge;
2215 ast_channel_internal_bridge_set(bridge_channel->chan, new_bridge);
2216 ast_channel_unlock(bridge_channel->chan);
2217 ast_bridge_channel_unlock(bridge_channel);
2218 ao2_ref(old_bridge, -1);
2219}
2220
2221static void bridge_channel_moving(struct ast_bridge_channel *bridge_channel, struct ast_bridge *src, struct ast_bridge *dst)
2222{
2223 struct ast_bridge_features *features = bridge_channel->features;
2224 struct ast_bridge_hook *hook;
2225 struct ao2_iterator iter;
2226
2227 /* Run any moving hooks. */
2228 iter = ao2_iterator_init(features->other_hooks, 0);
2229 for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
2230 int remove_me;
2232
2233 if (hook->type != AST_BRIDGE_HOOK_TYPE_MOVE) {
2234 continue;
2235 }
2237 remove_me = move_cb(bridge_channel, hook->hook_pvt, src, dst);
2238 if (remove_me) {
2239 ast_debug(1, "Move detection hook %p is being removed from %p(%s)\n",
2240 hook, bridge_channel, ast_channel_name(bridge_channel->chan));
2241 ao2_unlink(features->other_hooks, hook);
2242 }
2243 }
2244 ao2_iterator_destroy(&iter);
2245}
2246
2247void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_bridge_channel **kick_me, unsigned int num_kick,
2248 unsigned int optimized)
2249{
2250 struct ast_bridge_channel *bridge_channel;
2251 unsigned int idx;
2252
2253 ast_debug(1, "Merging bridge %s into bridge %s\n",
2254 src_bridge->uniqueid, dst_bridge->uniqueid);
2255
2256 ast_bridge_publish_merge(dst_bridge, src_bridge);
2257
2258 /*
2259 * Move channels from src_bridge over to dst_bridge.
2260 *
2261 * We must use AST_LIST_TRAVERSE_SAFE_BEGIN() because
2262 * bridge_channel_internal_pull() alters the list we are traversing.
2263 */
2264 AST_LIST_TRAVERSE_SAFE_BEGIN(&src_bridge->channels, bridge_channel, entry) {
2265 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
2266 /*
2267 * The channel is already leaving let it leave normally because
2268 * pulling it may delete hooks that should run for this channel.
2269 */
2270 continue;
2271 }
2272 if (ast_test_flag(&bridge_channel->features->feature_flags,
2274 continue;
2275 }
2276
2277 if (kick_me) {
2278 for (idx = 0; idx < num_kick; ++idx) {
2279 if (bridge_channel == kick_me[idx]) {
2280 ast_bridge_channel_leave_bridge(bridge_channel,
2282 break;
2283 }
2284 }
2285 }
2286 bridge_channel_internal_pull(bridge_channel);
2287 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
2288 /*
2289 * The channel died as a result of being pulled or it was
2290 * kicked. Leave it pointing to the original bridge.
2291 */
2292 continue;
2293 }
2294
2295 bridge_channel_moving(bridge_channel, bridge_channel->bridge, dst_bridge);
2296
2297 /* Point to new bridge.*/
2298 bridge_channel_change_bridge(bridge_channel, dst_bridge);
2299
2300 if (bridge_channel_internal_push(bridge_channel)) {
2301 ast_bridge_features_remove(bridge_channel->features,
2303 ast_bridge_channel_leave_bridge(bridge_channel,
2305 }
2306 }
2308
2309 if (kick_me) {
2310 /*
2311 * Now we can kick any channels in the dst_bridge without
2312 * potentially dissolving the bridge.
2313 */
2314 for (idx = 0; idx < num_kick; ++idx) {
2315 bridge_channel = kick_me[idx];
2316 ast_bridge_channel_lock(bridge_channel);
2317 if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
2320 bridge_channel_internal_pull(bridge_channel);
2321 }
2322 ast_bridge_channel_unlock(bridge_channel);
2323 }
2324 }
2325
2326 bridge_reconfigured(dst_bridge, !optimized);
2327 bridge_reconfigured(src_bridge, !optimized);
2328
2329 ast_debug(1, "Merged bridge %s into bridge %s\n",
2330 src_bridge->uniqueid, dst_bridge->uniqueid);
2331}
2332
2334 /*! Destination merge bridge. */
2336 /*! Source merge bridge. */
2338};
2339
2340/*!
2341 * \internal
2342 * \brief Determine which bridge should merge into the other.
2343 * \since 12.0.0
2344 *
2345 * \param bridge1 A bridge for merging
2346 * \param bridge2 A bridge for merging
2347 *
2348 * \note The two bridges are assumed already locked.
2349 *
2350 * \return Which bridge merges into which or NULL bridges if cannot merge.
2351 */
2352static struct merge_direction bridge_merge_determine_direction(struct ast_bridge *bridge1, struct ast_bridge *bridge2)
2353{
2354 struct merge_direction merge = { NULL, NULL };
2355 int bridge1_priority;
2356 int bridge2_priority;
2357
2358 if (!ast_test_flag(&bridge1->feature_flags,
2360 && !ast_test_flag(&bridge2->feature_flags,
2362 /*
2363 * Can merge either way. Merge to the higher priority merge
2364 * bridge. Otherwise merge to the larger bridge.
2365 */
2366 bridge1_priority = bridge1->v_table->get_merge_priority(bridge1);
2367 bridge2_priority = bridge2->v_table->get_merge_priority(bridge2);
2368 if (bridge2_priority < bridge1_priority) {
2369 merge.dest = bridge1;
2370 merge.src = bridge2;
2371 } else if (bridge1_priority < bridge2_priority) {
2372 merge.dest = bridge2;
2373 merge.src = bridge1;
2374 } else {
2375 /* Merge to the larger bridge. */
2376 if (bridge2->num_channels <= bridge1->num_channels) {
2377 merge.dest = bridge1;
2378 merge.src = bridge2;
2379 } else {
2380 merge.dest = bridge2;
2381 merge.src = bridge1;
2382 }
2383 }
2384 } else if (!ast_test_flag(&bridge1->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
2385 && !ast_test_flag(&bridge2->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
2386 /* Can merge only one way. */
2387 merge.dest = bridge1;
2388 merge.src = bridge2;
2389 } else if (!ast_test_flag(&bridge2->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
2390 && !ast_test_flag(&bridge1->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
2391 /* Can merge only one way. */
2392 merge.dest = bridge2;
2393 merge.src = bridge1;
2394 }
2395
2396 return merge;
2397}
2398
2399/*!
2400 * \internal
2401 * \brief Merge two bridges together
2402 * \since 12.0.0
2403 *
2404 * \param dst_bridge Destination bridge of merge.
2405 * \param src_bridge Source bridge of merge.
2406 * \param merge_best_direction TRUE if don't care about which bridge merges into the other.
2407 * \param kick_me Array of channels to kick from the bridges.
2408 * \param num_kick Number of channels in the kick_me array.
2409 *
2410 * \note The dst_bridge and src_bridge are assumed already locked.
2411 *
2412 * \retval 0 on success
2413 * \retval -1 on failure
2414 */
2415static 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)
2416{
2417 struct merge_direction merge;
2418 struct ast_bridge_channel **kick_them = NULL;
2419
2420 /* Sanity check. */
2421 ast_assert(dst_bridge && src_bridge && dst_bridge != src_bridge && (!num_kick || kick_me));
2422
2423 if (dst_bridge->dissolved || src_bridge->dissolved) {
2424 ast_debug(1, "Can't merge bridges %s and %s, at least one bridge is dissolved.\n",
2425 src_bridge->uniqueid, dst_bridge->uniqueid);
2426 return -1;
2427 }
2430 ast_debug(1, "Can't merge bridges %s and %s, masquerade only.\n",
2431 src_bridge->uniqueid, dst_bridge->uniqueid);
2432 return -1;
2433 }
2434 if (dst_bridge->inhibit_merge || src_bridge->inhibit_merge) {
2435 ast_debug(1, "Can't merge bridges %s and %s, merging temporarily inhibited.\n",
2436 src_bridge->uniqueid, dst_bridge->uniqueid);
2437 return -1;
2438 }
2439
2440 if (merge_best_direction) {
2441 merge = bridge_merge_determine_direction(dst_bridge, src_bridge);
2442 } else {
2443 merge.dest = dst_bridge;
2444 merge.src = src_bridge;
2445 }
2446
2447 if (!merge.dest
2450 ast_debug(1, "Can't merge bridges %s and %s, merging inhibited.\n",
2451 src_bridge->uniqueid, dst_bridge->uniqueid);
2452 return -1;
2453 }
2454 if (merge.src->num_channels < 2) {
2455 /*
2456 * For a two party bridge, a channel may be temporarily removed
2457 * from the source bridge or the initial bridge members have not
2458 * joined yet.
2459 */
2460 ast_debug(1, "Can't merge bridge %s into bridge %s, not enough channels in source bridge.\n",
2461 merge.src->uniqueid, merge.dest->uniqueid);
2462 return -1;
2463 }
2464 if (2 + num_kick < merge.dest->num_channels + merge.src->num_channels
2468 ast_debug(1, "Can't merge bridge %s into bridge %s, multimix is needed and it cannot be acquired.\n",
2469 merge.src->uniqueid, merge.dest->uniqueid);
2470 return -1;
2471 }
2472
2473 if (num_kick) {
2474 unsigned int num_to_kick = 0;
2475 unsigned int idx;
2476
2477 kick_them = ast_alloca(num_kick * sizeof(*kick_them));
2478 for (idx = 0; idx < num_kick; ++idx) {
2479 kick_them[num_to_kick] = bridge_find_channel(merge.src, kick_me[idx]);
2480 if (!kick_them[num_to_kick]) {
2481 kick_them[num_to_kick] = bridge_find_channel(merge.dest, kick_me[idx]);
2482 }
2483 if (kick_them[num_to_kick]) {
2484 ++num_to_kick;
2485 }
2486 }
2487
2488 if (num_to_kick != num_kick) {
2489 ast_debug(1, "Can't merge bridge %s into bridge %s, at least one kicked channel is not in either bridge.\n",
2490 merge.src->uniqueid, merge.dest->uniqueid);
2491 return -1;
2492 }
2493 }
2494
2495 bridge_do_merge(merge.dest, merge.src, kick_them, num_kick, 0);
2496 return 0;
2497}
2498
2499int 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)
2500{
2501 int res;
2502
2503 /* Sanity check. */
2504 ast_assert(dst_bridge && src_bridge);
2505
2506 ast_bridge_lock_both(dst_bridge, src_bridge);
2507 res = bridge_merge_locked(dst_bridge, src_bridge, merge_best_direction, kick_me, num_kick);
2508 ast_bridge_unlock(src_bridge);
2509 ast_bridge_unlock(dst_bridge);
2510 return res;
2511}
2512
2513int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel, int attempt_recovery,
2514 unsigned int optimized)
2515{
2516 struct ast_bridge *orig_bridge;
2517 int was_in_bridge;
2518 int res = 0;
2519
2520 if (bridge_channel->swap) {
2521 ast_debug(1, "Moving %p(%s) into bridge %s swapping with %s\n",
2522 bridge_channel, ast_channel_name(bridge_channel->chan), dst_bridge->uniqueid,
2523 ast_channel_name(bridge_channel->swap));
2524 } else {
2525 ast_debug(1, "Moving %p(%s) into bridge %s\n",
2526 bridge_channel, ast_channel_name(bridge_channel->chan), dst_bridge->uniqueid);
2527 }
2528
2529 orig_bridge = bridge_channel->bridge;
2530 was_in_bridge = bridge_channel->in_bridge;
2531
2532 bridge_channel_internal_pull(bridge_channel);
2533 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
2534 /*
2535 * The channel died as a result of being pulled. Leave it
2536 * pointing to the original bridge.
2537 *
2538 * Clear out the swap channel pointer. A ref is not held
2539 * by bridge_channel->swap at this point.
2540 */
2541 bridge_channel->swap = NULL;
2542 bridge_reconfigured(orig_bridge, 0);
2543 return -1;
2544 }
2545
2546 /* Point to new bridge.*/
2547 ao2_ref(orig_bridge, +1);/* Keep a ref in case the push fails. */
2548 bridge_channel_change_bridge(bridge_channel, dst_bridge);
2549
2550 bridge_channel_moving(bridge_channel, orig_bridge, dst_bridge);
2551
2552 if (bridge_channel_internal_push_full(bridge_channel, optimized)) {
2553 /* Try to put the channel back into the original bridge. */
2554 ast_bridge_features_remove(bridge_channel->features,
2556 if (attempt_recovery && was_in_bridge) {
2557 /* Point back to original bridge. */
2558 bridge_channel_change_bridge(bridge_channel, orig_bridge);
2559
2560 if (bridge_channel_internal_push(bridge_channel)) {
2561 ast_bridge_features_remove(bridge_channel->features,
2563 ast_bridge_channel_leave_bridge(bridge_channel,
2565 }
2566 } else {
2567 ast_bridge_channel_leave_bridge(bridge_channel,
2569 bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
2570 }
2571 res = -1;
2572 } else if (!optimized) {
2573 bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
2574 }
2575
2576 bridge_reconfigured(dst_bridge, !optimized);
2577 bridge_reconfigured(orig_bridge, !optimized);
2578 ao2_ref(orig_bridge, -1);
2579 return res;
2580}
2581
2582/*!
2583 * \internal
2584 * \brief Move a channel from one bridge to another.
2585 * \since 12.0.0
2586 *
2587 * \param dst_bridge Destination bridge of bridge channel move.
2588 * \param src_bridge Source bridge of bridge channel move.
2589 * \param chan Channel to move.
2590 * \param swap Channel to replace in dst_bridge.
2591 * \param attempt_recovery TRUE if failure attempts to push channel back into original bridge.
2592 *
2593 * \note The dst_bridge and src_bridge are assumed already locked.
2594 *
2595 * \retval 0 on success.
2596 * \retval -1 on failure.
2597 */
2598static 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)
2599{
2600 struct ast_bridge_channel *bridge_channel;
2601
2602 if (dst_bridge->dissolved || src_bridge->dissolved) {
2603 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, at least one bridge is dissolved.\n",
2604 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2605 return -1;
2606 }
2609 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, masquerade only.\n",
2610 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2611 return -1;
2612 }
2613 if (dst_bridge->inhibit_merge || src_bridge->inhibit_merge) {
2614 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, temporarily inhibited.\n",
2615 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2616 return -1;
2617 }
2618
2619 bridge_channel = bridge_find_channel(src_bridge, chan);
2620 if (!bridge_channel) {
2621 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel not in bridge.\n",
2622 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2623 return -1;
2624 }
2625 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
2626 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel leaving bridge.\n",
2627 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2628 return -1;
2629 }
2630 if (ast_test_flag(&bridge_channel->features->feature_flags,
2632 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel immovable.\n",
2633 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
2634 return -1;
2635 }
2636
2637 if (swap) {
2638 struct ast_bridge_channel *bridge_channel_swap;
2639
2640 bridge_channel_swap = bridge_find_channel(dst_bridge, swap);
2641 if (!bridge_channel_swap) {
2642 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, swap channel %s not in bridge.\n",
2643 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid,
2645 return -1;
2646 }
2647 if (bridge_channel_swap->state != BRIDGE_CHANNEL_STATE_WAIT) {
2648 ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, swap channel %s leaving bridge.\n",
2649 ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid,
2651 return -1;
2652 }
2653 }
2654
2655 bridge_channel->swap = swap;
2656 return bridge_do_move(dst_bridge, bridge_channel, attempt_recovery, 0);
2657}
2658
2659int ast_bridge_move(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_channel *chan, struct ast_channel *swap, int attempt_recovery)
2660{
2661 int res;
2662
2663 ast_bridge_lock_both(dst_bridge, src_bridge);
2664 res = bridge_move_locked(dst_bridge, src_bridge, chan, swap, attempt_recovery);
2665 ast_bridge_unlock(src_bridge);
2666 ast_bridge_unlock(dst_bridge);
2667 return res;
2668}
2669
2671 struct ast_bridge_features *features, int play_tone, const char *xfersound)
2672{
2673 RAII_VAR(struct ast_bridge *, chan_bridge, NULL, ao2_cleanup);
2674 RAII_VAR(struct ast_channel *, yanked_chan, NULL, ao2_cleanup);
2675
2677
2679 chan_bridge = ast_channel_get_bridge(chan);
2681
2682 if (chan_bridge) {
2683 struct ast_bridge_channel *bridge_channel;
2684
2685 /* The channel is in a bridge so it is not getting any new features. */
2687
2688 ast_bridge_lock_both(bridge, chan_bridge);
2689 bridge_channel = bridge_find_channel(chan_bridge, chan);
2690
2691 if (bridge_move_locked(bridge, chan_bridge, chan, NULL, 1)) {
2692 ast_bridge_unlock(chan_bridge);
2694 return -1;
2695 }
2696
2697 /*
2698 * bridge_move_locked() will implicitly ensure that
2699 * bridge_channel is not NULL.
2700 */
2701 ast_assert(bridge_channel != NULL);
2702
2703 /*
2704 * Additional checks if the channel we just stole dissolves the
2705 * original bridge.
2706 */
2707 bridge_dissolve_check_stolen(chan_bridge, bridge_channel);
2708 ast_bridge_unlock(chan_bridge);
2710 } else {
2711 int noanswer;
2712 const char *value;
2713 /* Slightly less easy case. We need to yank channel A from
2714 * where he currently is and impart him into our bridge.
2715 */
2716 yanked_chan = ast_channel_yank(chan);
2717 if (!yanked_chan) {
2718 ast_log(LOG_WARNING, "Could not gain control of channel %s\n", ast_channel_name(chan));
2720 return -1;
2721 }
2722
2724 value = pbx_builtin_getvar_helper(chan, "BRIDGE_NOANSWER");
2725 noanswer = !ast_strlen_zero(value) ? 1 : 0;
2727 if (noanswer) {
2728 ast_debug(3, "Skipping answer on bridge target channel %s\n", ast_channel_name(chan));
2729 } else if (ast_channel_state(yanked_chan) != AST_STATE_UP) {
2730 ast_answer(yanked_chan);
2731 }
2732
2733 ast_channel_ref(yanked_chan);
2734 if (ast_bridge_impart(bridge, yanked_chan, NULL, features,
2736 /* It is possible for us to yank a channel and have some other
2737 * thread start a PBX on the channel after we yanked it. In particular,
2738 * this can theoretically happen on the ;2 of a Local channel if we
2739 * yank it prior to the ;1 being answered. Make sure that it isn't
2740 * executing a PBX before hanging it up.
2741 */
2742 if (ast_channel_pbx(yanked_chan)) {
2743 ast_channel_unref(yanked_chan);
2744 } else {
2745 ast_hangup(yanked_chan);
2746 }
2747 return -1;
2748 }
2749 }
2750
2751 if (play_tone && !ast_strlen_zero(xfersound)) {
2752 struct ast_channel *play_chan = yanked_chan ?: chan;
2753 RAII_VAR(struct ast_bridge_channel *, play_bridge_channel, NULL, ao2_cleanup);
2754
2755 ast_channel_lock(play_chan);
2756 play_bridge_channel = ast_channel_get_bridge_channel(play_chan);
2757 ast_channel_unlock(play_chan);
2758
2759 if (!play_bridge_channel) {
2760 ast_log(LOG_WARNING, "Unable to play tone for channel %s. No longer in a bridge.\n",
2761 ast_channel_name(play_chan));
2762 } else {
2763 ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, xfersound, NULL);
2764 }
2765 }
2766 return 0;
2767}
2768
2775
2776/*!
2777 * \internal
2778 * \brief Lock the unreal channel stack for chan and prequalify it.
2779 * \since 12.0.0
2780 *
2781 * \param chan Unreal channel writing a frame into the channel driver.
2782 *
2783 * \note It is assumed that chan is already locked.
2784 *
2785 * \return bridge on success with bridge and bridge_channel locked.
2786 * \retval NULL if cannot do optimization now.
2787 */
2789{
2790 struct ast_bridge *bridge;
2791 struct ast_bridge_channel *bridge_channel;
2792
2794 return NULL;
2795 }
2797 return NULL;
2798 }
2800 /* Channel has an active monitor, audiohook, or framehook. */
2801 return NULL;
2802 }
2803 bridge_channel = ast_channel_internal_bridge_channel(chan);
2804 if (!bridge_channel || ast_bridge_channel_trylock(bridge_channel)) {
2805 return NULL;
2806 }
2807 bridge = bridge_channel->bridge;
2808 if (bridge_channel->activity != BRIDGE_CHANNEL_THREAD_SIMPLE
2809 || bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT
2811 ast_bridge_channel_unlock(bridge_channel);
2812 return NULL;
2813 }
2814 if (!bridge_channel_internal_allows_optimization(bridge_channel) ||
2817 ast_bridge_channel_unlock(bridge_channel);
2818 return NULL;
2819 }
2820 return bridge;
2821}
2822
2823/*!
2824 * \internal
2825 * \brief Lock the unreal channel stack for peer and prequalify it.
2826 * \since 12.0.0
2827 *
2828 * \param peer Other unreal channel in the pair.
2829 *
2830 * \return bridge on success with bridge, bridge_channel, and peer locked.
2831 * \retval NULL if cannot do optimization now.
2832 */
2834{
2835 struct ast_bridge *bridge;
2836 struct ast_bridge_channel *bridge_channel;
2837
2838 if (ast_channel_trylock(peer)) {
2839 return NULL;
2840 }
2841 if (!AST_LIST_EMPTY(ast_channel_readq(peer))) {
2842 ast_channel_unlock(peer);
2843 return NULL;
2844 }
2846 ast_channel_unlock(peer);
2847 return NULL;
2848 }
2850 /* Peer has an active monitor, audiohook, or framehook. */
2851 ast_channel_unlock(peer);
2852 return NULL;
2853 }
2854 bridge_channel = ast_channel_internal_bridge_channel(peer);
2855 if (!bridge_channel || ast_bridge_channel_trylock(bridge_channel)) {
2856 ast_channel_unlock(peer);
2857 return NULL;
2858 }
2859 bridge = bridge_channel->bridge;
2860 if (bridge_channel->activity != BRIDGE_CHANNEL_THREAD_IDLE
2861 || bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT
2863 ast_bridge_channel_unlock(bridge_channel);
2864 ast_channel_unlock(peer);
2865 return NULL;
2866 }
2870 ast_bridge_channel_unlock(bridge_channel);
2871 ast_channel_unlock(peer);
2872 return NULL;
2873 }
2874 return bridge;
2875}
2876
2877/*!
2878 * \internal
2879 * \brief Indicates allowability of a swap optimization
2880 */
2882 /*! Bridges cannot allow for a swap optimization to occur */
2884 /*! Bridge swap optimization can occur into the chan_bridge */
2886 /*! Bridge swap optimization can occur into the peer_bridge */
2888};
2889
2890/*!
2891 * \internal
2892 * \brief Determine if two bridges allow for swap optimization to occur
2893 *
2894 * \param chan_bridge First bridge being tested
2895 * \param peer_bridge Second bridge being tested
2896 * \return Allowability of swap optimization
2897 */
2899 struct ast_bridge *peer_bridge)
2900{
2901 int chan_priority;
2902 int peer_priority;
2903
2904 if (!ast_test_flag(&chan_bridge->feature_flags,
2907 && !ast_test_flag(&peer_bridge->feature_flags,
2910 /*
2911 * Can swap either way. Swap to the higher priority merge
2912 * bridge.
2913 */
2914 chan_priority = chan_bridge->v_table->get_merge_priority(chan_bridge);
2915 peer_priority = peer_bridge->v_table->get_merge_priority(peer_bridge);
2916 if (chan_bridge->num_channels == 2
2917 && chan_priority <= peer_priority) {
2918 return SWAP_TO_PEER_BRIDGE;
2919 } else if (peer_bridge->num_channels == 2
2920 && peer_priority <= chan_priority) {
2921 return SWAP_TO_CHAN_BRIDGE;
2922 }
2923 } else if (chan_bridge->num_channels == 2
2926 /* Can swap optimize only one way. */
2927 return SWAP_TO_PEER_BRIDGE;
2928 } else if (peer_bridge->num_channels == 2
2931 /* Can swap optimize only one way. */
2932 return SWAP_TO_CHAN_BRIDGE;
2933 }
2934
2935 return SWAP_PROHIBITED;
2936}
2937
2938/*!
2939 * \internal
2940 * \brief Check and attempt to swap optimize out the unreal channels.
2941 * \since 12.0.0
2942 *
2943 * \param chan_bridge
2944 * \param chan_bridge_channel
2945 * \param peer_bridge
2946 * \param peer_bridge_channel
2947 * \param pvt Unreal data containing callbacks to call if the optimization actually
2948 * happens
2949 *
2950 * \retval 1 if unreal channels failed to optimize out.
2951 * \retval 0 if unreal channels were not optimized out.
2952 * \retval -1 if unreal channels were optimized out.
2953 */
2954static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
2955 struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge,
2956 struct ast_bridge_channel *peer_bridge_channel,
2957 struct ast_unreal_pvt *pvt)
2958{
2959 struct ast_bridge *dst_bridge;
2960 struct ast_bridge_channel *dst_bridge_channel;
2961 struct ast_bridge_channel *src_bridge_channel;
2962 struct ast_bridge_channel *other;
2963 int res = 1;
2964
2965 switch (bridges_allow_swap_optimization(chan_bridge, peer_bridge)) {
2967 dst_bridge = chan_bridge;
2968 dst_bridge_channel = chan_bridge_channel;
2969 src_bridge_channel = peer_bridge_channel;
2970 break;
2972 dst_bridge = peer_bridge;
2973 dst_bridge_channel = peer_bridge_channel;
2974 src_bridge_channel = chan_bridge_channel;
2975 break;
2976 case SWAP_PROHIBITED:
2977 default:
2978 return 0;
2979 }
2980
2981 other = ast_bridge_channel_peer(src_bridge_channel);
2982 if (other && other->state == BRIDGE_CHANNEL_STATE_WAIT) {
2983 unsigned int id;
2984
2985 if (ast_channel_trylock(other->chan)) {
2986 return 1;
2987 }
2988
2989 id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
2990
2991 ast_verb(4, "Move-swap optimizing %s <-- %s.\n",
2992 ast_channel_name(dst_bridge_channel->chan),
2993 ast_channel_name(other->chan));
2994
2995 if (pvt && !ast_test_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN) && pvt->callbacks
2997 pvt->callbacks->optimization_started(pvt, other->chan,
2998 dst_bridge_channel->chan == pvt->owner ? AST_UNREAL_OWNER : AST_UNREAL_CHAN,
2999 id);
3001 }
3002 other->swap = dst_bridge_channel->chan;
3003 if (!bridge_do_move(dst_bridge, other, 1, 1)) {
3004 ast_bridge_channel_leave_bridge(src_bridge_channel,
3006 res = -1;
3007 }
3008 if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
3009 pvt->callbacks->optimization_finished(pvt, res == 1, id);
3010 }
3011 ast_channel_unlock(other->chan);
3012 }
3013 return res;
3014}
3015
3016/*!
3017 * \internal
3018 * \brief Indicates allowability of a merge optimization
3019 */
3021 /*! Bridge properties prohibit merge optimization */
3023 /*! Merge optimization cannot occur because the source bridge has too few channels */
3025 /*! Merge optimization cannot occur because multimix capability could not be requested */
3027 /*! Merge optimization allowed between bridges */
3029};
3030
3031/*!
3032 * \internal
3033 * \brief Determines allowability of a merge optimization
3034 *
3035 * \note The merge output parameter is undefined if MERGE_PROHIBITED is returned. For success
3036 * and other failure returns, a merge direction was determined, and the parameter is safe to
3037 * access.
3038 *
3039 * \param chan_bridge First bridge being tested
3040 * \param peer_bridge Second bridge being tested
3041 * \param num_kick_channels The number of channels to remove from the bridges during merging
3042 * \param[out] merge Indicates the recommended direction for the bridge merge
3043 */
3045 struct ast_bridge *peer_bridge, int num_kick_channels, struct merge_direction *merge)
3046{
3047 *merge = bridge_merge_determine_direction(chan_bridge, peer_bridge);
3048 if (!merge->dest) {
3049 return MERGE_PROHIBITED;
3050 }
3051 if (merge->src->num_channels < 2) {
3053 } else if ((2 + num_kick_channels) < merge->dest->num_channels + merge->src->num_channels
3057 return MERGE_NO_MULTIMIX;
3058 }
3059
3060 return MERGE_ALLOWED;
3061}
3062
3063/*!
3064 * \internal
3065 * \brief Check and attempt to merge optimize out the unreal channels.
3066 * \since 12.0.0
3067 *
3068 * \param chan_bridge
3069 * \param chan_bridge_channel
3070 * \param peer_bridge
3071 * \param peer_bridge_channel
3072 * \param pvt Unreal data containing callbacks to call if the optimization actually
3073 * happens
3074 *
3075 * \retval 0 if unreal channels were not optimized out.
3076 * \retval -1 if unreal channels were optimized out.
3077 */
3078static int try_merge_optimize_out(struct ast_bridge *chan_bridge,
3079 struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge,
3080 struct ast_bridge_channel *peer_bridge_channel,
3081 struct ast_unreal_pvt *pvt)
3082{
3083 struct merge_direction merge;
3084 struct ast_bridge_channel *kick_me[] = {
3085 chan_bridge_channel,
3086 peer_bridge_channel,
3087 };
3088 unsigned int id;
3089
3090 switch (bridges_allow_merge_optimization(chan_bridge, peer_bridge, ARRAY_LEN(kick_me), &merge)) {
3091 case MERGE_ALLOWED:
3092 break;
3093 case MERGE_PROHIBITED:
3094 return 0;
3096 ast_debug(4, "Can't optimize %s -- %s out, not enough channels in bridge %s.\n",
3097 ast_channel_name(chan_bridge_channel->chan),
3098 ast_channel_name(peer_bridge_channel->chan),
3099 merge.src->uniqueid);
3100 return 0;
3101 case MERGE_NO_MULTIMIX:
3102 ast_debug(4, "Can't optimize %s -- %s out, multimix is needed and it cannot be acquired.\n",
3103 ast_channel_name(chan_bridge_channel->chan),
3104 ast_channel_name(peer_bridge_channel->chan));
3105 return 0;
3106 }
3107
3108 ast_verb(4, "Merge optimizing %s -- %s out.\n",
3109 ast_channel_name(chan_bridge_channel->chan),
3110 ast_channel_name(peer_bridge_channel->chan));
3111
3112 id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
3113
3114 if (pvt && !ast_test_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN) && pvt->callbacks
3118 id);
3120 }
3121 bridge_do_merge(merge.dest, merge.src, kick_me, ARRAY_LEN(kick_me), 1);
3122 if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
3123 pvt->callbacks->optimization_finished(pvt, 1, id);
3124 }
3125
3126 return -1;
3127}
3128
3130{
3131 struct ast_bridge *chan_bridge;
3132 struct ast_bridge *peer_bridge;
3133 struct ast_bridge_channel *chan_bridge_channel;
3134 struct ast_bridge_channel *peer_bridge_channel;
3135 int res = 0;
3136
3137 chan_bridge = optimize_lock_chan_stack(chan);
3138 if (!chan_bridge) {
3139 return res;
3140 }
3141 chan_bridge_channel = ast_channel_internal_bridge_channel(chan);
3142
3143 peer_bridge = optimize_lock_peer_stack(peer);
3144 if (peer_bridge) {
3145 peer_bridge_channel = ast_channel_internal_bridge_channel(peer);
3146
3147 res = try_swap_optimize_out(chan_bridge, chan_bridge_channel,
3148 peer_bridge, peer_bridge_channel, pvt);
3149 if (!res) {
3150 res = try_merge_optimize_out(chan_bridge, chan_bridge_channel,
3151 peer_bridge, peer_bridge_channel, pvt);
3152 } else if (0 < res) {
3153 res = 0;
3154 }
3155
3156 /* Release peer locks. */
3157 ast_bridge_unlock(peer_bridge);
3158 ast_bridge_channel_unlock(peer_bridge_channel);
3159 ast_channel_unlock(peer);
3160 }
3161
3162 /* Release chan locks. */
3163 ast_bridge_unlock(chan_bridge);
3164 ast_bridge_channel_unlock(chan_bridge_channel);
3165
3166 return res;
3167}
3168
3170 struct ast_bridge *peer_bridge)
3171{
3172 struct merge_direction merge;
3173
3174 if (!bridge_allows_optimization(chan_bridge) || !bridge_allows_optimization(peer_bridge)) {
3176 }
3177
3178 switch (bridges_allow_swap_optimization(chan_bridge, peer_bridge)) {
3183 case SWAP_PROHIBITED:
3184 default:
3185 break;
3186 }
3187
3188 /* Two channels will be kicked from the bridges, the unreal;1 and unreal;2 channels */
3189 if (bridges_allow_merge_optimization(chan_bridge, peer_bridge, 2, &merge) != MERGE_ALLOWED) {
3191 }
3192
3193 if (merge.dest == chan_bridge) {
3195 } else {
3197 }
3198}
3199
3201{
3202 int new_request;
3203
3204 new_request = bridge->inhibit_merge + request;
3205 ast_assert(0 <= new_request);
3206 bridge->inhibit_merge = new_request;
3207}
3208
3210{
3211 ast_bridge_lock(bridge);
3213 ast_bridge_unlock(bridge);
3214}
3215
3216int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan)
3217{
3218 struct ast_bridge_channel *bridge_channel;
3219/* XXX ASTERISK-21271 the case of a dissolved bridge while channel is suspended is not handled. */
3220/* XXX ASTERISK-21271 suspend/unsuspend needs to be rethought. The caller must block until it has successfully suspended the channel for temporary control. */
3221/* 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. */
3222
3224
3225 if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
3227 return -1;
3228 }
3229
3231
3233
3234 return 0;
3235}
3236
3238{
3239 struct ast_bridge_channel *bridge_channel;
3240/* XXX ASTERISK-21271 the case of a dissolved bridge while channel is suspended is not handled. */
3241
3243
3244 if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
3246 return -1;
3247 }
3248
3250
3252
3253 return 0;
3254}
3255
3257{
3258 technology->suspended = 1;
3259}
3260
3262{
3263 /*
3264 * XXX We may want the act of unsuspending a bridge technology
3265 * to prod all existing bridges to see if they should start
3266 * using it.
3267 */
3268 technology->suspended = 0;
3269}
3270
3272{
3273 if (ARRAY_LEN(builtin_features_handlers) <= feature
3274 || builtin_features_handlers[feature]) {
3275 return -1;
3276 }
3277
3278 if (!ast_strlen_zero(dtmf)) {
3279 ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature]));
3280 }
3281
3283
3284 return 0;
3285}
3286
3288{
3289 if (ARRAY_LEN(builtin_features_handlers) <= feature
3290 || !builtin_features_handlers[feature]) {
3291 return -1;
3292 }
3293
3295
3296 return 0;
3297}
3298
3299int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
3300{
3302
3303 if (ARRAY_LEN(builtin_features_handlers) <= feature) {
3304 return -1;
3305 }
3306
3308 if (!callback) {
3309 return -1;
3310 }
3311 callback(bridge_channel, hook_pvt);
3312
3313 return 0;
3314}
3315
3317{
3318 if (ARRAY_LEN(builtin_interval_handlers) <= interval
3319 || builtin_interval_handlers[interval]) {
3320 return -1;
3321 }
3322
3324
3325 return 0;
3326}
3327
3329{
3330 if (ARRAY_LEN(builtin_interval_handlers) <= interval
3331 || !builtin_interval_handlers[interval]) {
3332 return -1;
3333 }
3334
3335 builtin_interval_handlers[interval] = NULL;
3336
3337 return 0;
3338
3339}
3340
3341/*!
3342 * \internal
3343 * \brief Bridge hook destructor.
3344 * \since 12.0.0
3345 *
3346 * \param vhook Object to destroy.
3347 */
3348static void bridge_hook_destroy(void *vhook)
3349{
3350 struct ast_bridge_hook *hook = vhook;
3351
3352 if (hook->destructor) {
3353 hook->destructor(hook->hook_pvt);
3354 }
3355}
3356
3357/*!
3358 * \internal
3359 * \brief Allocate and setup a generic bridge hook.
3360 * \since 12.0.0
3361 *
3362 * \param size How big an object to allocate.
3363 * \param callback Function to execute upon activation
3364 * \param hook_pvt Unique data
3365 * \param destructor Optional destructor callback for hook_pvt data
3366 * \param remove_flags Dictates what situations the hook should be removed.
3367 *
3368 * \return hook on success.
3369 * \retval NULL on error.
3370 */
3371static struct ast_bridge_hook *bridge_hook_generic(size_t size,
3373 void *hook_pvt,
3376{
3377 struct ast_bridge_hook *hook;
3378
3379 /* Allocate new hook and setup it's basic variables */
3381 if (hook) {
3382 hook->callback = callback;
3383 hook->destructor = destructor;
3384 hook->hook_pvt = hook_pvt;
3386 }
3387
3388 return hook;
3389}
3390
3392 const char *dtmf,
3394 void *hook_pvt,
3397{
3398 struct ast_bridge_hook_dtmf *hook;
3399 int res;
3400
3401 /* Allocate new hook and setup it's various variables */
3402 hook = (struct ast_bridge_hook_dtmf *) bridge_hook_generic(sizeof(*hook), callback,
3403 hook_pvt, destructor, remove_flags);
3404 if (!hook) {
3405 return -1;
3406 }
3408 ast_copy_string(hook->dtmf.code, dtmf, sizeof(hook->dtmf.code));
3409
3410 /* Once done we put it in the container. */
3411 res = ao2_link(features->dtmf_hooks, hook) ? 0 : -1;
3412 if (res) {
3413 /*
3414 * Could not link the hook into the container.
3415 *
3416 * Remove the hook_pvt destructor call from the hook since we
3417 * are returning failure to install the hook.
3418 */
3419 hook->generic.destructor = NULL;
3420 }
3421 ao2_ref(hook, -1);
3422
3423 return res;
3424}
3425
3426/*!
3427 * \internal
3428 * \brief Attach an other hook to a bridge features structure
3429 *
3430 * \param features Bridge features structure
3431 * \param callback Function to execute upon activation
3432 * \param hook_pvt Unique data
3433 * \param destructor Optional destructor callback for hook_pvt data
3434 * \param remove_flags Dictates what situations the hook should be removed.
3435 * \param type What type of hook is being attached.
3436 *
3437 * \retval 0 on success
3438 * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
3439 */
3440static int bridge_other_hook(struct ast_bridge_features *features,
3442 void *hook_pvt,
3444 enum ast_bridge_hook_remove_flags remove_flags,
3446{
3447 struct ast_bridge_hook *hook;
3448 int res;
3449
3450 /* Allocate new hook and setup it's various variables */
3451 hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor,
3452 remove_flags);
3453 if (!hook) {
3454 return -1;
3455 }
3456 hook->type = type;
3457
3458 /* Once done we put it in the container. */
3459 res = ao2_link(features->other_hooks, hook) ? 0 : -1;
3460 if (res) {
3461 /*
3462 * Could not link the hook into the container.
3463 *
3464 * Remove the hook_pvt destructor call from the hook since we
3465 * are returning failure to install the hook.
3466 */
3467 hook->destructor = NULL;
3468 }
3469 ao2_ref(hook, -1);
3470
3471 return res;
3472}
3473
3483
3493
3503
3515
3527
3530 unsigned int interval,
3532 void *hook_pvt,
3535{
3536 struct ast_bridge_hook_timer *hook;
3537 int res;
3538
3539 if (!features ||!interval || !callback) {
3540 return -1;
3541 }
3542
3543 /* Allocate new hook and setup it's various variables */
3544 hook = (struct ast_bridge_hook_timer *) bridge_hook_generic(sizeof(*hook), callback,
3545 hook_pvt, destructor, remove_flags);
3546 if (!hook) {
3547 return -1;
3548 }
3550 hook->timer.interval = interval;
3551 hook->timer.trip_time = ast_tvadd(ast_tvnow(), ast_samp2tv(interval, 1000));
3552 hook->timer.seqno = ast_atomic_fetchadd_int((int *) &features->interval_sequence, +1);
3553 hook->timer.flags = flags;
3554
3555 ast_debug(1, "Putting interval hook %p with interval %u in the heap on features %p\n",
3556 hook, hook->timer.interval, features);
3558 res = ast_heap_push(features->interval_hooks, hook);
3560 if (res) {
3561 /*
3562 * Could not push the hook into the heap
3563 *
3564 * Remove the hook_pvt destructor call from the hook since we
3565 * are returning failure to install the hook.
3566 */
3567 hook->generic.destructor = NULL;
3568 ao2_ref(hook, -1);
3569 }
3570
3571 return res ? -1 : 0;
3572}
3573
3575 enum ast_bridge_builtin_feature feature,
3576 const char *dtmf,
3577 void *config,
3579 enum ast_bridge_hook_remove_flags remove_flags)
3580{
3581 if (ARRAY_LEN(builtin_features_handlers) <= feature
3582 || !builtin_features_handlers[feature]) {
3583 return -1;
3584 }
3585
3586 /* If no alternate DTMF stream was provided use the default one */
3587 if (ast_strlen_zero(dtmf)) {
3588 dtmf = builtin_features_dtmf[feature];
3589 /* If no DTMF is still available (ie: it has been disabled) then error out now */
3590 if (ast_strlen_zero(dtmf)) {
3591 ast_debug(1, "Failed to enable built in feature %u on %p, no DTMF string is available for it.\n",
3592 feature, features);
3593 return -1;
3594 }
3595 }
3596
3597 /*
3598 * The rest is basically pretty easy. We create another hook
3599 * using the built in feature's DTMF callback. Easy as pie.
3600 */
3601 return ast_bridge_dtmf_hook(features, dtmf, builtin_features_handlers[feature],
3602 config, destructor, remove_flags);
3603}
3604
3606{
3607 memset(limits, 0, sizeof(*limits));
3608
3609 if (ast_string_field_init(limits, 256)) {
3610 return -1;
3611 }
3612
3613 return 0;
3614}
3615
3620
3623 enum ast_bridge_hook_remove_flags remove_flags)
3624{
3627
3629 return callback(features, limits, remove_flags);
3630 }
3631
3632 ast_log(LOG_ERROR, "Attempted to set limits without an AST_BRIDGE_BUILTIN_INTERVAL_LIMITS callback registered.\n");
3633 return -1;
3634}
3635
3636void ast_bridge_features_set_flag(struct ast_bridge_features *features, unsigned int flag)
3637{
3638 ast_set_flag(&features->feature_flags, flag);
3639 features->usable = 1;
3640}
3641
3642/*!
3643 * \internal
3644 * \brief ao2 object match hooks with appropriate remove_flags.
3645 * \since 12.0.0
3646 *
3647 * \param obj Feature hook object.
3648 * \param arg Removal flags
3649 * \param flags Not used
3650 *
3651 * \retval CMP_MATCH if hook's remove_flags match the removal flags set.
3652 * \retval 0 if not match.
3653 */
3654static int hook_remove_match(void *obj, void *arg, int flags)
3655{
3656 struct ast_bridge_hook *hook = obj;
3658
3659 if (ast_test_flag(&hook->remove_flags, *remove_flags)) {
3660 return CMP_MATCH;
3661 } else {
3662 return 0;
3663 }
3664}
3665
3666/*!
3667 * \internal
3668 * \brief Remove all hooks with appropriate remove_flags in the container.
3669 * \since 12.0.0
3670 *
3671 * \param hooks Hooks container to work on.
3672 * \param remove_flags Determinator for whether hook is removed
3673 */
3679
3680/*!
3681 * \internal
3682 * \brief Remove all hooks in the heap with appropriate remove_flags set.
3683 * \since 12.0.0
3684 *
3685 * \param hooks Hooks heap to work on.
3686 * \param remove_flags Determinator for whether hook is removed
3687 */
3689{
3690 struct ast_bridge_hook *hook;
3691 int changed;
3692
3693 ast_heap_wrlock(hooks);
3694 do {
3695 int idx;
3696
3697 changed = 0;
3698 for (idx = ast_heap_size(hooks); idx; --idx) {
3699 hook = ast_heap_peek(hooks, idx);
3701 ast_heap_remove(hooks, hook);
3702 ao2_ref(hook, -1);
3703 changed = 1;
3704 }
3705 }
3706 } while (changed);
3707 ast_heap_unlock(hooks);
3708}
3709
3716
3717static int interval_hook_time_cmp(void *a, void *b)
3718{
3719 struct ast_bridge_hook_timer *hook_a = a;
3720 struct ast_bridge_hook_timer *hook_b = b;
3721 int cmp;
3722
3723 cmp = ast_tvcmp(hook_b->timer.trip_time, hook_a->timer.trip_time);
3724 if (cmp) {
3725 return cmp;
3726 }
3727
3728 cmp = hook_b->timer.seqno - hook_a->timer.seqno;
3729 return cmp;
3730}
3731
3732/*!
3733 * \internal
3734 * \brief DTMF hook container sort comparison function.
3735 * \since 12.0.0
3736 *
3737 * \param obj_left pointer to the (user-defined part) of an object.
3738 * \param obj_right pointer to the (user-defined part) of an object.
3739 * \param flags flags from ao2_callback()
3740 * OBJ_POINTER - if set, 'obj_right', is an object.
3741 * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
3742 * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
3743 *
3744 * \retval <0 if obj_left < obj_right
3745 * \retval =0 if obj_left == obj_right
3746 * \retval >0 if obj_left > obj_right
3747 */
3748static int bridge_dtmf_hook_sort(const void *obj_left, const void *obj_right, int flags)
3749{
3750 const struct ast_bridge_hook_dtmf *hook_left = obj_left;
3751 const struct ast_bridge_hook_dtmf *hook_right = obj_right;
3752 const char *right_key = obj_right;
3753 int cmp;
3754
3755 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
3756 default:
3757 case OBJ_POINTER:
3758 right_key = hook_right->dtmf.code;
3759 /* Fall through */
3760 case OBJ_KEY:
3761 cmp = strcasecmp(hook_left->dtmf.code, right_key);
3762 break;
3763 case OBJ_PARTIAL_KEY:
3764 cmp = strncasecmp(hook_left->dtmf.code, right_key, strlen(right_key));
3765 break;
3766 }
3767 return cmp;
3768}
3769
3770/*! \brief Callback for merging hook ao2_containers */
3771static int merge_container_cb(void *obj, void *data, int flags)
3772{
3773 ao2_link(data, obj);
3774 return 0;
3775}
3776
3777/*! \brief Wrapper for interval hooks that calls into the wrapped hook */
3778static int interval_wrapper_cb(struct ast_bridge_channel *bridge_channel, void *obj)
3779{
3780 struct ast_bridge_hook_timer *hook = obj;
3781
3782 return hook->generic.callback(bridge_channel, hook->generic.hook_pvt);
3783}
3784
3785/*! \brief Destructor for the hook wrapper */
3786static void interval_wrapper_pvt_dtor(void *obj)
3787{
3788 ao2_cleanup(obj);
3789}
3790
3791/*! \brief Wrap the provided interval hook and add it to features */
3792static void wrap_hook(struct ast_bridge_features *features, struct ast_bridge_hook_timer *hook)
3793{
3794 /* Break out of the current wrapper if it exists to avoid multiple layers */
3795 if (hook->generic.callback == interval_wrapper_cb) {
3796 hook = hook->generic.hook_pvt;
3797 }
3798
3799 ast_bridge_interval_hook(features, hook->timer.flags, hook->timer.interval,
3801 hook->generic.remove_flags.flags);
3802}
3803
3805{
3806 struct ast_bridge_hook_timer *hook;
3807 int idx;
3808
3809 /* Merge hook containers */
3812
3813 /* Merge hook heaps */
3815 for (idx = 1; (hook = ast_heap_peek(from->interval_hooks, idx)); idx++) {
3816 wrap_hook(into, hook);
3817 }
3819
3820 /* Merge feature flags */
3821 into->feature_flags.flags |= from->feature_flags.flags;
3822 into->usable |= from->usable;
3823
3824 into->mute |= from->mute;
3825 into->dtmf_passthrough |= from->dtmf_passthrough;
3826}
3827
3828/* XXX ASTERISK-21271 make ast_bridge_features_init() static when make ast_bridge_join() requires features to be allocated. */
3830{
3831 /* Zero out the structure */
3832 memset(features, 0, sizeof(*features));
3833
3834 /* Initialize the DTMF hooks container */
3837 if (!features->dtmf_hooks) {
3838 return -1;
3839 }
3840
3841 /* Initialize the miscellaneous other hooks container */
3843 NULL);
3844 if (!features->other_hooks) {
3845 return -1;
3846 }
3847
3848 /* Initialize the interval hooks heap */
3850 offsetof(struct ast_bridge_hook_timer, timer.heap_index));
3851 if (!features->interval_hooks) {
3852 return -1;
3853 }
3854
3855 features->dtmf_passthrough = 1;
3856 features->text_messaging = 1;
3857
3858 return 0;
3859}
3860
3861/* XXX ASTERISK-21271 make ast_bridge_features_cleanup() static when make ast_bridge_join() requires features to be allocated. */
3863{
3864 struct ast_bridge_hook_timer *hook;
3865
3866 /* Destroy the interval hooks heap. */
3867 if (features->interval_hooks) {
3868 while ((hook = ast_heap_pop(features->interval_hooks))) {
3869 ao2_ref(hook, -1);
3870 }
3871 features->interval_hooks = ast_heap_destroy(features->interval_hooks);
3872 }
3873
3874 /* Destroy the miscellaneous other hooks container. */
3875 ao2_cleanup(features->other_hooks);
3876 features->other_hooks = NULL;
3877
3878 /* Destroy the DTMF hooks container. */
3879 ao2_cleanup(features->dtmf_hooks);
3880 features->dtmf_hooks = NULL;
3881}
3882
3884{
3885 if (!features) {
3886 return;
3887 }
3889 ast_free(features);
3890}
3891
3893{
3894 struct ast_bridge_features *features;
3895
3896 features = ast_malloc(sizeof(*features));
3897 if (features) {
3898 if (ast_bridge_features_init(features)) {
3900 features = NULL;
3901 }
3902 }
3903
3904 return features;
3905}
3906
3907void ast_bridge_set_mixing_interval(struct ast_bridge *bridge, unsigned int mixing_interval)
3908{
3909 ast_bridge_lock(bridge);
3910 bridge->softmix.internal_mixing_interval = mixing_interval;
3911 ast_bridge_unlock(bridge);
3912}
3913
3914void ast_bridge_set_binaural_active(struct ast_bridge *bridge, unsigned int binaural_active)
3915{
3916 ast_bridge_lock(bridge);
3917 bridge->softmix.binaural_active = binaural_active;
3918 ast_bridge_unlock(bridge);
3919}
3920
3921void ast_bridge_set_internal_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
3922{
3923 ast_bridge_lock(bridge);
3924 bridge->softmix.internal_sample_rate = sample_rate;
3925 ast_bridge_unlock(bridge);
3926}
3927
3928void ast_bridge_set_maximum_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
3929{
3930 ast_bridge_lock(bridge);
3931 bridge->softmix.maximum_sample_rate = sample_rate;
3932 ast_bridge_unlock(bridge);
3933}
3934
3957
3958void ast_bridge_set_single_src_video_mode(struct ast_bridge *bridge, struct ast_channel *video_src_chan)
3959{
3960 ast_bridge_lock(bridge);
3961 cleanup_video_mode(bridge);
3963 if (video_src_chan) {
3965 ast_verb(5, "Video source in bridge '%s' (%s) is now '%s' (%s)\n",
3966 bridge->name, bridge->uniqueid,
3967 ast_channel_name(video_src_chan),
3968 ast_channel_uniqueid(video_src_chan));
3969 ast_indicate(video_src_chan, AST_CONTROL_VIDUPDATE);
3970 }
3972 ast_bridge_unlock(bridge);
3973}
3974
3982
3984{
3985 ast_bridge_lock(bridge);
3986 cleanup_video_mode(bridge);
3988 ast_bridge_unlock(bridge);
3989}
3990
3991void ast_bridge_set_video_update_discard(struct ast_bridge *bridge, unsigned int video_update_discard)
3992{
3993 ast_bridge_lock(bridge);
3994 bridge->softmix.video_mode.video_update_discard = video_update_discard;
3995 ast_bridge_unlock(bridge);
3996}
3997
3998void ast_bridge_set_remb_send_interval(struct ast_bridge *bridge, unsigned int remb_send_interval)
3999{
4001
4002 ast_bridge_lock(bridge);
4003 bridge->softmix.video_mode.mode_data.sfu_data.remb_send_interval = remb_send_interval;
4004 ast_bridge_unlock(bridge);
4005}
4006
4015
4016void ast_bridge_set_remb_estimated_bitrate(struct ast_bridge *bridge, float estimated_bitrate)
4017{
4019
4020 ast_bridge_lock(bridge);
4021 bridge->softmix.video_mode.mode_data.sfu_data.estimated_bitrate = estimated_bitrate;
4022 ast_bridge_unlock(bridge);
4023}
4024
4025void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyframe)
4026{
4028
4029 /* If the channel doesn't support video, we don't care about it */
4031 return;
4032 }
4033
4034 ast_bridge_lock(bridge);
4036
4037 if (data->chan_vsrc == chan) {
4038 data->average_talking_energy = talker_energy;
4039 } else if ((data->average_talking_energy < talker_energy) && is_keyframe) {
4040 if (data->chan_old_vsrc) {
4042 }
4043 if (data->chan_vsrc) {
4044 data->chan_old_vsrc = data->chan_vsrc;
4046 }
4047 data->chan_vsrc = ast_channel_ref(chan);
4048 data->average_talking_energy = talker_energy;
4049 ast_verb(5, "Video source in bridge '%s' (%s) is now '%s' (%s)\n",
4050 bridge->name, bridge->uniqueid,
4055 } else if ((data->average_talking_energy < talker_energy) && !is_keyframe) {
4057 } else if (!data->chan_vsrc && is_keyframe) {
4058 data->chan_vsrc = ast_channel_ref(chan);
4059 data->average_talking_energy = talker_energy;
4060 ast_verb(5, "Video source in bridge '%s' (%s) is now '%s' (%s)\n",
4061 bridge->name, bridge->uniqueid,
4066 } else if (!data->chan_old_vsrc && is_keyframe) {
4067 data->chan_old_vsrc = ast_channel_ref(chan);
4069 }
4070 ast_bridge_unlock(bridge);
4071}
4072
4074{
4075 int res = 0;
4076
4077 ast_bridge_lock(bridge);
4078 switch (bridge->softmix.video_mode.mode) {
4080 break;
4083 res = 1;
4084 }
4085 break;
4088 res++;
4089 }
4091 res++;
4092 }
4094 break;
4095 }
4096 ast_bridge_unlock(bridge);
4097 return res;
4098}
4099
4100int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
4101{
4102 int res = 0;
4103
4104 ast_bridge_lock(bridge);
4105 switch (bridge->softmix.video_mode.mode) {
4107 break;
4110 res = 1;
4111 }
4112 break;
4115 res = 1;
4116 } else if (bridge->softmix.video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
4117 res = 2;
4118 }
4120 break;
4121 }
4122 ast_bridge_unlock(bridge);
4123 return res;
4124}
4125
4126void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
4127{
4128 ast_bridge_lock(bridge);
4129 switch (bridge->softmix.video_mode.mode) {
4131 break;
4136 }
4138 }
4139 break;
4144 }
4147 }
4151 }
4153 }
4155 break;
4156 }
4157 ast_bridge_unlock(bridge);
4158}
4159
4161{
4162 switch (video_mode) {
4164 return "talker";
4166 return "single";
4168 return "sfu";
4170 default:
4171 return "none";
4172 }
4173}
4174
4175void ast_bridge_set_send_sdp_label(struct ast_bridge *bridge, unsigned int send_sdp_label)
4176{
4177 ast_bridge_lock(bridge);
4178 bridge->softmix.send_sdp_label = send_sdp_label;
4179 ast_bridge_unlock(bridge);
4180}
4181
4182static int channel_hash(const void *obj, int flags)
4183{
4184 const struct ast_channel *chan = obj;
4185 const char *name = obj;
4186 int hash;
4187
4188 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
4189 default:
4190 case OBJ_POINTER:
4191 name = ast_channel_name(chan);
4192 /* Fall through */
4193 case OBJ_KEY:
4194 hash = ast_str_hash(name);
4195 break;
4196 case OBJ_PARTIAL_KEY:
4197 /* Should never happen in hash callback. */
4198 ast_assert(0);
4199 hash = 0;
4200 break;
4201 }
4202 return hash;
4203}
4204
4205static int channel_cmp(void *obj, void *arg, int flags)
4206{
4207 const struct ast_channel *left = obj;
4208 const struct ast_channel *right = arg;
4209 const char *right_name = arg;
4210 int cmp;
4211
4212 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
4213 default:
4214 case OBJ_POINTER:
4215 right_name = ast_channel_name(right);
4216 /* Fall through */
4217 case OBJ_KEY:
4218 cmp = strcmp(ast_channel_name(left), right_name);
4219 break;
4220 case OBJ_PARTIAL_KEY:
4221 cmp = strncmp(ast_channel_name(left), right_name, strlen(right_name));
4222 break;
4223 }
4224 return cmp ? 0 : CMP_MATCH;
4225}
4226
4228{
4229 struct ao2_container *channels;
4230 struct ast_bridge_channel *iter;
4231
4234 if (!channels) {
4235 return NULL;
4236 }
4237
4239 ao2_link(channels, iter->chan);
4240 }
4241
4242 return channels;
4243}
4244
4246{
4247 struct ao2_container *channels;
4248
4249 ast_bridge_lock(bridge);
4251 ast_bridge_unlock(bridge);
4252
4253 return channels;
4254}
4255
4257{
4258 struct ast_channel *peer = NULL;
4259 struct ast_bridge_channel *iter;
4260
4261 /* Asking for the peer channel only makes sense on a two-party bridge. */
4262 if (bridge->num_channels == 2
4265 int in_bridge = 0;
4266
4268 if (iter->chan != chan) {
4269 peer = iter->chan;
4270 } else {
4271 in_bridge = 1;
4272 }
4273 }
4274 if (in_bridge && peer) {
4275 ast_channel_ref(peer);
4276 } else {
4277 peer = NULL;
4278 }
4279 }
4280
4281 return peer;
4282}
4283
4285{
4286 struct ast_channel *peer;
4287
4289 peer = ast_bridge_peer_nolock(bridge, chan);
4291
4292 return peer;
4293}
4294
4295/*!
4296 * \internal
4297 * \brief Transfer an entire bridge to a specific destination.
4298 *
4299 * This creates a local channel to dial out and swaps the called local channel
4300 * with the transferer channel. By doing so, all participants in the bridge are
4301 * connected to the specified destination.
4302 *
4303 * While this means of transferring would work for both two-party and multi-party
4304 * bridges, this method is only used for multi-party bridges since this method would
4305 * be less efficient for two-party bridges.
4306 *
4307 * \param is_external Whether the transfer is externally initiated
4308 * \param transferer The channel performing a transfer
4309 * \param bridge The bridge where the transfer is being performed
4310 * \param exten The destination extension for the blind transfer
4311 * \param context The destination context for the blind transfer
4312 * \param transferee The party being transferred if there is only one
4313 * \param new_channel_cb Callback to call on channel that is created to
4314 * facilitate the blind transfer.
4315 * \param user_data_wrapper User-provided data needed in new_channel_cb
4316 * \param transfer_message The Stasis publication for this transfer.
4317 *
4318 * \return The success or failure of the operation
4319 */
4320static enum ast_transfer_result blind_transfer_bridge(int is_external,
4321 struct ast_channel *transferer, struct ast_bridge *bridge,
4322 const char *exten, const char *context, struct ast_channel *transferee,
4323 transfer_channel_cb new_channel_cb,
4324 struct transfer_channel_data *user_data_wrapper,
4325 struct ast_blind_transfer_message *transfer_message)
4326{
4327 struct ast_channel *local;
4328 char chan_name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
4329 int cause;
4330 struct ast_format_cap *caps;
4331
4332 ast_channel_lock(transferer);
4333 caps = ao2_bump(ast_channel_nativeformats(transferer));
4334 ast_channel_unlock(transferer);
4335
4336 snprintf(chan_name, sizeof(chan_name), "%s@%s", exten, context);
4337 local = ast_request("Local", caps, NULL, transferer,
4338 chan_name, &cause);
4339
4340 ao2_cleanup(caps);
4341
4342 if (!local) {
4344 }
4345
4346 ast_channel_lock_both(local, transferer);
4348
4350 if (!transfer_message->replace_channel) {
4351 ast_hangup(local);
4353 }
4354
4356 ast_channel_unlock(local);
4357 ast_channel_unlock(transferer);
4358
4359 if (new_channel_cb) {
4360 new_channel_cb(local, user_data_wrapper, AST_BRIDGE_TRANSFER_MULTI_PARTY);
4361 }
4362
4363 if (ast_call(local, chan_name, 0)) {
4364 ast_hangup(local);
4366 }
4367
4368 if (ast_bridge_impart(bridge, local, transferer, NULL,
4370 ast_hangup(local);
4372 }
4373
4375}
4376
4377/*!
4378 * \internal
4379 * \brief Get the transferee channel
4380 *
4381 * This is only applicable to cases where a transfer is occurring on a
4382 * two-party bridge. The channels container passed in is expected to only
4383 * contain two channels, the transferer and the transferee. The transferer
4384 * channel is passed in as a parameter to ensure we don't return it as
4385 * the transferee channel.
4386 *
4387 * \param channels A two-channel container containing the transferer and transferee
4388 * \param transferer The party that is transferring the call
4389 * \return The party that is being transferred
4390 */
4391static struct ast_channel *get_transferee(struct ao2_container *channels, struct ast_channel *transferer)
4392{
4393 struct ao2_iterator channel_iter;
4394 struct ast_channel *transferee;
4395
4396 for (channel_iter = ao2_iterator_init(channels, 0);
4397 (transferee = ao2_iterator_next(&channel_iter));
4398 ao2_cleanup(transferee)) {
4399 if (transferee != transferer) {
4400 break;
4401 }
4402 }
4403
4404 ao2_iterator_destroy(&channel_iter);
4405 return transferee;
4406}
4407
4408/*!
4409 * \brief Perform an attended transfer of a bridge
4410 *
4411 * This performs an attended transfer of an entire bridge to a target.
4412 * The target varies, depending on what bridges exist during the transfer
4413 * attempt.
4414 *
4415 * If two bridges exist, then a local channel is created to link the two
4416 * bridges together.
4417 *
4418 * If only one bridge exists, then a local channel is created with one end
4419 * placed into the existing bridge and the other end masquerading into
4420 * the unbridged channel.
4421 *
4422 * \param chan1 Transferer channel. Guaranteed to be bridged.
4423 * \param chan2 Other transferer channel. May or may not be bridged.
4424 * \param bridge1 Bridge that chan1 is in. Guaranteed to be non-NULL.
4425 * \param bridge2 Bridge that chan2 is in. If NULL, then chan2 is not bridged.
4426 * \param transfer_msg Data to publish for a stasis attended transfer message.
4427 * \retval AST_BRIDGE_TRANSFER_FAIL Internal error occurred
4428 * \retval AST_BRIDGE_TRANSFER_SUCCESS Successfully transferred the bridge
4429 */
4431 struct ast_channel *chan2, struct ast_bridge *bridge1, struct ast_bridge *bridge2,
4432 struct ast_attended_transfer_message *transfer_msg)
4433{
4434#define BRIDGE_LOCK_ONE_OR_BOTH(b1, b2) \
4435 do { \
4436 if (b2) { \
4437 ast_bridge_lock_both(b1, b2); \
4438 } else { \
4439 ast_bridge_lock(b1); \
4440 } \
4441 } while (0)
4442
4443 static const char *dest = "_attended@transfer/m";
4444 struct ast_channel *local_chan;
4445 int cause;
4446 int res;
4447 const char *app = NULL;
4448 struct ast_format_cap *caps;
4449
4450 ast_channel_lock(chan1);
4451 caps = ao2_bump(ast_channel_nativeformats(chan1));
4452 ast_channel_unlock(chan1);
4453
4454 local_chan = ast_request("Local", caps, NULL, chan1, dest, &cause);
4455
4456 ao2_cleanup(caps);
4457
4458 if (!local_chan) {
4460 }
4461
4462 ast_channel_lock_both(local_chan, chan1);
4465 ast_channel_unlock(local_chan);
4466 ast_channel_unlock(chan1);
4467
4468 if (bridge2) {
4469 res = ast_local_setup_bridge(local_chan, bridge2, chan2, NULL);
4470 } else {
4472 res = ast_local_setup_masquerade(local_chan, chan2);
4473 }
4474
4475 if (res) {
4476 ast_hangup(local_chan);
4478 }
4479
4480 /*
4481 * Since bridges need to be unlocked before entering ast_bridge_impart and
4482 * core_local may call into it then the bridges need to be unlocked here.
4483 */
4484 ast_bridge_unlock(bridge1);
4485 if (bridge2) {
4486 ast_bridge_unlock(bridge2);
4487 }
4488
4489 if (ast_call(local_chan, dest, 0)) {
4490 ast_hangup(local_chan);
4491 BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2);
4493 }
4494
4495 /* Get a ref for use later since this one is being stolen */
4496 ao2_ref(local_chan, +1);
4497 if (ast_bridge_impart(bridge1, local_chan, chan1, NULL,
4499 ast_hangup(local_chan);
4500 ao2_cleanup(local_chan);
4501 BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2);
4503 }
4504 BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2);
4505
4506 if (bridge2) {
4507 void *tech;
4508 struct ast_channel *locals[2];
4509
4510 /* Have to lock everything just in case a hangup comes in early */
4511 ast_local_lock_all(local_chan, &tech, &locals[0], &locals[1]);
4512 if (!locals[0] || !locals[1]) {
4513 ast_log(LOG_ERROR, "Transfer failed probably due to an early hangup - "
4514 "missing other half of '%s'\n", ast_channel_name(local_chan));
4516 ao2_cleanup(local_chan);
4518 }
4519
4520 /* Make sure the peer is properly set */
4521 if (local_chan != locals[0]) {
4522 SWAP(locals[0], locals[1]);
4523 }
4524
4527 } else {
4528 ast_attended_transfer_message_add_app(transfer_msg, app, local_chan);
4529 }
4530
4531 ao2_cleanup(local_chan);
4533}
4534
4535static enum ast_transfer_result try_parking(struct ast_channel *transferer,
4536 const char *context, const char *exten, transfer_channel_cb new_channel_cb,
4537 struct transfer_channel_data *user_data_wrapper)
4538{
4539 RAII_VAR(struct ast_bridge_channel *, transferer_bridge_channel, NULL, ao2_cleanup);
4540
4543 }
4544
4545 ast_channel_lock(transferer);
4546 transferer_bridge_channel = ast_channel_get_bridge_channel(transferer);
4547 ast_channel_unlock(transferer);
4548
4549 if (!transferer_bridge_channel) {
4551 }
4552
4553 if (ast_parking_blind_transfer_park(transferer_bridge_channel,
4554 context, exten, new_channel_cb, user_data_wrapper)) {
4556 }
4557
4559}
4560
4561void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int attended)
4562{
4563 char *writevar;
4564 char *erasevar;
4565
4566 if (attended) {
4567 writevar = ATTENDEDTRANSFER;
4568 erasevar = BLINDTRANSFER;
4569 } else {
4570 writevar = BLINDTRANSFER;
4571 erasevar = ATTENDEDTRANSFER;
4572 }
4573
4574 pbx_builtin_setvar_helper(chan, writevar, value);
4575 pbx_builtin_setvar_helper(chan, erasevar, NULL);
4576}
4577
4578/*!
4579 * \internal
4580 * \brief Set the transfer variable as appropriate on channels involved in the transfer
4581 *
4582 * The transferer channel will have its variable set the same as its BRIDGEPEER
4583 * variable. This will account for all channels that it is bridged to. The other channels
4584 * involved in the transfer will have their variable set to the transferer
4585 * channel's name.
4586 *
4587 * \param transferer The channel performing the transfer
4588 * \param channels The channels belonging to the bridge
4589 * \param is_attended false set BLINDTRANSFER and unset ATTENDEDTRANSFER
4590 * true set ATTENDEDTRANSFER and unset BLINDTRANSFER
4591 */
4592static void set_transfer_variables_all(struct ast_channel *transferer, struct ao2_container *channels, int is_attended)
4593{
4594 struct ao2_iterator iter;
4595 struct ast_channel *chan;
4596 const char *transferer_name;
4597 const char *transferer_bridgepeer;
4598
4599 ast_channel_lock(transferer);
4600 transferer_name = ast_strdupa(ast_channel_name(transferer));
4601 transferer_bridgepeer = ast_strdupa(S_OR(pbx_builtin_getvar_helper(transferer, "BRIDGEPEER"), ""));
4602 ast_channel_unlock(transferer);
4603
4604 for (iter = ao2_iterator_init(channels, 0);
4605 (chan = ao2_iterator_next(&iter));
4606 ao2_cleanup(chan)) {
4607 if (chan == transferer) {
4608 ast_bridge_set_transfer_variables(chan, transferer_bridgepeer, is_attended);
4609 } else {
4610 ast_bridge_set_transfer_variables(chan, transferer_name, is_attended);
4611 }
4612 }
4613
4614 ao2_iterator_destroy(&iter);
4615}
4616
4618{
4619 struct ast_bridge *bridge;
4620
4621 ast_channel_lock(chan);
4622 bridge = ast_channel_get_bridge(chan);
4623 ast_channel_unlock(chan);
4624
4625 if (bridge && ast_test_flag(&bridge->feature_flags,
4627 ao2_ref(bridge, -1);
4628 bridge = NULL;
4629 }
4630
4631 return bridge;
4632}
4633
4635 struct ast_channel *transferer, const char *exten, const char *context,
4636 transfer_channel_cb new_channel_cb, void *user_data)
4637{
4638 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
4639 RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
4641 RAII_VAR(struct ast_channel *, transferee, NULL, ast_channel_cleanup);
4642 RAII_VAR(struct transfer_channel_data *, user_data_wrapper, NULL, ao2_cleanup);
4643 RAII_VAR(struct ast_blind_transfer_message *, transfer_message, NULL, ao2_cleanup);
4644 int do_bridge_transfer;
4645 int transfer_prohibited;
4646 enum ast_transfer_result transfer_result;
4647
4648 transfer_message = ast_blind_transfer_message_create(is_external, transferer, exten, context);
4649 if (!transfer_message) {
4650 /* Out of memory. Not even possible to publish a Stasis message about the
4651 * failure
4652 */
4653 ast_log(LOG_ERROR, "Unable to allocate memory for blind transfer publication from %s\n",
4654 ast_channel_name(transferer));
4656 }
4657
4658 bridge = ast_bridge_transfer_acquire_bridge(transferer);
4659 if (!bridge) {
4660 transfer_result = AST_BRIDGE_TRANSFER_INVALID;
4661 goto publish;
4662 }
4663
4664 ast_bridge_lock(bridge);
4665 transfer_message->bridge = ast_bridge_snapshot_create(bridge);
4666 ast_bridge_unlock(bridge);
4667 if (!transfer_message->bridge) {
4668 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4669 goto publish;
4670 }
4671
4672 transferee = ast_bridge_peer(bridge, transferer);
4673 if (transferee) {
4674 transfer_message->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee));
4675 if (!transfer_message->transferee) {
4676 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4677 goto publish;
4678 }
4679 }
4680
4681 ast_channel_lock(transferer);
4682 bridge_channel = ast_channel_get_bridge_channel(transferer);
4683 ast_channel_unlock(transferer);
4684 if (!bridge_channel) {
4685 transfer_result = AST_BRIDGE_TRANSFER_INVALID;
4686 goto publish;
4687 }
4688
4689 user_data_wrapper = ao2_alloc(sizeof(*user_data_wrapper), NULL);
4690 if (!user_data_wrapper) {
4691 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4692 goto publish;
4693 }
4694
4695 user_data_wrapper->data = user_data;
4696
4697 /* Take off hold if they are on hold. */
4698 ast_bridge_channel_write_unhold(bridge_channel);
4699
4700 transfer_result = try_parking(transferer, context, exten, new_channel_cb, user_data_wrapper);
4701 if (transfer_result == AST_BRIDGE_TRANSFER_SUCCESS) {
4702 goto publish;
4703 }
4704
4705 /* Since parking didn't take control of the user_data_wrapper, we are just going to raise the completed flag now. */
4706 user_data_wrapper->completed = 1;
4707
4708 {
4710
4712 if (!channels) {
4713 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4714 goto publish;
4715 }
4716 if (ao2_container_count(channels) <= 1) {
4717 transfer_result = AST_BRIDGE_TRANSFER_INVALID;
4718 goto publish;
4719 }
4720 transfer_prohibited = ast_test_flag(&bridge->feature_flags,
4722 do_bridge_transfer = ast_test_flag(&bridge->feature_flags,
4725 }
4726
4727 if (transfer_prohibited) {
4728 transfer_result = AST_BRIDGE_TRANSFER_NOT_PERMITTED;
4729 goto publish;
4730 }
4731
4732 set_transfer_variables_all(transferer, channels, 0);
4733
4734 if (do_bridge_transfer) {
4735 transfer_result = blind_transfer_bridge(is_external, transferer, bridge,
4736 exten, context, transferee, new_channel_cb, user_data_wrapper, transfer_message);
4737 goto publish;
4738 }
4739
4740 /* Reaching this portion means that we're dealing with a two-party bridge */
4741
4742 if (!transferee) {
4743 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4744 goto publish;
4745 }
4746
4747 if (bridge_channel_internal_queue_blind_transfer(transferee, exten, context,
4748 new_channel_cb, user_data_wrapper)) {
4749 transfer_result = AST_BRIDGE_TRANSFER_FAIL;
4750 goto publish;
4751 }
4752
4753 ast_bridge_remove(bridge, transferer);
4754 transfer_result = AST_BRIDGE_TRANSFER_SUCCESS;
4755
4756publish:
4757 transfer_message->result = transfer_result;
4758 ast_bridge_publish_blind_transfer(transfer_message);
4759 return transfer_result;
4760}
4761
4762/*!
4763 * \internal
4764 * \brief Performs an attended transfer by moving a channel from one bridge to another
4765 *
4766 * The channel that is bridged to the source_channel is moved into the dest_bridge from
4767 * the source_bridge_channel's bridge. The swap_channel is swapped out of the dest_bridge and placed in
4768 * the source_bridge_channel's bridge.
4769 *
4770 * \note dest_bridge and source_bridge_channel's bridge MUST be locked before calling this function.
4771 *
4772 * \param dest_bridge The final bridge for the attended transfer
4773 * \param source_bridge_channel Channel who is bridged to the channel that will move
4774 * \param swap_channel Channel to be swapped out of the dest_bridge
4775 * \return The success or failure of the swap attempt
4776 */
4778 struct ast_bridge_channel *source_bridge_channel, struct ast_channel *swap_channel)
4779{
4780 struct ast_bridge_channel *bridged_to_source;
4781
4782 bridged_to_source = ast_bridge_channel_peer(source_bridge_channel);
4783 if (bridged_to_source
4784 && bridged_to_source->state == BRIDGE_CHANNEL_STATE_WAIT
4785 && !ast_test_flag(&bridged_to_source->features->feature_flags,
4787 bridged_to_source->swap = swap_channel;
4788 if (bridge_do_move(dest_bridge, bridged_to_source, 1, 0)) {
4790 }
4791 /* Must kick the source channel out of its bridge. */
4792 ast_bridge_channel_leave_bridge(source_bridge_channel,
4795 } else {
4797 }
4798}
4799
4800/*!
4801 * \internal
4802 * \brief Function that performs an attended transfer when both transferer channels are bridged
4803 *
4804 * The method by which the transfer is performed is dependent on whether the bridges allow for
4805 * optimization to occur between them. If no optimization is permitted, then an unreal channel
4806 * is placed as a link between the two bridges. If optimization is permitted, then that means
4807 * we are free to perform move or merge operations in order to perform the transfer.
4808 *
4809 * \note to_transferee_bridge and to_target_bridge MUST be locked before calling this function
4810 *
4811 * \param to_transferee The channel that is bridged to the transferee
4812 * \param to_transferee_bridge_channel to_transferee's bridge_channel
4813 * \param to_transfer_target The channel that is bridged to the transfer target
4814 * \param to_target_bridge_channel to_transfer_target's bridge_channel
4815 * \param to_transferee_bridge The bridge between to_transferee and the transferee
4816 * \param to_target_bridge The bridge between to_transfer_target and the transfer_target
4817 * \param transfer_msg Data to publish for a stasis attended transfer message
4818 * \return The success or failure of the attended transfer
4819 */
4821 struct ast_bridge_channel *to_transferee_bridge_channel,
4822 struct ast_channel *to_transfer_target,
4823 struct ast_bridge_channel *to_target_bridge_channel,
4824 struct ast_bridge *to_transferee_bridge, struct ast_bridge *to_target_bridge,
4825 struct ast_attended_transfer_message *transfer_msg)
4826{
4827 struct ast_bridge_channel *kick_me[] = {
4828 to_transferee_bridge_channel,
4829 to_target_bridge_channel,
4830 };
4831 enum ast_transfer_result res;
4832 struct ast_bridge *final_bridge = NULL;
4834
4835 channels = ast_bridge_peers_nolock(to_transferee_bridge);
4836
4837 if (!channels) {
4839 goto end;
4840 }
4841
4842 set_transfer_variables_all(to_transferee, channels, 1);
4843
4844 switch (ast_bridges_allow_optimization(to_transferee_bridge, to_target_bridge)) {
4846 final_bridge = to_transferee_bridge;
4847 res = bridge_swap_attended_transfer(to_transferee_bridge, to_target_bridge_channel, to_transferee);
4848 goto end;
4850 final_bridge = to_target_bridge;
4851 res = bridge_swap_attended_transfer(to_target_bridge, to_transferee_bridge_channel, to_transfer_target);
4852 goto end;
4854 final_bridge = to_transferee_bridge;
4855 bridge_do_merge(to_transferee_bridge, to_target_bridge, kick_me, ARRAY_LEN(kick_me), 0);
4857 goto end;
4859 final_bridge = to_target_bridge;
4860 bridge_do_merge(to_target_bridge, to_transferee_bridge, kick_me, ARRAY_LEN(kick_me), 0);
4862 goto end;
4864 default:
4865 /* Just because optimization wasn't doable doesn't necessarily mean
4866 * that we can actually perform the transfer. Some reasons for non-optimization
4867 * indicate bridge invalidity, so let's check those before proceeding.
4868 */
4869 if (to_transferee_bridge->inhibit_merge || to_transferee_bridge->dissolved ||
4870 to_target_bridge->inhibit_merge || to_target_bridge->dissolved) {
4872 }
4873
4874 return attended_transfer_bridge(to_transferee, to_transfer_target,
4875 to_transferee_bridge, to_target_bridge, transfer_msg);
4876 }
4877
4878end:
4879 if (res == AST_BRIDGE_TRANSFER_SUCCESS) {
4880 ast_attended_transfer_message_add_merge(transfer_msg, final_bridge);
4881 }
4882
4883 return res;
4884}
4885
4887 struct ast_channel *to_transfer_target)
4888{
4889 RAII_VAR(struct ast_bridge *, to_transferee_bridge, NULL, ao2_cleanup);
4890 RAII_VAR(struct ast_bridge *, to_target_bridge, NULL, ao2_cleanup);
4891 RAII_VAR(struct ast_bridge_channel *, to_transferee_bridge_channel, NULL, ao2_cleanup);
4892 RAII_VAR(struct ast_bridge_channel *, to_target_bridge_channel, NULL, ao2_cleanup);
4894 RAII_VAR(struct ast_channel *, transferee, NULL, ao2_cleanup);
4895 RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
4896 struct ast_bridge *the_bridge = NULL;
4897 struct ast_channel *chan_bridged;
4898 struct ast_channel *chan_unbridged;
4899 int transfer_prohibited;
4900 int do_bridge_transfer;
4901 enum ast_transfer_result res;
4902 const char *app = NULL;
4903 int hangup_target = 0;
4904
4905 to_transferee_bridge = ast_bridge_transfer_acquire_bridge(to_transferee);
4906 to_target_bridge = ast_bridge_transfer_acquire_bridge(to_transfer_target);
4907
4908 transfer_msg = ast_attended_transfer_message_create(1, to_transferee, to_transferee_bridge,
4909 to_transfer_target, to_target_bridge, NULL, NULL);
4910 if (!transfer_msg) {
4911 ast_log(LOG_ERROR, "Unable to create Stasis publication for attended transfer from %s\n",
4912 ast_channel_name(to_transferee));
4914 }
4915
4916 /* They can't both be unbridged, you silly goose! */
4917 if (!to_transferee_bridge && !to_target_bridge) {
4919 goto end;
4920 }
4921
4922 ast_channel_lock(to_transferee);
4923 to_transferee_bridge_channel = ast_channel_get_bridge_channel(to_transferee);
4924 ast_channel_unlock(to_transferee);
4925
4926 ast_channel_lock(to_transfer_target);
4927 to_target_bridge_channel = ast_channel_get_bridge_channel(to_transfer_target);
4928 ast_channel_unlock(to_transfer_target);
4929
4930 if (to_transferee_bridge_channel) {
4931 /* Take off hold if they are on hold. */
4932 if (ast_bridge_channel_write_unhold(to_transferee_bridge_channel)) {
4933 ast_log(LOG_ERROR, "Transferee channel disappeared during transfer!\n");
4935 goto end;
4936 }
4937 }
4938
4939 if (to_target_bridge_channel) {
4940 const char *target_complete_sound;
4941
4942 /* Take off hold if they are on hold. */
4943 if (ast_bridge_channel_write_unhold(to_target_bridge_channel)) {
4944 ast_log(LOG_ERROR, "Target channel disappeared during transfer!\n");
4946 goto end;
4947 }
4948
4949 /* Is there a courtesy sound to play to the target? */
4950 ast_channel_lock(to_transfer_target);
4951 target_complete_sound = pbx_builtin_getvar_helper(to_transfer_target,
4952 "ATTENDED_TRANSFER_COMPLETE_SOUND");
4953 if (!ast_strlen_zero(target_complete_sound)) {
4954 target_complete_sound = ast_strdupa(target_complete_sound);
4955 } else {
4956 target_complete_sound = NULL;
4957 }
4958 ast_channel_unlock(to_transfer_target);
4959 if (!target_complete_sound) {
4960 ast_channel_lock(to_transferee);
4961 target_complete_sound = pbx_builtin_getvar_helper(to_transferee,
4962 "ATTENDED_TRANSFER_COMPLETE_SOUND");
4963 if (!ast_strlen_zero(target_complete_sound)) {
4964 target_complete_sound = ast_strdupa(target_complete_sound);
4965 } else {
4966 target_complete_sound = NULL;
4967 }
4968 ast_channel_unlock(to_transferee);
4969 }
4970 if (target_complete_sound) {
4971 ast_bridge_channel_write_playfile(to_target_bridge_channel, NULL,
4972 target_complete_sound, NULL);
4973 }
4974 }
4975
4976 /* Let's get the easy one out of the way first */
4977 if (to_transferee_bridge && to_target_bridge) {
4978
4979 if (!to_transferee_bridge_channel || !to_target_bridge_channel) {
4981 goto end;
4982 }
4983
4984 ast_bridge_lock_both(to_transferee_bridge, to_target_bridge);
4985 res = two_bridge_attended_transfer(to_transferee, to_transferee_bridge_channel,
4986 to_transfer_target, to_target_bridge_channel,
4987 to_transferee_bridge, to_target_bridge, transfer_msg);
4988 ast_bridge_unlock(to_transferee_bridge);
4989 ast_bridge_unlock(to_target_bridge);
4990
4991 hangup_target = 1;
4992 goto end;
4993 }
4994
4995 the_bridge = to_transferee_bridge ?: to_target_bridge;
4996 chan_bridged = to_transferee_bridge ? to_transferee : to_transfer_target;
4997 chan_unbridged = to_transferee_bridge ? to_transfer_target : to_transferee;
4998
4999 /*
5000 * Race condition makes it possible for app to be NULL, so get the app prior to
5001 * transferring with a fallback of "unknown".
5002 */
5003 app = ast_strdupa(ast_channel_appl(chan_unbridged) ?: "unknown");
5004
5005 {
5006 int chan_count;
5008
5009 channels = ast_bridge_peers_nolock(the_bridge);
5010 if (!channels) {
5012 goto end;
5013 }
5014 chan_count = ao2_container_count(channels);
5015 if (chan_count <= 1) {
5017 goto end;
5018 }
5019 transfer_prohibited = ast_test_flag(&the_bridge->feature_flags,
5021 do_bridge_transfer = ast_test_flag(&the_bridge->feature_flags,
5023 chan_count > 2;
5024 }
5025
5026 if (transfer_prohibited) {
5028 goto end;
5029 }
5030
5031 set_transfer_variables_all(to_transferee, channels, 1);
5032
5033 if (do_bridge_transfer) {
5034 /*
5035 * Hang up the target if it was bridged. Note, if it is not bridged
5036 * it is hung up during the masquerade.
5037 */
5038 hangup_target = chan_bridged == to_transfer_target;
5039 ast_bridge_lock(the_bridge);
5040 res = attended_transfer_bridge(chan_bridged, chan_unbridged, the_bridge, NULL, transfer_msg);
5041 ast_bridge_unlock(the_bridge);
5042 goto end;
5043 }
5044
5045 transferee = get_transferee(channels, chan_bridged);
5046 if (!transferee) {
5048 goto end;
5049 }
5050
5051 if (bridge_channel_internal_queue_attended_transfer(transferee, chan_unbridged)) {
5053 goto end;
5054 }
5055
5056 ast_bridge_remove(the_bridge, chan_bridged);
5057
5060
5061end:
5062 if ((res == AST_BRIDGE_TRANSFER_SUCCESS && hangup_target) || res == AST_BRIDGE_TRANSFER_FAIL) {
5063 ast_softhangup(to_transfer_target, AST_SOFTHANGUP_DEV);
5064 }
5065
5066 transfer_msg->result = res;
5068 return res;
5069}
5070
5071/*!
5072 * \internal
5073 * \brief Service the bridge manager request.
5074 * \since 12.0.0
5075 *
5076 * \param bridge requesting service.
5077 */
5079{
5081 if (bridge->callid) {
5083 }
5084
5085 /* Do any pending bridge actions. */
5088}
5089
5090/*!
5091 * \internal
5092 * \brief Bridge manager service thread.
5093 * \since 12.0.0
5094 */
5095static void *bridge_manager_thread(void *data)
5096{
5097 struct bridge_manager_controller *manager = data;
5099
5100 ao2_lock(manager);
5101 while (!manager->stop) {
5103 if (!request) {
5104 ast_cond_wait(&manager->cond, ao2_object_get_lockaddr(manager));
5105 continue;
5106 }
5107 ao2_unlock(manager);
5108
5109 /* Service the bridge. */
5111 ao2_ref(request->bridge, -1);
5113
5114 ao2_lock(manager);
5115 }
5116 ao2_unlock(manager);
5117
5118 return NULL;
5119}
5120
5121/*!
5122 * \internal
5123 * \brief Destroy the bridge manager controller.
5124 * \since 12.0.0
5125 *
5126 * \param obj Bridge manager to destroy.
5127 */
5128static void bridge_manager_destroy(void *obj)
5129{
5130 struct bridge_manager_controller *manager = obj;
5132
5133 if (manager->thread != AST_PTHREADT_NULL) {
5134 /* Stop the manager thread. */
5135 ao2_lock(manager);
5136 manager->stop = 1;
5137 ast_cond_signal(&manager->cond);
5138 ao2_unlock(manager);
5139 ast_debug(1, "Waiting for bridge manager thread to die.\n");
5140 pthread_join(manager->thread, NULL);
5141 }
5142
5143 /* Destroy the service request queue. */
5144 while ((request = AST_LIST_REMOVE_HEAD(&manager->service_requests, node))) {
5145 ao2_ref(request->bridge, -1);
5147 }
5148
5149 ast_cond_destroy(&manager->cond);
5150}
5151
5152/*!
5153 * \internal
5154 * \brief Create the bridge manager controller.
5155 * \since 12.0.0
5156 *
5157 * \return manager on success.
5158 * \retval NULL on error.
5159 */
5161{
5162 struct bridge_manager_controller *manager;
5163
5164 manager = ao2_alloc(sizeof(*manager), bridge_manager_destroy);
5165 if (!manager) {
5166 /* Well. This isn't good. */
5167 return NULL;
5168 }
5169 ast_cond_init(&manager->cond, NULL);
5171
5172 /* Create the bridge manager thread. */
5173 if (ast_pthread_create(&manager->thread, NULL, bridge_manager_thread, manager)) {
5174 /* Well. This isn't good either. */
5175 manager->thread = AST_PTHREADT_NULL;
5176 ao2_ref(manager, -1);
5177 manager = NULL;
5178 }
5179
5180 return manager;
5181}
5182
5183/*!
5184 * \internal
5185 * \brief Bridge ao2 container sort function.
5186 * \since 12.0.0
5187 *
5188 * \param obj_left pointer to the (user-defined part) of an object.
5189 * \param obj_right pointer to the (user-defined part) of an object.
5190 * \param flags flags from ao2_callback()
5191 * OBJ_POINTER - if set, 'obj_right', is an object.
5192 * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
5193 * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
5194 *
5195 * \retval <0 if obj_left < obj_right
5196 * \retval =0 if obj_left == obj_right
5197 * \retval >0 if obj_left > obj_right
5198 */
5199static int bridge_sort_cmp(const void *obj_left, const void *obj_right, int flags)
5200{
5201 const struct ast_bridge *bridge_left = obj_left;
5202 const struct ast_bridge *bridge_right = obj_right;
5203 const char *right_key = obj_right;
5204 int cmp;
5205
5206 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
5207 default:
5208 case OBJ_POINTER:
5209 right_key = bridge_right->uniqueid;
5210 /* Fall through */
5211 case OBJ_KEY:
5212 cmp = strcmp(bridge_left->uniqueid, right_key);
5213 break;
5214 case OBJ_PARTIAL_KEY:
5215 cmp = strncmp(bridge_left->uniqueid, right_key, strlen(right_key));
5216 break;
5217 }
5218 return cmp;
5219}
5220
5221struct ast_bridge *ast_bridge_find_by_id(const char *bridge_id)
5222{
5223 return ao2_find(bridges, bridge_id, OBJ_SEARCH_KEY);
5224}
5225
5226static int complete_bridge_live_search(void *obj, void *arg, int flags)
5227{
5228 struct ast_bridge *bridge = obj;
5229
5231 return CMP_STOP;
5232 }
5233
5234 return 0;
5235}
5236
5237static char *complete_bridge_live(const char *word)
5238{
5241
5242 return NULL;
5243}
5244
5245static char *handle_bridge_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5246{
5247#define FORMAT_HDR "%-36s %-36s %5s %-15s %-15s %s\n"
5248#define FORMAT_ROW "%-36s %-36s %5u %-15s %-15s %s\n"
5249
5250 struct ao2_iterator iter;
5251 struct ast_bridge *bridge;
5252
5253 switch (cmd) {
5254 case CLI_INIT:
5255 e->command = "bridge show all";
5256 e->usage =
5257 "Usage: bridge show all\n"
5258 " List all bridges\n";
5259 return NULL;
5260 case CLI_GENERATE:
5261 return NULL;
5262 }
5263
5264 ast_cli(a->fd, FORMAT_HDR, "Bridge-ID", "Name", "Chans", "Type", "Technology", "Duration");
5265
5266 iter = ao2_iterator_init(bridges, 0);
5267 for (; (bridge = ao2_iterator_next(&iter)); ao2_ref(bridge, -1)) {
5268 struct ast_bridge_snapshot *snapshot = ast_bridge_get_snapshot(bridge);
5269 char print_time[32];
5270
5271 if (snapshot) {
5272 ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, sizeof(print_time));
5273 ast_cli(a->fd, FORMAT_ROW,
5274 bridge->uniqueid,
5275 S_OR(bridge->name, "<unknown>"),
5276 snapshot->num_channels,
5277 S_OR(snapshot->subclass, "<unknown>"),
5278 S_OR(snapshot->technology, "<unknown>"),
5279 print_time);
5280 ao2_ref(snapshot, -1);
5281 }
5282 }
5283 ao2_iterator_destroy(&iter);
5284
5285 return CLI_SUCCESS;
5286
5287#undef FORMAT_HDR
5288#undef FORMAT_ROW
5289}
5290
5291/*! \brief Internal callback function for sending channels in a bridge to the CLI */
5292static int bridge_show_specific_print_channel(void *obj, void *arg, int flags)
5293{
5294 const char *uniqueid = obj;
5295 struct ast_cli_args *a = arg;
5296 struct ast_channel_snapshot *snapshot;
5297
5298 snapshot = ast_channel_snapshot_get_latest(uniqueid);
5299 if (!snapshot) {
5300 return 0;
5301 }
5302
5303 ast_cli(a->fd, "Channel: %s\n", snapshot->base->name);
5304 ao2_ref(snapshot, -1);
5305
5306 return 0;
5307}
5308
5309static char *handle_bridge_show_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5310{
5311 struct ast_bridge_snapshot *snapshot;
5312 char print_time[32];
5313
5314 switch (cmd) {
5315 case CLI_INIT:
5316 e->command = "bridge show";
5317 e->usage =
5318 "Usage: bridge show <bridge-id>\n"
5319 " Show information about the <bridge-id> bridge\n";
5320 return NULL;
5321 case CLI_GENERATE:
5322 if (a->pos == 2) {
5323 return complete_bridge_live(a->word);
5324 }
5325 return NULL;
5326 }
5327
5328 if (a->argc != 3) {
5329 return CLI_SHOWUSAGE;
5330 }
5331
5332 snapshot = ast_bridge_get_snapshot_by_uniqueid(a->argv[2]);
5333 if (!snapshot) {
5334 ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
5335 return CLI_SUCCESS;
5336 }
5337
5338 ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, sizeof(print_time));
5339
5340 ast_cli(a->fd, "Id: %s\n", snapshot->uniqueid);
5341 ast_cli(a->fd, "Type: %s\n", S_OR(snapshot->subclass, "<unknown>"));
5342 ast_cli(a->fd, "Technology: %s\n", S_OR(snapshot->technology, "<unknown>"));
5343 ast_cli(a->fd, "Subclass: %s\n", snapshot->subclass);
5344 ast_cli(a->fd, "Creator: %s\n", snapshot->creator);
5345 ast_cli(a->fd, "Name: %s\n", snapshot->name);
5346 ast_cli(a->fd, "Video-Mode: %s\n", ast_bridge_video_mode_to_string(snapshot->video_mode));
5347 ast_cli(a->fd, "Video-Source-Id: %s\n", snapshot->video_source_id);
5348 ast_cli(a->fd, "Num-Channels: %u\n", snapshot->num_channels);
5349 ast_cli(a->fd, "Num-Active: %u\n", snapshot->num_active);
5350 ast_cli(a->fd, "Duration: %s\n", print_time);
5352 ao2_ref(snapshot, -1);
5353
5354 return CLI_SUCCESS;
5355}
5356
5357#ifdef AST_DEVMODE
5358static char *handle_bridge_destroy_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5359{
5360 struct ast_bridge *bridge;
5361
5362 switch (cmd) {
5363 case CLI_INIT:
5364 e->command = "bridge destroy";
5365 e->usage =
5366 "Usage: bridge destroy <bridge-id>\n"
5367 " Destroy the <bridge-id> bridge\n";
5368 return NULL;
5369 case CLI_GENERATE:
5370 if (a->pos == 2) {
5371 return complete_bridge_live(a->word);
5372 }
5373 return NULL;
5374 }
5375
5376 if (a->argc != 3) {
5377 return CLI_SHOWUSAGE;
5378 }
5379
5380 bridge = ast_bridge_find_by_id(a->argv[2]);
5381 if (!bridge) {
5382 ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
5383 return CLI_SUCCESS;
5384 }
5385
5386 ast_cli(a->fd, "Destroying bridge '%s'\n", a->argv[2]);
5387 ast_bridge_destroy(bridge, 0);
5388
5389 return CLI_SUCCESS;
5390}
5391#endif
5392
5393static char *complete_bridge_participant(const char *bridge_name, const char *word)
5394{
5395 struct ast_bridge *bridge;
5396 struct ast_bridge_channel *bridge_channel;
5397 int wordlen;
5398
5399 bridge = ast_bridge_find_by_id(bridge_name);
5400 if (!bridge) {
5401 return NULL;
5402 }
5403
5404 wordlen = strlen(word);
5405
5407 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
5408 if (!strncasecmp(ast_channel_name(bridge_channel->chan), word, wordlen)) {
5409 if (ast_cli_completion_add(ast_strdup(ast_channel_name(bridge_channel->chan)))) {
5410 break;
5411 }
5412 }
5413 }
5415
5416 ao2_ref(bridge, -1);
5417
5418 return NULL;
5419}
5420
5421static char *handle_bridge_kick_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5422{
5423 static const char * const completions[] = { "all", NULL };
5424 struct ast_bridge *bridge;
5425
5426 switch (cmd) {
5427 case CLI_INIT:
5428 e->command = "bridge kick";
5429 e->usage =
5430 "Usage: bridge kick <bridge-id> <channel-name | all>\n"
5431 " Kick the <channel-name> channel out of the <bridge-id> bridge\n"
5432 " If all is specified as the channel name then all channels will be\n"
5433 " kicked out of the bridge.\n";
5434 return NULL;
5435 case CLI_GENERATE:
5436 if (a->pos == 2) {
5437 return complete_bridge_live(a->word);
5438 }
5439 if (a->pos == 3) {
5440 ast_cli_complete(a->word, completions, -1);
5441 return complete_bridge_participant(a->argv[2], a->word);
5442 }
5443 return NULL;
5444 }
5445
5446 if (a->argc != 4) {
5447 return CLI_SHOWUSAGE;
5448 }
5449
5450 bridge = ast_bridge_find_by_id(a->argv[2]);
5451 if (!bridge) {
5452 ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
5453 return CLI_SUCCESS;
5454 }
5455
5456 if (!strcasecmp(a->argv[3], "all")) {
5457 struct ast_bridge_channel *bridge_channel;
5458
5459 ast_cli(a->fd, "Kicking all channels from bridge '%s'\n", a->argv[2]);
5460
5462 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
5463 ast_bridge_channel_queue_callback(bridge_channel, 0, kick_it, NULL, 0);
5464 }
5466 } else {
5467 struct ast_channel *chan;
5468
5469 chan = ast_channel_get_by_name_prefix(a->argv[3], strlen(a->argv[3]));
5470 if (!chan) {
5471 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[3]);
5472 ao2_ref(bridge, -1);
5473 return CLI_SUCCESS;
5474 }
5475
5476 ast_cli(a->fd, "Kicking channel '%s' from bridge '%s'\n",
5477 ast_channel_name(chan), a->argv[2]);
5478 ast_bridge_kick(bridge, chan);
5479 ast_channel_unref(chan);
5480 }
5481
5482 ao2_ref(bridge, -1);
5483 return CLI_SUCCESS;
5484}
5485
5486/*! Bridge technology capabilities to string. */
5487static const char *tech_capability2str(uint32_t capabilities)
5488{
5489 const char *type;
5490
5491 if (capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
5492 type = "Holding";
5493 } else if (capabilities & AST_BRIDGE_CAPABILITY_EARLY) {
5494 type = "Early";
5495 } else if (capabilities & AST_BRIDGE_CAPABILITY_NATIVE) {
5496 type = "Native";
5497 } else if (capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
5498 type = "1to1Mix";
5499 } else if (capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
5500 type = "MultiMix";
5501 } else {
5502 type = "<Unknown>";
5503 }
5504 return type;
5505}
5506
5507static char *handle_bridge_technology_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5508{
5509#define FORMAT_HDR "%-20s %-20s %8s %s\n"
5510#define FORMAT_ROW "%-20s %-20s %8u %s\n"
5511
5512 struct ast_bridge_technology *cur;
5513
5514 switch (cmd) {
5515 case CLI_INIT:
5516 e->command = "bridge technology show";
5517 e->usage =
5518 "Usage: bridge technology show\n"
5519 " List registered bridge technologies\n";
5520 return NULL;
5521 case CLI_GENERATE:
5522 return NULL;
5523 }
5524
5525 ast_cli(a->fd, FORMAT_HDR, "Name", "Type", "Priority", "Suspended");
5528 const char *type;
5529
5530 /* Decode type for display */
5532
5533 ast_cli(a->fd, FORMAT_ROW, cur->name, type, cur->preference,
5534 AST_CLI_YESNO(cur->suspended));
5535 }
5537 return CLI_SUCCESS;
5538
5539#undef FORMAT
5540}
5541
5542static char *complete_bridge_technology(const char *word)
5543{
5544 struct ast_bridge_technology *cur;
5545 int wordlen;
5546
5547 wordlen = strlen(word);
5550 if (!strncasecmp(cur->name, word, wordlen)) {
5552 break;
5553 }
5554 }
5555 }
5557
5558 return NULL;
5559}
5560
5561static char *handle_bridge_technology_suspend(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5562{
5563 struct ast_bridge_technology *cur;
5564 int suspend;
5565 int successful;
5566
5567 switch (cmd) {
5568 case CLI_INIT:
5569 e->command = "bridge technology {suspend|unsuspend}";
5570 e->usage =
5571 "Usage: bridge technology {suspend|unsuspend} <technology-name>\n"
5572 " Suspend or unsuspend a bridge technology.\n";
5573 return NULL;
5574 case CLI_GENERATE:
5575 if (a->pos == 3) {
5576 return complete_bridge_technology(a->word);
5577 }
5578 return NULL;
5579 }
5580
5581 if (a->argc != 4) {
5582 return CLI_SHOWUSAGE;
5583 }
5584
5585 suspend = !strcasecmp(a->argv[2], "suspend");
5586 successful = 0;
5589 if (!strcasecmp(cur->name, a->argv[3])) {
5590 successful = 1;
5591 if (suspend) {
5593 } else {
5595 }
5596 break;
5597 }
5598 }
5600
5601 if (successful) {
5602 if (suspend) {
5603 ast_cli(a->fd, "Suspended bridge technology '%s'\n", a->argv[3]);
5604 } else {
5605 ast_cli(a->fd, "Unsuspended bridge technology '%s'\n", a->argv[3]);
5606 }
5607 } else {
5608 ast_cli(a->fd, "Bridge technology '%s' not found\n", a->argv[3]);
5609 }
5610
5611 return CLI_SUCCESS;
5612}
5613
5614static struct ast_cli_entry bridge_cli[] = {
5615 AST_CLI_DEFINE(handle_bridge_show_all, "List all bridges"),
5616 AST_CLI_DEFINE(handle_bridge_show_specific, "Show information about a bridge"),
5617#ifdef AST_DEVMODE
5618 AST_CLI_DEFINE(handle_bridge_destroy_specific, "Destroy a bridge"),
5619#endif
5620 AST_CLI_DEFINE(handle_bridge_kick_channel, "Kick a channel from a bridge"),
5621 AST_CLI_DEFINE(handle_bridge_technology_show, "List registered bridge technologies"),
5622 AST_CLI_DEFINE(handle_bridge_technology_suspend, "Suspend/unsuspend a bridge technology"),
5623};
5624
5625
5626static int handle_manager_bridge_tech_suspend(struct mansession *s, const struct message *m, int suspend)
5627{
5628 const char *name = astman_get_header(m, "BridgeTechnology");
5629 struct ast_bridge_technology *cur;
5630 int successful = 0;
5631
5632 if (ast_strlen_zero(name)) {
5633 astman_send_error(s, m, "BridgeTechnology must be provided");
5634 return 0;
5635 }
5636
5639
5640 if (!strcasecmp(cur->name, name)) {
5641 successful = 1;
5642 if (suspend) {
5644 } else {
5646 }
5647 break;
5648 }
5649 }
5651 if (!successful) {
5652 astman_send_error(s, m, "BridgeTechnology not found");
5653 return 0;
5654 }
5655
5656 astman_send_ack(s, m, (suspend ? "Suspended bridge technology" : "Unsuspended bridge technology"));
5657 return 0;
5658}
5659
5660static int manager_bridge_tech_suspend(struct mansession *s, const struct message *m)
5661{
5662 return handle_manager_bridge_tech_suspend(s, m, 1);
5663}
5664
5665static int manager_bridge_tech_unsuspend(struct mansession *s, const struct message *m)
5666{
5667 return handle_manager_bridge_tech_suspend(s, m, 0);
5668}
5669
5670static int manager_bridge_tech_list(struct mansession *s, const struct message *m)
5671{
5672 const char *id = astman_get_header(m, "ActionID");
5673 RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free);
5674 struct ast_bridge_technology *cur;
5675 int num_items = 0;
5676
5677 if (!id_text) {
5678 astman_send_error(s, m, "Internal error");
5679 return -1;
5680 }
5681
5682 if (!ast_strlen_zero(id)) {
5683 ast_str_set(&id_text, 0, "ActionID: %s\r\n", id);
5684 }
5685
5686 astman_send_listack(s, m, "Bridge technology listing will follow", "start");
5687
5690 const char *type;
5691
5693
5694 astman_append(s,
5695 "Event: BridgeTechnologyListItem\r\n"
5696 "BridgeTechnology: %s\r\n"
5697 "BridgeType: %s\r\n"
5698 "BridgePriority: %u\r\n"
5699 "BridgeSuspended: %s\r\n"
5700 "%s"
5701 "\r\n",
5702 cur->name, type, cur->preference, AST_YESNO(cur->suspended),
5703 ast_str_buffer(id_text));
5704 ++num_items;
5705 }
5707
5708 astman_send_list_complete_start(s, m, "BridgeTechnologyListComplete", num_items);
5710
5711 return 0;
5712}
5713
5714/*!
5715 * \internal
5716 * \brief Print bridge object key (name).
5717 * \since 12.0.0
5718 *
5719 * \param v_obj A pointer to the object we want the key printed.
5720 * \param where User data needed by prnt to determine where to put output.
5721 * \param prnt Print output callback function to use.
5722 */
5723static void bridge_prnt_obj(void *v_obj, void *where, ao2_prnt_fn *prnt)
5724{
5725 struct ast_bridge *bridge = v_obj;
5726
5727 if (!bridge) {
5728 return;
5729 }
5730 prnt(where, "%s %s chans:%u",
5731 bridge->uniqueid, bridge->v_table->name, bridge->num_channels);
5732}
5733
5734/*!
5735 * \internal
5736 * \brief Shutdown the bridging system. Stuff to do on graceful shutdown.
5737 * \since 13.3.0
5738 */
5739static void bridge_cleanup(void)
5740{
5741 ast_manager_unregister("BridgeTechnologyList");
5742 ast_manager_unregister("BridgeTechnologySuspend");
5743 ast_manager_unregister("BridgeTechnologyUnsuspend");
5745 ao2_container_unregister("bridges");
5746
5748 bridges = NULL;
5751}
5752
5754{
5756
5758 return -1;
5759 }
5760
5762 if (!bridge_manager) {
5763 return -1;
5764 }
5765
5768 if (!bridges) {
5769 return -1;
5770 }
5772
5774
5776
5777 ast_manager_register_xml_core("BridgeTechnologyList", 0, manager_bridge_tech_list);
5778 ast_manager_register_xml_core("BridgeTechnologySuspend", 0, manager_bridge_tech_suspend);
5779 ast_manager_register_xml_core("BridgeTechnologyUnsuspend", 0, manager_bridge_tech_unsuspend);
5780
5781 return 0;
5782}
Prototypes for public functions only of internal interest,.
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
static const char app[]
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:1790
ast_cond_t cond
Definition app_sla.c:336
ast_mutex_t lock
Definition app_sla.c:337
#define var
Definition ast_expr2f.c:605
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:2105
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:4561
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:4016
static struct ast_channel * get_transferee(struct ao2_container *channels, struct ast_channel *transferer)
Definition bridge.c:4391
struct ao2_container * ast_bridges(void)
Returns the global bridges container.
Definition bridge.c:196
static struct bridge_manager_controller * bridge_manager
Definition bridge.c:194
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:3975
int ast_bridging_init(void)
Initialize the bridging system.
Definition bridge.c:5753
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:1019
static void bridge_channel_complete_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Definition bridge.c:463
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:1820
static int bridge_base_push_peek(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
Definition bridge.c:1003
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:4820
static int manager_bridge_tech_list(struct mansession *s, const struct message *m)
Definition bridge.c:5670
static int bridge_set_ari_var_reportable(struct ast_bridge *bridge, const char *variable, int report_events)
Definition bridge.c:1309
static void bridge_channel_impart_ds_head_signal(struct bridge_channel_impart_ds_head *ds_head)
Definition bridge.c:1693
static int channel_hash(const void *obj, int flags)
Definition bridge.c:4182
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:3474
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:3914
void ast_bridge_technology_unsuspend(struct ast_bridge_technology *technology)
Unsuspend a bridge technology.
Definition bridge.c:3261
static void hooks_remove_heap(struct ast_heap *hooks, enum ast_bridge_hook_remove_flags remove_flags)
Definition bridge.c:3688
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:4256
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:3621
int ast_bridge_number_video_src(struct ast_bridge *bridge)
Returns the number of video sources currently active in the bridge.
Definition bridge.c:4073
struct ao2_container * ast_bridge_peers_nolock(struct ast_bridge *bridge)
Get a container of all channels in the bridge.
Definition bridge.c:4227
static void set_bridge_peer_vars_2party(struct ast_channel *c0, struct ast_channel *c1)
Definition bridge.c:1430
static char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING]
Definition bridge.c:166
static void bridge_channel_impart_ds_head_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition bridge.c:1722
#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:3829
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:2247
static void bridge_queue_action_nodup(struct ast_bridge *bridge, struct ast_frame *action)
Definition bridge.c:314
void ast_bridge_set_sfu_video_mode(struct ast_bridge *bridge)
Set the bridge to be a selective forwarding unit.
Definition bridge.c:3983
static int manager_bridge_tech_suspend(struct mansession *s, const struct message *m)
Definition bridge.c:5660
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:4777
static void bridge_manager_service(struct ast_bridge *bridge)
Definition bridge.c:5078
int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature)
Unregister a handler for a built in feature.
Definition bridge.c:3287
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:3440
static void bridge_base_dissolving(struct ast_bridge *self)
Definition bridge.c:913
int ast_bridge_features_limits_construct(struct ast_bridge_features_limits *limits)
Constructor function for ast_bridge_features_limits.
Definition bridge.c:3605
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:3928
static int hook_remove_match(void *obj, void *arg, int flags)
Definition bridge.c:3654
void bridge_dissolve(struct ast_bridge *bridge, int cause)
Definition bridge.c:337
static int manager_bridge_tech_unsuspend(struct mansession *s, const struct message *m)
Definition bridge.c:5665
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:3528
static void bridge_channel_impart_wait(struct bridge_channel_impart_cond *cond)
Definition bridge.c:1800
static struct ast_cli_entry bridge_cli[]
Definition bridge.c:5614
#define FORMAT_ROW
static int interval_hook_time_cmp(void *a, void *b)
Definition bridge.c:3717
#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:3991
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:3516
static const char * tech_capability2str(uint32_t capabilities)
Definition bridge.c:5487
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:3504
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:3710
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:3391
static void bridge_hook_destroy(void *vhook)
Definition bridge.c:3348
static int channel_cmp(void *obj, void *arg, int flags)
Definition bridge.c:4205
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:2077
int ast_bridge_queue_action(struct ast_bridge *bridge, struct ast_frame *action)
Put an action onto the specified bridge.
Definition bridge.c:325
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition bridge.c:1029
static int bridge_sort_cmp(const void *obj_left, const void *obj_right, int flags)
Definition bridge.c:5199
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:4430
static int handle_manager_bridge_tech_suspend(struct mansession *s, const struct message *m, int suspend)
Definition bridge.c:5626
static void bridge_manager_destroy(void *obj)
Definition bridge.c:5128
static int bridge_dtmf_hook_sort(const void *obj_left, const void *obj_right, int flags)
Definition bridge.c:3748
static void check_bridge_play_sounds(struct ast_bridge *bridge)
Definition bridge.c:1292
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:3078
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:3636
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition bridge.c:1008
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:3299
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:4007
struct varshead * ast_bridge_get_ari_reportable_variables(struct ast_bridge *bridge)
Get a list of variables that should be included in ARI events for this bridge.
Definition bridge.c:1385
static void * bridge_manager_thread(void *data)
Definition bridge.c:5095
struct ast_bridge * ast_bridge_transfer_acquire_bridge(struct ast_channel *chan)
Acquire the channel's bridge for transfer purposes.
Definition bridge.c:4617
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:3484
static struct ast_bridge * optimize_lock_chan_stack(struct ast_channel *chan)
Definition bridge.c:2788
static int complete_bridge_live_search(void *obj, void *arg, int flags)
Definition bridge.c:5226
struct ast_bridge * bridge_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Definition bridge.c:731
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:2415
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:3044
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:2598
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition bridge.c:3892
static void bridge_channel_impart_ds_head_dtor(void *doomed)
Definition bridge.c:1707
int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
Remove a channel from a bridge.
Definition bridge.c:2150
#define BV_NAME_CMP(var_str, name)
Compare a bridge variable name with a given name.
Definition bridge.c:161
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:1301
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:803
void ast_bridge_merge_inhibit(struct ast_bridge *bridge, int request)
Adjust the bridge merge inhibit request count.
Definition bridge.c:3209
static void fill_bridgepeer_buf(char *buf, unsigned int cur_idx, const char *names[], unsigned int num_names)
Definition bridge.c:1468
void bridge_reconfigured(struct ast_bridge *bridge, unsigned int colp_update)
Definition bridge.c:1602
static char * handle_bridge_technology_suspend(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition bridge.c:5561
int ast_bridge_kick(struct ast_bridge *bridge, struct ast_channel *chan)
Kick a channel from a bridge.
Definition bridge.c:2178
static int smart_bridge_operation(struct ast_bridge *bridge)
Definition bridge.c:1061
void bridge_channel_impart_signal(struct ast_channel *chan)
Definition bridge.c:1781
static int bridge_base_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
Definition bridge.c:937
static int bridge_base_get_merge_priority(struct ast_bridge *self)
Definition bridge.c:983
static ast_bridge_builtin_set_limits_fn builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_END]
Definition bridge.c:172
static ast_bridge_hook_callback builtin_features_handlers[AST_BRIDGE_BUILTIN_END]
Definition bridge.c:169
static int merge_container_cb(void *obj, void *data, int flags)
Callback for merging hook ao2_containers.
Definition bridge.c:3771
static char * handle_bridge_technology_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition bridge.c:5507
struct ast_bridge * ast_bridge_find_by_id(const char *bridge_id)
Find bridge by id.
Definition bridge.c:5221
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:4284
struct ast_bridge_channel * bridge_find_channel(struct ast_bridge *bridge, struct ast_channel *chan)
Definition bridge.c:1628
static char * handle_bridge_kick_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition bridge.c:5421
int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan)
Suspend a channel temporarily from a bridge.
Definition bridge.c:3216
static void bridge_prnt_obj(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition bridge.c:5723
static const struct ast_datastore_info bridge_channel_impart_ds_info
Definition bridge.c:1731
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:3958
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:3907
static struct ast_bridge * optimize_lock_peer_stack(struct ast_channel *peer)
Definition bridge.c:2833
struct ao2_container * ast_bridge_peers(struct ast_bridge *bridge)
Get a container of all channels in the bridge.
Definition bridge.c:4245
#define MAX_BRIDGEPEER_CHANS
static void set_transfer_variables_all(struct ast_channel *transferer, struct ao2_container *channels, int is_attended)
Definition bridge.c:4592
static void bridge_base_destroy(struct ast_bridge *self)
Definition bridge.c:900
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:3804
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:2954
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:3792
struct ast_bridge * bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
Definition bridge.c:765
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:4126
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:4634
static void destroy_bridge(void *obj)
Definition bridge.c:670
bridge_allow_swap
Definition bridge.c:2881
@ SWAP_PROHIBITED
Definition bridge.c:2883
@ SWAP_TO_PEER_BRIDGE
Definition bridge.c:2887
@ SWAP_TO_CHAN_BRIDGE
Definition bridge.c:2885
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:3778
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:4160
static void hooks_remove_container(struct ao2_container *hooks, enum ast_bridge_hook_remove_flags remove_flags)
Definition bridge.c:3674
static void bridge_reconfigured_connected_line_update(struct ast_bridge *bridge)
Definition bridge.c:415
static void cleanup_video_mode(struct ast_bridge *bridge)
Definition bridge.c:3935
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:2499
#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:4535
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:3494
int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan)
Unsuspend a channel from a bridge.
Definition bridge.c:3237
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:4175
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:2670
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:3316
static void set_bridge_peer_vars_multiparty(struct ast_bridge *bridge)
Definition bridge.c:1505
static char * complete_bridge_live(const char *word)
Definition bridge.c:5237
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition bridge.c:3862
static void bridge_action_bridge(struct ast_bridge *bridge, struct ast_frame *action)
Definition bridge.c:618
bridge_allow_merge
Definition bridge.c:3020
@ MERGE_ALLOWED
Definition bridge.c:3028
@ MERGE_NOT_ENOUGH_CHANNELS
Definition bridge.c:3024
@ MERGE_NO_MULTIMIX
Definition bridge.c:3026
@ MERGE_PROHIBITED
Definition bridge.c:3022
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:4320
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:3371
const char * ast_bridge_get_variable(const struct ast_bridge *bridge, const char *name)
Get value a variable from the bridge by name.
Definition bridge.c:1380
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:4025
static void bridge_cleanup(void)
Definition bridge.c:5739
static void bridge_channel_change_bridge(struct ast_bridge_channel *bridge_channel, struct ast_bridge *new_bridge)
Definition bridge.c:2206
static struct bridge_manager_controller * bridge_manager_create(void)
Definition bridge.c:5160
static char * handle_bridge_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition bridge.c:5245
static void bridge_handle_actions(struct ast_bridge *bridge)
Definition bridge.c:652
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:1976
static void * bridge_channel_depart_thread(void *data)
Thread responsible for imparted bridged channels to be departed.
Definition bridge.c:1910
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition bridge.c:285
static void bridge_complete_join(struct ast_bridge *bridge)
Definition bridge.c:504
int ast_bridge_interval_unregister(enum ast_bridge_builtin_interval interval)
Unregisters a handler for a built in interval feature.
Definition bridge.c:3328
#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:3129
static void kick_it(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
Definition bridge.c:2173
static char * complete_bridge_participant(const char *bridge_name, const char *word)
Definition bridge.c:5393
void ast_bridge_technology_suspend(struct ast_bridge_technology *technology)
Suspend a bridge technology from consideration.
Definition bridge.c:3256
int __ast_bridge_technology_register(struct ast_bridge_technology *technology, struct ast_module *module)
Register a bridge technology for use.
Definition bridge.c:234
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition bridge.c:3883
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:3574
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:3169
static void check_bridge_play_sound(struct ast_bridge_channel *bridge_channel)
Definition bridge.c:1264
int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel, int attempt_recovery, unsigned int optimized)
Definition bridge.c:2513
static void set_bridge_peer_vars(struct ast_bridge *bridge)
Definition bridge.c:1585
static int bridge_channel_impart_add(struct ast_channel *chan, struct bridge_channel_impart_cond *cond)
Definition bridge.c:1748
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:4100
int ast_bridge_set_variable(struct ast_bridge *bridge, const char *name, const char *value, int report_events)
Set a variable on the bridge.
Definition bridge.c:1341
static void bridge_channel_moving(struct ast_bridge_channel *bridge_channel, struct ast_bridge *src, struct ast_bridge *dst)
Definition bridge.c:2221
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:529
static void bridge_manager_service_req(struct ast_bridge *bridge)
Definition bridge.c:208
static char * complete_bridge_technology(const char *word)
Definition bridge.c:5542
void ast_bridge_features_limits_destroy(struct ast_bridge_features_limits *limits)
Destructor function for ast_bridge_features_limits.
Definition bridge.c:3616
void bridge_merge_inhibit_nolock(struct ast_bridge *bridge, int request)
Definition bridge.c:3200
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:3271
static struct merge_direction bridge_merge_determine_direction(struct ast_bridge *bridge1, struct ast_bridge *bridge2)
Definition bridge.c:2352
static void bridge_base_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
Definition bridge.c:952
static void bridge_dissolve_check_stolen(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Definition bridge.c:385
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:3998
static enum bridge_allow_swap bridges_allow_swap_optimization(struct ast_bridge *chan_bridge, struct ast_bridge *peer_bridge)
Definition bridge.c:2898
static char * handle_bridge_show_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition bridge.c:5309
void ast_bridge_notify_masquerade(struct ast_channel *chan)
Notify bridging that this channel was just masqueraded.
Definition bridge.c:1641
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition bridge.c:4886
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:5292
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:2659
static void bridge_tech_deferred_destroy(struct ast_bridge *bridge, struct ast_frame *action)
Definition bridge.c:590
static void bridge_base_notify_masquerade(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
Definition bridge.c:967
static int bridge_allows_optimization(struct ast_bridge *bridge)
Definition bridge.c:2769
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:3921
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:3786
#define FORMAT_HDR
static void * bridge_channel_ind_thread(void *data)
Thread responsible for independent imparted bridged channels.
Definition bridge.c:1941
static void set_bridge_peer_vars_holding(struct ast_bridge *bridge)
Definition bridge.c:1565
Bridging API.
#define ast_bridge_lock_both(bridge1, bridge2)
Lock two bridges.
Definition bridge.h:498
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition bridge.h:491
ast_bridge_optimization
Tells, if optimization is allowed, how the optimization would be performed.
Definition bridge.h:935
@ AST_BRIDGE_OPTIMIZE_PROHIBITED
Definition bridge.h:945
@ AST_BRIDGE_OPTIMIZE_MERGE_TO_CHAN_BRIDGE
Definition bridge.h:941
@ AST_BRIDGE_OPTIMIZE_SWAP_TO_PEER_BRIDGE
Definition bridge.h:939
@ AST_BRIDGE_OPTIMIZE_MERGE_TO_PEER_BRIDGE
Definition bridge.h:943
@ AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE
Definition bridge.h:937
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:469
@ 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:1174
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:1204
ast_transfer_result
Definition bridge.h:1159
@ AST_BRIDGE_TRANSFER_NOT_PERMITTED
Definition bridge.h:1163
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition bridge.h:1161
@ AST_BRIDGE_TRANSFER_INVALID
Definition bridge.h:1165
@ AST_BRIDGE_TRANSFER_FAIL
Definition bridge.h:1167
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:480
ast_bridge_impart_flags
Definition bridge.h:594
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
Definition bridge.h:598
@ AST_BRIDGE_IMPART_CHAN_MASK
Definition bridge.h:596
@ AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP
Definition bridge.h:602
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition bridge.h:600
#define BRIDGE_PRINTF_VARS(bridge)
Definition bridge.h:80
ast_bridge_join_flags
Definition bridge.h:543
@ AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP
Definition bridge.h:547
@ AST_BRIDGE_JOIN_PASS_REFERENCE
Definition bridge.h:545
#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.
@ AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED
@ AST_BRIDGE_AFTER_CB_REASON_DEPART
void ast_bridge_run_after_goto(struct ast_channel *chan)
Run a PBX on any after bridge goto location.
int ast_bridge_setup_after_goto(struct ast_channel *chan)
Setup any after bridge goto location to begin execution.
void ast_bridge_run_after_callback(struct ast_channel *chan)
Run any after bridge callback.
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
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:3211
static int connected
Definition cdr_pgsql.c:73
static struct ast_timer * timer
Definition chan_iax2.c:401
static const char type[]
static const char config[]
static int request(void *obj)
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:6480
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2376
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2540
@ 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:2059
void ast_channel_internal_bridge_channel_set(struct ast_channel *chan, struct ast_bridge_channel *value)
#define ast_channel_lock(chan)
Definition channel.h:2983
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
@ AST_FLAG_ZOMBIE
Definition channel.h:1007
@ AST_FLAG_EMULATE_DTMF
Definition channel.h:1024
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition channel.c:10773
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
#define ast_channel_ref(c)
Increase channel reference count.
Definition channel.h:3008
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition channel.h:2990
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:6453
int ast_check_hangup_locked(struct ast_channel *chan)
Definition channel.c:460
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:1400
#define ast_channel_trylock(chan)
Definition channel.h:2985
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:10714
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2462
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:8873
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3019
#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:2009
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:10762
const char * ast_cause2str(int cause) attribute_pure
Gives the string form of a given cause code.
Definition channel.c:613
@ AST_SOFTHANGUP_ASYNCGOTO
Definition channel.h:1146
@ AST_SOFTHANGUP_DEV
Definition channel.h:1141
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:8469
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition channel.c:2449
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:3030
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition channel.c:2805
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition channel.c:4298
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:6373
#define ast_channel_unlock(chan)
Definition channel.h:2984
#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:2390
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:2517
ast_channel_state
ast_channel states
@ AST_STATE_UP
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, int rdlock)
void ast_var_list_destroy(struct varshead *head)
Definition chanvars.c:109
char * ast_var_find(const struct varshead *head, const char *name)
Definition chanvars.c:85
const char * ast_var_name(const struct ast_var_t *var)
Definition chanvars.c:60
#define ast_var_assign(name, value)
Definition chanvars.h:40
void ast_var_delete(struct ast_var_t *var)
Definition extconf.c:2469
struct varshead * ast_var_list_create(void)
Definition chanvars.c:97
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
#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:2845
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:1931
@ 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
#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 * 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:2042
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition manager.c:2000
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:2078
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition manager.c:2032
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition manager.c:1661
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition manager.c:2086
void astman_append(struct mansession *s, const char *fmt,...)
Definition manager.c:1921
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7716
#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 callid 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
#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.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#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.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_RWLIST_TRAVERSE
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_RWLIST_INSERT_TAIL
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_RWLIST_INSERT_BEFORE_CURRENT
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
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:204
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:7812
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
#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.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
#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
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
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
struct ast_bridge_channel::@201 entry
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
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.
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
union ast_bridge_video_mode::@198 mode_data
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:355
struct ast_bridge_softmix softmix
Definition bridge.h:373
void * tech_pvt
Definition bridge.h:363
struct ast_vector_int media_types
Definition bridge.h:410
struct timeval creationtime
Definition bridge.h:414
const struct ast_bridge_methods * v_table
Definition bridge.h:357
struct varshead bridgevars
Definition bridge.h:416
unsigned int reconfigured
Definition bridge.h:394
unsigned int num_active
Definition bridge.h:381
ast_callid callid
Definition bridge.h:367
const ast_string_field creator
Definition bridge.h:407
const ast_string_field uniqueid
Definition bridge.h:407
struct ast_bridge_channels_list channels
Definition bridge.h:369
struct ast_bridge_snapshot * current_snapshot
Definition bridge.h:412
unsigned int num_channels
Definition bridge.h:379
unsigned int dissolved
Definition bridge.h:396
struct ast_bridge::@199 action_queue
int cause
Definition bridge.h:392
struct ast_bridge_technology * technology
Definition bridge.h:361
unsigned int construction_completed
Definition bridge.h:398
struct ast_bridge::@200 ari_reportable_variable_names
const ast_string_field name
Definition bridge.h:407
unsigned int num_lonely
Definition bridge.h:383
unsigned int inhibit_merge
Count of the active temporary requests to inhibit bridge merges. Zero if merges are allowed.
Definition bridge.h:390
struct ast_flags feature_flags
Definition bridge.h:375
uint32_t allowed_capabilities
Definition bridge.h:377
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
char context[AST_MAX_CONTEXT]
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:221
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::@237 data
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
struct ast_var_t::@221 entries
Internal bridge impart wait condition and associated conditional.
Definition bridge.c:1674
struct bridge_channel_impart_cond::@329 node
struct bridge_manager_controller::@328 service_requests
struct ast_bridge * bridge
Definition bridge.c:179
struct bridge_manager_request::@327 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:2337
struct ast_bridge * dest
Definition bridge.c:2335
struct ast_bridge_technology * tech
Definition bridge.c:576
AO2 object that wraps data for transfer_channel_cb.
Definition bridge.h:1180
int value
Definition syslog.c:37
Test Framework API.
static int hook_cb(struct ast_config *cfg)
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:2331
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:64
#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:981
#define ast_assert(a)
Definition utils.h:779
#define MIN(a, b)
Definition utils.h:252
#define ast_pthread_create(a, b, c, d)
Definition utils.h:624
#define ast_pthread_create_detached(a, b, c, d)
Definition utils.h:628
#define SWAP(a, b)
Definition utils.h:256
#define ast_set_flag(p, flag)
Definition utils.h:71
#define ARRAY_LEN(a)
Definition utils.h:706
#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_RESET(vec, cleanup)
Reset vector.
Definition vector.h:636
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:620
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
Definition vector.h:499
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition vector.h:742
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691