bridge.c File Reference

Bridging API. More...

#include "asterisk.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_internal.h"
#include "asterisk/bridge_channel_internal.h"
#include "asterisk/bridge_features.h"
#include "asterisk/bridge_basic.h"
#include "asterisk/bridge_technology.h"
#include "asterisk/bridge_channel.h"
#include "asterisk/bridge_after.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_cache_pattern.h"
#include "asterisk/app.h"
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/pbx.h"
#include "asterisk/test.h"
#include "asterisk/_private.h"
#include "asterisk/heap.h"
#include "asterisk/say.h"
#include "asterisk/timing.h"
#include "asterisk/stringfields.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/cli.h"
#include "asterisk/parking.h"
#include "asterisk/core_local.h"
#include "asterisk/core_unreal.h"
#include "asterisk/causes.h"

Include dependency graph for bridge.c:

Go to the source code of this file.

Data Structures

struct  bridge_complete
struct  bridge_manager_controller
struct  bridge_manager_request
struct  bridge_technologies
struct  merge_direction
struct  tech_deferred_destroy

Defines

#define ATTENDEDTRANSFER   "ATTENDEDTRANSFER"
#define BLINDTRANSFER   "BLINDTRANSFER"
#define BRIDGE_ARRAY_GROW   32
#define BRIDGE_ARRAY_START   128
#define FORMAT_HDR   "%-20s %-20s %8s %s\n"
#define FORMAT_HDR   "%-36s %5s %-15s %s\n"
#define FORMAT_ROW   "%-20s %-20s %8u %s\n"
#define FORMAT_ROW   "%-36s %5u %-15s %s\n"
#define MAX_BRIDGEPEER_CHANS   (10 + 1)
#define UPDATE_BRIDGE_VARS_GET(chan, name, pvtid)

Enumerations

enum  bridge_allow_merge { MERGE_PROHIBITED, MERGE_NOT_ENOUGH_CHANNELS, MERGE_NO_MULTIMIX, MERGE_ALLOWED }
enum  bridge_allow_swap { SWAP_PROHIBITED, SWAP_TO_CHAN_BRIDGE, SWAP_TO_PEER_BRIDGE }

Functions

int __ast_bridge_technology_register (struct ast_bridge_technology *technology, struct ast_module *module)
 Register a bridge technology for use.
static void __fini_bridge_technologies (void)
static void __init_bridge_technologies (void)
static struct ast_bridgeacquire_bridge (struct ast_channel *chan)
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.
struct ast_bridgeast_bridge_base_new (uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
 Create a new base class bridge.
int ast_bridge_depart (struct ast_channel *chan)
 Depart a channel from a bridge.
int ast_bridge_destroy (struct ast_bridge *bridge, int cause)
 Destroy a bridge.
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.
void ast_bridge_features_cleanup (struct ast_bridge_features *features)
 Clean up the contents of a bridge features structure.
void ast_bridge_features_destroy (struct ast_bridge_features *features)
 Destroy an allocated bridge features struct.
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.
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.
int ast_bridge_features_init (struct ast_bridge_features *features)
 Initialize bridge features structure.
int ast_bridge_features_limits_construct (struct ast_bridge_features_limits *limits)
 Constructor function for ast_bridge_features_limits.
void ast_bridge_features_limits_destroy (struct ast_bridge_features_limits *limits)
 Destructor function for ast_bridge_features_limits.
void ast_bridge_features_merge (struct ast_bridge_features *into, const struct ast_bridge_features *from)
 Merge one ast_bridge_features into another.
struct ast_bridge_featuresast_bridge_features_new (void)
 Allocate a new bridge features struct.
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.
void ast_bridge_features_remove (struct ast_bridge_features *features, enum ast_bridge_hook_remove_flags remove_flags)
 Remove marked bridge channel feature hooks.
void ast_bridge_features_set_flag (struct ast_bridge_features *features, unsigned int flag)
 Set a flag on a bridge channel features structure.
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 time runs out.
int ast_bridge_features_unregister (enum ast_bridge_builtin_feature feature)
 Unregister a handler for a built in feature.
struct ast_bridgeast_bridge_find_by_id (const char *bridge_id)
 Find bridge by id.
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.
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).
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.
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.
int ast_bridge_interval_unregister (enum ast_bridge_builtin_interval interval)
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.
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).
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)
 Unregisters a handler for a built in interval feature.
int ast_bridge_kick (struct ast_bridge *bridge, struct ast_channel *chan)
 Kick a channel from a bridge.
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.
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.
void ast_bridge_merge_inhibit (struct ast_bridge *bridge, int request)
 Adjust the bridge merge inhibit request count.
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.
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.
void ast_bridge_notify_masquerade (struct ast_channel *chan)
 Notify bridging that this channel was just masqueraded.
int ast_bridge_number_video_src (struct ast_bridge *bridge)
 Returns the number of video sources currently active in the bridge.
struct ast_channelast_bridge_peer (struct ast_bridge *bridge, struct ast_channel *chan)
 Get the channel's bridge peer only if the bridge is two-party.
struct ast_channelast_bridge_peer_nolock (struct ast_bridge *bridge, struct ast_channel *chan)
 Get the channel's bridge peer only if the bridge is two-party.
struct ao2_containerast_bridge_peers (struct ast_bridge *bridge)
 Get a container of all channels in the bridge.
struct ao2_containerast_bridge_peers_nolock (struct ast_bridge *bridge)
 Get a container of all channels in the bridge.
int ast_bridge_queue_action (struct ast_bridge *bridge, struct ast_frame *action)
 Put an action onto the specified bridge.
int ast_bridge_remove (struct ast_bridge *bridge, struct ast_channel *chan)
 Remove a channel from a bridge.
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.
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.
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.
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.
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.
void ast_bridge_set_transfer_variables (struct ast_channel *chan, const char *value, int attended)
 Set the relevant transfer variables for a single channel.
int ast_bridge_suspend (struct ast_bridge *bridge, struct ast_channel *chan)
 Suspend a channel temporarily from a bridge.
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.
void ast_bridge_technology_suspend (struct ast_bridge_technology *technology)
 Suspend a bridge technology from consideration.
int ast_bridge_technology_unregister (struct ast_bridge_technology *technology)
 Unregister a bridge technology from use.
void ast_bridge_technology_unsuspend (struct ast_bridge_technology *technology)
 Unsuspend a bridge technology.
enum ast_transfer_result ast_bridge_transfer_attended (struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
 Attended transfer.
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.
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.
int ast_bridge_unsuspend (struct ast_bridge *bridge, struct ast_channel *chan)
 Unsuspend a channel from a bridge.
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.
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.
int ast_bridging_init (void)
 Initialize the bridging system.
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.
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)
static void bridge_action_bridge (struct ast_bridge *bridge, struct ast_frame *action)
struct ast_bridgebridge_alloc (size_t size, const struct ast_bridge_methods *v_table)
static int bridge_allows_optimization (struct ast_bridge *bridge)
static void bridge_base_destroy (struct ast_bridge *self)
static void bridge_base_dissolving (struct ast_bridge *self)
static int bridge_base_get_merge_priority (struct ast_bridge *self)
struct ast_bridgebridge_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.
static void bridge_base_notify_masquerade (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
static void bridge_base_pull (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
static int bridge_base_push (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
static int bridge_base_push_peek (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
static void bridge_channel_change_bridge (struct ast_bridge_channel *bridge_channel, struct ast_bridge *new_bridge)
static void bridge_channel_complete_join (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static void * bridge_channel_depart_thread (void *data)
 Thread responsible for imparted bridged channels to be departed.
static void * bridge_channel_ind_thread (void *data)
 Thread responsible for independent imparted bridged channels.
static void bridge_channel_moving (struct ast_bridge_channel *bridge_channel, struct ast_bridge *src, struct ast_bridge *dst)
static void bridge_cleanup (void)
static void bridge_complete_join (struct ast_bridge *bridge)
void bridge_dissolve (struct ast_bridge *bridge, int cause)
static void bridge_dissolve_check_stolen (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
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)
int bridge_do_move (struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel, int attempt_recovery, unsigned int optimized)
static int bridge_dtmf_hook_sort (const void *obj_left, const void *obj_right, int flags)
struct ast_bridge_channelbridge_find_channel (struct ast_bridge *bridge, struct ast_channel *chan)
static void bridge_handle_actions (struct ast_bridge *bridge)
static void bridge_hook_destroy (void *vhook)
static struct ast_bridge_hookbridge_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)
static struct
bridge_manager_controller
bridge_manager_create (void)
static void bridge_manager_destroy (void *obj)
static void bridge_manager_service (struct ast_bridge *bridge)
static void bridge_manager_service_req (struct ast_bridge *bridge)
static void * bridge_manager_thread (void *data)
static struct merge_direction bridge_merge_determine_direction (struct ast_bridge *bridge1, struct ast_bridge *bridge2)
void bridge_merge_inhibit_nolock (struct ast_bridge *bridge, int request)
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)
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)
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)
static void bridge_prnt_obj (void *v_obj, void *where, ao2_prnt_fn *prnt)
static void bridge_queue_action_nodup (struct ast_bridge *bridge, struct ast_frame *action)
void bridge_reconfigured (struct ast_bridge *bridge, unsigned int colp_update)
static void bridge_reconfigured_connected_line_update (struct ast_bridge *bridge)
struct ast_bridgebridge_register (struct ast_bridge *bridge)
 Register the new bridge with the system.
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.
static int bridge_sort_cmp (const void *obj_left, const void *obj_right, int flags)
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)
static void bridge_tech_deferred_destroy (struct ast_bridge *bridge, struct ast_frame *action)
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)
static enum bridge_allow_swap bridges_allow_swap_optimization (struct ast_bridge *chan_bridge, struct ast_bridge *peer_bridge)
static int channel_cmp (void *obj, void *arg, int flags)
static int channel_hash (const void *obj, int flags)
static void check_bridge_play_sound (struct ast_bridge_channel *bridge_channel)
static void check_bridge_play_sounds (struct ast_bridge *bridge)
static void cleanup_video_mode (struct ast_bridge *bridge)
static char * complete_bridge_live (const char *word, int state)
static int complete_bridge_live_search (void *obj, void *arg, void *data, int flags)
static char * complete_bridge_participant (const char *bridge_name, const char *line, const char *word, int pos, int state)
static char * complete_bridge_stasis (const char *word, int state)
static char * complete_bridge_technology (const char *word, int state)
static struct stasis_messagecreate_bridge_snapshot_message (struct ast_bridge *bridge)
static void destroy_bridge (void *obj)
static void fill_bridgepeer_buf (char *buf, unsigned int cur_idx, const char *names[], unsigned int num_names)
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.
static struct ast_channelget_transferee (struct ao2_container *channels, struct ast_channel *transferer)
static char * handle_bridge_kick_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_bridge_show_all (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_bridge_show_specific (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_bridge_technology_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_bridge_technology_suspend (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_manager_bridge_tech_suspend (struct mansession *s, const struct message *m, int suspend)
static int hook_remove_match (void *obj, void *arg, int flags)
static void hooks_remove_container (struct ao2_container *hooks, enum ast_bridge_hook_remove_flags remove_flags)
static void hooks_remove_heap (struct ast_heap *hooks, enum ast_bridge_hook_remove_flags remove_flags)
static int interval_hook_time_cmp (void *a, void *b)
static int interval_wrapper_cb (struct ast_bridge_channel *bridge_channel, void *obj)
 Wrapper for interval hooks that calls into the wrapped hook.
static void interval_wrapper_pvt_dtor (void *obj)
 Destructor for the hook wrapper.
static void kick_it (struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
static int manager_bridge_tech_list (struct mansession *s, const struct message *m)
static int manager_bridge_tech_suspend (struct mansession *s, const struct message *m)
static int manager_bridge_tech_unsuspend (struct mansession *s, const struct message *m)
static int merge_container_cb (void *obj, void *data, int flags)
 Callback for merging hook ao2_containers.
static struct ast_bridgeoptimize_lock_chan_stack (struct ast_channel *chan)
static struct ast_bridgeoptimize_lock_peer_stack (struct ast_channel *peer)
static void set_bridge_peer_vars (struct ast_bridge *bridge)
static void set_bridge_peer_vars_2party (struct ast_channel *c0, struct ast_channel *c1)
static void set_bridge_peer_vars_holding (struct ast_bridge *bridge)
static void set_bridge_peer_vars_multiparty (struct ast_bridge *bridge)
static void set_transfer_variables_all (struct ast_channel *transferer, struct ao2_container *channels, int is_attended)
static int smart_bridge_operation (struct ast_bridge *bridge)
static const char * tech_capability2str (uint32_t capabilities)
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)
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)
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)
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)
static void update_bridge_vars_set (struct ast_channel *chan, const char *name, const char *pvtid)
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.

Variables

struct ast_bridge_methods ast_bridge_base_v_table
 Bridge base class virtual method table.
static struct ast_cli_entry bridge_cli []
static struct
bridge_manager_controller
bridge_manager
static struct ao2_containerbridges
static char builtin_features_dtmf [AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING]
static ast_bridge_hook_callback builtin_features_handlers [AST_BRIDGE_BUILTIN_END]
static
ast_bridge_builtin_set_limits_fn 
builtin_interval_handlers [AST_BRIDGE_BUILTIN_INTERVAL_END]
static unsigned int optimization_id


Detailed Description

Bridging API.

Author:
Joshua Colp <jcolp@digium.com>

Definition in file bridge.c.


Define Documentation

#define ATTENDEDTRANSFER   "ATTENDEDTRANSFER"

Definition at line 129 of file bridge.c.

Referenced by ast_bridge_set_transfer_variables(), and attended_transfer_bridge().

#define BLINDTRANSFER   "BLINDTRANSFER"

Definition at line 126 of file bridge.c.

Referenced by ast_bridge_set_transfer_variables(), and blind_transfer_bridge().

#define BRIDGE_ARRAY_GROW   32

Definition at line 123 of file bridge.c.

#define BRIDGE_ARRAY_START   128

Definition at line 120 of file bridge.c.

#define FORMAT_HDR   "%-20s %-20s %8s %s\n"

#define FORMAT_HDR   "%-36s %5s %-15s %s\n"

#define FORMAT_ROW   "%-20s %-20s %8u %s\n"

#define FORMAT_ROW   "%-36s %5u %-15s %s\n"

#define MAX_BRIDGEPEER_CHANS   (10 + 1)

#define UPDATE_BRIDGE_VARS_GET ( chan,
name,
pvtid   ) 


Enumeration Type Documentation

Enumerator:
MERGE_PROHIBITED  Bridge properties prohibit merge optimization
MERGE_NOT_ENOUGH_CHANNELS  Merge optimization cannot occur because the source bridge has too few channels
MERGE_NO_MULTIMIX  Merge optimization cannot occur because multimix capability could not be requested
MERGE_ALLOWED  Merge optimization allowed between bridges

Definition at line 2628 of file bridge.c.

02628                         {
02629    /*! Bridge properties prohibit merge optimization */
02630    MERGE_PROHIBITED,
02631    /*! Merge optimization cannot occur because the source bridge has too few channels */
02632    MERGE_NOT_ENOUGH_CHANNELS,
02633    /*! Merge optimization cannot occur because multimix capability could not be requested */
02634    MERGE_NO_MULTIMIX,
02635    /*! Merge optimization allowed between bridges */
02636    MERGE_ALLOWED,
02637 };

Enumerator:
SWAP_PROHIBITED  Bridges cannot allow for a swap optimization to occur
SWAP_TO_CHAN_BRIDGE  Bridge swap optimization can occur into the chan_bridge
SWAP_TO_PEER_BRIDGE  Bridge swap optimization can occur into the peer_bridge

Definition at line 2489 of file bridge.c.

02489                        {
02490    /*! Bridges cannot allow for a swap optimization to occur */
02491    SWAP_PROHIBITED,
02492    /*! Bridge swap optimization can occur into the chan_bridge */
02493    SWAP_TO_CHAN_BRIDGE,
02494    /*! Bridge swap optimization can occur into the peer_bridge */
02495    SWAP_TO_PEER_BRIDGE,
02496 };


Function Documentation

int __ast_bridge_technology_register ( struct ast_bridge_technology technology,
struct ast_module mod 
)

Register a bridge technology for use.

Parameters:
technology The bridge technology to register
mod The module that is registering the bridge technology
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_technology_register(&simple_bridge_tech);

This registers a bridge technology declared as the structure simple_bridge_tech with the bridging core and makes it available for use when creating bridges.

Definition at line 199 of file bridge.c.

References ast_log, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero, ast_verb, ast_bridge_technology::capabilities, LOG_WARNING, ast_bridge_technology::mod, ast_bridge_technology::name, and ast_bridge_technology::write.

Referenced by dahdi_native_load().

00200 {
00201    struct ast_bridge_technology *current;
00202 
00203    /* Perform a sanity check to make sure the bridge technology conforms to our needed requirements */
00204    if (ast_strlen_zero(technology->name)
00205       || !technology->capabilities
00206       || !technology->write) {
00207       ast_log(LOG_WARNING, "Bridge technology %s failed registration sanity check.\n",
00208          technology->name);
00209       return -1;
00210    }
00211 
00212    AST_RWLIST_WRLOCK(&bridge_technologies);
00213 
00214    /* Look for duplicate bridge technology already using this name, or already registered */
00215    AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) {
00216       if ((!strcasecmp(current->name, technology->name)) || (current == technology)) {
00217          ast_log(LOG_WARNING, "A bridge technology of %s already claims to exist in our world.\n",
00218             technology->name);
00219          AST_RWLIST_UNLOCK(&bridge_technologies);
00220          return -1;
00221       }
00222    }
00223 
00224    /* Copy module pointer so reference counting can keep the module from unloading */
00225    technology->mod = module;
00226 
00227    /* Insert our new bridge technology into the list and print out a pretty message */
00228    AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
00229 
00230    AST_RWLIST_UNLOCK(&bridge_technologies);
00231 
00232    ast_verb(2, "Registered bridge technology %s\n", technology->name);
00233 
00234    return 0;
00235 }

static void __fini_bridge_technologies ( void   )  [static]

Definition at line 115 of file bridge.c.

00143 {

static void __init_bridge_technologies ( void   )  [static]

Definition at line 115 of file bridge.c.

00143 {

static struct ast_bridge* acquire_bridge ( struct ast_channel chan  )  [static, read]

Definition at line 4104 of file bridge.c.

References ao2_ref, AST_BRIDGE_FLAG_MASQUERADE_ONLY, ast_channel_get_bridge(), ast_channel_lock, ast_channel_unlock, ast_test_flag, ast_bridge::feature_flags, and NULL.

Referenced by ast_bridge_transfer_attended(), and ast_bridge_transfer_blind().

04105 {
04106    struct ast_bridge *bridge;
04107 
04108    ast_channel_lock(chan);
04109    bridge = ast_channel_get_bridge(chan);
04110    ast_channel_unlock(chan);
04111 
04112    if (bridge
04113       && ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)) {
04114       ao2_ref(bridge, -1);
04115       bridge = NULL;
04116    }
04117 
04118    return bridge;
04119 }

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.

Since:
12.0.0
The channel that is being added to the bridge can be in any state: unbridged, bridged, answered, unanswered, etc. The channel will be added asynchronously, meaning that when this function returns once the channel has been added to the bridge, not once the channel has been removed from the bridge.

In addition, a tone can optionally be played to the channel once the channel is placed into the bridge.

Note:
When this function returns, there is no guarantee that the channel that was passed in is valid any longer. Do not attempt to operate on the channel after this function returns.
Parameters:
bridge Bridge to which the channel should be added
chan The channel to add to the bridge
features Features for this channel in the bridge
play_tone Indicates if a tone should be played to the channel
xfersound Sound that should be used to indicate transfer with play_tone
Return values:
0 Success
-1 Failure

Definition at line 2291 of file bridge.c.

References ao2_cleanup, ast_answer(), ast_assert, ast_bridge_channel_queue_playfile(), ast_bridge_features_destroy(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_bridge_lock_both, ast_bridge_unlock, ast_channel_get_bridge(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_channel_yank(), ast_hangup(), ast_log, AST_STATE_UP, ast_strlen_zero, bridge_dissolve_check_stolen(), bridge_find_channel(), bridge_move_locked(), LOG_WARNING, NULL, and RAII_VAR.

Referenced by action_bridge(), bridge_exec(), and manager_park_unbridged().

02293 {
02294    RAII_VAR(struct ast_bridge *, chan_bridge, NULL, ao2_cleanup);
02295    RAII_VAR(struct ast_channel *, yanked_chan, NULL, ao2_cleanup);
02296 
02297    ast_channel_lock(chan);
02298    chan_bridge = ast_channel_get_bridge(chan);
02299    ast_channel_unlock(chan);
02300 
02301    if (chan_bridge) {
02302       struct ast_bridge_channel *bridge_channel;
02303 
02304       ast_bridge_lock_both(bridge, chan_bridge);
02305       bridge_channel = bridge_find_channel(chan_bridge, chan);
02306 
02307       if (bridge_move_locked(bridge, chan_bridge, chan, NULL, 1)) {
02308          ast_bridge_unlock(chan_bridge);
02309          ast_bridge_unlock(bridge);
02310          return -1;
02311       }
02312 
02313       /*
02314        * bridge_move_locked() will implicitly ensure that
02315        * bridge_channel is not NULL.
02316        */
02317       ast_assert(bridge_channel != NULL);
02318 
02319       /*
02320        * Additional checks if the channel we just stole dissolves the
02321        * original bridge.
02322        */
02323       bridge_dissolve_check_stolen(chan_bridge, bridge_channel);
02324       ast_bridge_unlock(chan_bridge);
02325       ast_bridge_unlock(bridge);
02326 
02327       /* The channel was in a bridge so it is not getting any new features. */
02328       ast_bridge_features_destroy(features);
02329    } else {
02330       /* Slightly less easy case. We need to yank channel A from
02331        * where he currently is and impart him into our bridge.
02332        */
02333       yanked_chan = ast_channel_yank(chan);
02334       if (!yanked_chan) {
02335          ast_log(LOG_WARNING, "Could not gain control of channel %s\n", ast_channel_name(chan));
02336          return -1;
02337       }
02338       if (ast_channel_state(yanked_chan) != AST_STATE_UP) {
02339          ast_answer(yanked_chan);
02340       }
02341       ast_channel_ref(yanked_chan);
02342       if (ast_bridge_impart(bridge, yanked_chan, NULL, features,
02343          AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
02344          /* It is possible for us to yank a channel and have some other
02345           * thread start a PBX on the channl after we yanked it. In particular,
02346           * this can theoretically happen on the ;2 of a Local channel if we
02347           * yank it prior to the ;1 being answered. Make sure that it isn't
02348           * executing a PBX before hanging it up.
02349           */
02350          if (ast_channel_pbx(yanked_chan)) {
02351             ast_channel_unref(yanked_chan);
02352          } else {
02353             ast_hangup(yanked_chan);
02354          }
02355          return -1;
02356       }
02357    }
02358 
02359    if (play_tone && !ast_strlen_zero(xfersound)) {
02360       struct ast_channel *play_chan = yanked_chan ?: chan;
02361       RAII_VAR(struct ast_bridge_channel *, play_bridge_channel, NULL, ao2_cleanup);
02362 
02363       ast_channel_lock(play_chan);
02364       play_bridge_channel = ast_channel_get_bridge_channel(play_chan);
02365       ast_channel_unlock(play_chan);
02366 
02367       if (!play_bridge_channel) {
02368          ast_log(LOG_WARNING, "Unable to play tone for channel %s. No longer in a bridge.\n",
02369             ast_channel_name(play_chan));
02370       } else {
02371          ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, xfersound, NULL);
02372       }
02373    }
02374    return 0;
02375 }

struct ast_bridge* ast_bridge_base_new ( uint32_t  capabilities,
unsigned int  flags,
const char *  creator,
const char *  name,
const char *  id 
) [read]

Create a new base class bridge.

Parameters:
capabilities The capabilities that we require to be used on the bridge
flags Flags that will alter the behavior of the bridge
creator Entity that created the bridge (optional)
name Name given to the bridge by its creator (optional, requires named creator)
id Unique ID given to the bridge by its creator (optional)
Return values:
a pointer to a new bridge on success
NULL on failure
Example usage:

This creates a no frills two party bridge that will be destroyed once one of the channels hangs up.

Definition at line 932 of file bridge.c.

References bridge_alloc(), bridge_base_init(), and bridge_register().

Referenced by AST_TEST_DEFINE(), get_wait_bridge_wrapper(), and join_conference_bridge().

00933 {
00934    void *bridge;
00935 
00936    bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_base_v_table);
00937    bridge = bridge_base_init(bridge, capabilities, flags, creator, name, id);
00938    bridge = bridge_register(bridge);
00939    return bridge;
00940 }

int ast_bridge_depart ( struct ast_channel chan  ) 

Depart a channel from a bridge.

Parameters:
chan Channel to depart
Note:
chan is locked by this function.
Return values:
0 on success
-1 on failure
Example usage:

This removes the channel pointed to by the chan pointer from any bridge it may be in and gives control to the calling thread. This does not hang up the channel.

Note:
This API call can only be used on channels that were added to the bridge using the ast_bridge_impart API call with the AST_BRIDGE_IMPART_CHAN_DEPARTABLE flag.

Definition at line 1727 of file bridge.c.

References ao2_ref, ast_assert, ast_bridge_channel_leave_bridge(), AST_CAUSE_NORMAL_CLEARING, ast_channel_internal_bridge_channel(), ast_channel_internal_bridge_channel_set(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_log, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, ast_bridge_channel::chan, ast_bridge_channel::depart_wait, LOG_ERROR, NULL, and ast_bridge_channel::thread.

Referenced by app_control_continue(), app_control_remove_channel_from_bridge(), AST_TEST_DEFINE(), bridge_channel_depart(), conf_announce_channel_depart(), control_add_channel_to_bridge(), and stasis_app_exec().

01728 {
01729    struct ast_bridge_channel *bridge_channel;
01730    int departable;
01731 
01732    ast_channel_lock(chan);
01733    bridge_channel = ast_channel_internal_bridge_channel(chan);
01734    departable = bridge_channel && bridge_channel->depart_wait;
01735    ast_channel_unlock(chan);
01736    if (!departable) {
01737       ast_log(LOG_ERROR, "Channel %s cannot be departed.\n",
01738          ast_channel_name(chan));
01739       /*
01740        * Should never happen.  It likely means that
01741        * ast_bridge_depart() is called by two threads for the same
01742        * channel, the channel was never imparted to be departed, or it
01743        * has already been departed.
01744        */
01745       ast_assert(0);
01746       return -1;
01747    }
01748 
01749    /*
01750     * We are claiming the bridge_channel reference held by
01751     * bridge_channel_depart_thread().
01752     */
01753 
01754    ast_bridge_channel_leave_bridge(bridge_channel,
01755       BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
01756 
01757    /* Wait for the depart thread to die */
01758    ast_debug(1, "Waiting for %p(%s) bridge thread to die.\n",
01759       bridge_channel, ast_channel_name(bridge_channel->chan));
01760    pthread_join(bridge_channel->thread, NULL);
01761 
01762    ast_channel_lock(chan);
01763    ast_channel_internal_bridge_channel_set(chan, NULL);
01764    ast_channel_unlock(chan);
01765 
01766    /* We can get rid of the bridge_channel after the depart thread has died. */
01767    ao2_ref(bridge_channel, -1);
01768    return 0;
01769 }

int ast_bridge_destroy ( struct ast_bridge bridge,
int  cause 
)

Destroy a bridge.

Parameters:
bridge Bridge to destroy
cause Cause of bridge being destroyed. (If cause <= 0 then use AST_CAUSE_NORMAL_CLEARING)
Return values:
0 on success
-1 on failure
Example usage:

This destroys a bridge that was previously created.

Note:
While this function will kick all channels out of the bridge, channels that were added to the bridge using ast_bridge_impart() with the flag AST_BRIDGE_IMPART_CHAN_DEPARTABLE set must have ast_bridge_depart() called on them.

Definition at line 942 of file bridge.c.

References ao2_ref, ast_bridge_lock, ast_bridge_unlock, ast_debug, bridge_dissolve(), and ast_bridge::uniqueid.

Referenced by action_bridge(), agent_connect_caller(), agent_logout(), agent_pvt_destructor(), agent_request_exec(), agent_run(), ast_bridge_call_with_flags(), attended_transfer_properties_shutdown(), bridge_exec(), bridge_register(), caller_abort_agent(), destroy_conference_bridge(), fail_enter(), manager_bridge_destroy(), parked_call_app_exec(), parking_lot_destructor(), safe_bridge_destroy(), stasis_app_bridge_create(), stasis_app_bridge_destroy(), unload_module(), wait_bridge_wrapper_alloc(), and wait_bridge_wrapper_destructor().

00943 {
00944    ast_debug(1, "Bridge %s: telling all channels to leave the party\n", bridge->uniqueid);
00945    ast_bridge_lock(bridge);
00946    bridge_dissolve(bridge, cause);
00947    ast_bridge_unlock(bridge);
00948 
00949    ao2_ref(bridge, -1);
00950 
00951    return 0;
00952 }

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.

Parameters:
features Bridge features structure
dtmf DTMF string to be activated upon
callback Function to execute upon activation
hook_pvt Unique data
destructor Optional destructor callback for hook_pvt data
remove_flags Dictates what situations the hook should be removed.
Return values:
0 on success
-1 on failure (The caller must cleanup any hook_pvt resources.)
Example usage:

 struct ast_bridge_features features;
 ast_bridge_features_init(&features);
 ast_bridge_dtmf_hook(&features, "#", pound_callback, NULL, NULL, 0);

This makes the bridging core call pound_callback if a channel that has this feature structure inputs the DTMF string '#'. A pointer to useful data may be provided to the hook_pvt parameter.

Definition at line 3014 of file bridge.c.

References ao2_link, ao2_ref, AST_BRIDGE_HOOK_TYPE_DTMF, ast_copy_string(), bridge_hook_generic(), ast_bridge_hook_dtmf_parms::code, ast_bridge_hook::destructor, ast_bridge_hook_dtmf::dtmf, ast_bridge_features::dtmf_hooks, ast_bridge_hook_dtmf::generic, NULL, and ast_bridge_hook::type.

Referenced by apply_menu_to_user(), ast_bridge_features_enable(), AST_TEST_DEFINE(), bridge_agent_hold_push(), bridge_personality_atxfer_push(), and dynamic_dtmf_hook_add().

03020 {
03021    struct ast_bridge_hook_dtmf *hook;
03022    int res;
03023 
03024    /* Allocate new hook and setup it's various variables */
03025    hook = (struct ast_bridge_hook_dtmf *) bridge_hook_generic(sizeof(*hook), callback,
03026       hook_pvt, destructor, remove_flags);
03027    if (!hook) {
03028       return -1;
03029    }
03030    hook->generic.type = AST_BRIDGE_HOOK_TYPE_DTMF;
03031    ast_copy_string(hook->dtmf.code, dtmf, sizeof(hook->dtmf.code));
03032 
03033    /* Once done we put it in the container. */
03034    res = ao2_link(features->dtmf_hooks, hook) ? 0 : -1;
03035    if (res) {
03036       /*
03037        * Could not link the hook into the container.
03038        *
03039        * Remove the hook_pvt destructor call from the hook since we
03040        * are returning failure to install the hook.
03041        */
03042       hook->generic.destructor = NULL;
03043    }
03044    ao2_ref(hook, -1);
03045 
03046    return res;
03047 }

void ast_bridge_features_cleanup ( struct ast_bridge_features features  ) 

Clean up the contents of a bridge features structure.

Parameters:
features Bridge features structure
Returns:
Nothing
Example usage:

This cleans up the feature structure 'features'.

Note:
This MUST be called after the features structure is done being used or a memory leak may occur.

Definition at line 3488 of file bridge.c.

References ao2_cleanup, ao2_ref, ast_heap_destroy(), ast_heap_pop(), ast_bridge_features::dtmf_hooks, ast_bridge_features::interval_hooks, NULL, and ast_bridge_features::other_hooks.

Referenced by agent_request_exec(), agent_run(), ast_bridge_call_with_flags(), ast_bridge_features_destroy(), AST_TEST_DEFINE(), bridge_exec(), bridgewait_exec(), channel_feature_hooks_set_full(), confbridge_exec(), park_and_announce_app_exec(), park_app_exec(), and parked_call_app_exec().

03489 {
03490    struct ast_bridge_hook_timer *hook;
03491 
03492    /* Destroy the interval hooks heap. */
03493    if (features->interval_hooks) {
03494       while ((hook = ast_heap_pop(features->interval_hooks))) {
03495          ao2_ref(hook, -1);
03496       }
03497       features->interval_hooks = ast_heap_destroy(features->interval_hooks);
03498    }
03499 
03500    /* Destroy the miscellaneous other hooks container. */
03501    ao2_cleanup(features->other_hooks);
03502    features->other_hooks = NULL;
03503 
03504    /* Destroy the DTMF hooks container. */
03505    ao2_cleanup(features->dtmf_hooks);
03506    features->dtmf_hooks = NULL;
03507 }

void ast_bridge_features_destroy ( struct ast_bridge_features features  ) 

Destroy an allocated bridge features struct.

Since:
12.0.0
Parameters:
features Bridge features structure
Example usage:

 struct ast_bridge_features *features;
 features = ast_bridge_features_new();
 ast_bridge_features_destroy(features);

Returns:
Nothing

Definition at line 3509 of file bridge.c.

References ast_bridge_features_cleanup(), and ast_free.

Referenced by ast_bridge_add_channel(), ast_bridge_call_with_flags(), ast_bridge_features_new(), ast_bridge_impart(), ast_local_setup_bridge(), ast_unreal_channel_push_to_bridge(), bridge_channel_depart_thread(), bridge_channel_ind_thread(), bridge_exec(), conf_announce_channel_push(), conf_start_record(), features_destroy(), and local_pvt_destructor().

03510 {
03511    if (!features) {
03512       return;
03513    }
03514    ast_bridge_features_cleanup(features);
03515    ast_free(features);
03516 }

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.

Parameters:
feature The feature to invoke
bridge_channel Channel executing the feature
hook_pvt Private data passed in when the hook was created
Note:
This API call is only meant to be used by bridge subclasses and hook callbacks to request a builtin feature hook to be executed.
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_features_do(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, bridge_channel, hook_pvt);

Definition at line 2920 of file bridge.c.

References ARRAY_LEN.

Referenced by agent_connect_caller().

02921 {
02922    ast_bridge_hook_callback callback;
02923 
02924    if (ARRAY_LEN(builtin_features_handlers) <= feature) {
02925       return -1;
02926    }
02927 
02928    callback = builtin_features_handlers[feature];
02929    if (!callback) {
02930       return -1;
02931    }
02932    callback(bridge_channel, hook_pvt);
02933 
02934    return 0;
02935 }

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.

Parameters:
features Bridge features structure
feature Feature to enable
dtmf Optionally the DTMF stream to trigger the feature, if not specified it will be the default
config Configuration structure unique to the built in type
destructor Optional destructor callback for config data
remove_flags Dictates what situations the hook should be removed.
Return values:
0 on success
-1 on failure
Example usage:

This enables the attended transfer DTMF option using the default DTMF string. An alternate string may be provided using the dtmf parameter. Internally this is simply setting up a hook to a built in feature callback function.

Definition at line 3197 of file bridge.c.

References ARRAY_LEN, ast_bridge_dtmf_hook(), ast_debug, and ast_strlen_zero.

Referenced by builtin_features_helper().

03203 {
03204    if (ARRAY_LEN(builtin_features_handlers) <= feature
03205       || !builtin_features_handlers[feature]) {
03206       return -1;
03207    }
03208 
03209    /* If no alternate DTMF stream was provided use the default one */
03210    if (ast_strlen_zero(dtmf)) {
03211       dtmf = builtin_features_dtmf[feature];
03212       /* If no DTMF is still available (ie: it has been disabled) then error out now */
03213       if (ast_strlen_zero(dtmf)) {
03214          ast_debug(1, "Failed to enable built in feature %u on %p, no DTMF string is available for it.\n",
03215             feature, features);
03216          return -1;
03217       }
03218    }
03219 
03220    /*
03221     * The rest is basically pretty easy.  We create another hook
03222     * using the built in feature's DTMF callback.  Easy as pie.
03223     */
03224    return ast_bridge_dtmf_hook(features, dtmf, builtin_features_handlers[feature],
03225       config, destructor, remove_flags);
03226 }

int ast_bridge_features_init ( struct ast_bridge_features features  ) 

Initialize bridge features structure.

Parameters:
features Bridge featues structure
Return values:
0 on success
-1 on failure
Example usage:

 struct ast_bridge_features features;
 ast_bridge_features_init(&features);

This initializes the feature structure 'features' to have nothing enabled.

Note:
This MUST be called before enabling features or flags. Failure to do so may result in a crash.

Definition at line 3456 of file bridge.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_list, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ast_heap_create(), bridge_dtmf_hook_sort(), ast_bridge_features::dtmf_hooks, ast_bridge_features::dtmf_passthrough, interval_hook_time_cmp(), ast_bridge_features::interval_hooks, NULL, ast_bridge_features::other_hooks, and timer.

Referenced by agent_request_exec(), agent_run(), ast_bridge_call_with_flags(), ast_bridge_features_new(), AST_TEST_DEFINE(), bridge_exec(), bridgewait_exec(), channel_feature_hooks_set_full(), confbridge_exec(), park_and_announce_app_exec(), park_app_exec(), and parked_call_app_exec().

03457 {
03458    /* Zero out the structure */
03459    memset(features, 0, sizeof(*features));
03460 
03461    /* Initialize the DTMF hooks container */
03462    features->dtmf_hooks = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX,
03463       AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, bridge_dtmf_hook_sort, NULL);
03464    if (!features->dtmf_hooks) {
03465       return -1;
03466    }
03467 
03468    /* Initialize the miscellaneous other hooks container */
03469    features->other_hooks = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL,
03470       NULL);
03471    if (!features->other_hooks) {
03472       return -1;
03473    }
03474 
03475    /* Initialize the interval hooks heap */
03476    features->interval_hooks = ast_heap_create(8, interval_hook_time_cmp,
03477       offsetof(struct ast_bridge_hook_timer, timer.heap_index));
03478    if (!features->interval_hooks) {
03479       return -1;
03480    }
03481 
03482    features->dtmf_passthrough = 1;
03483 
03484    return 0;
03485 }

int ast_bridge_features_limits_construct ( struct ast_bridge_features_limits limits  ) 

Constructor function for ast_bridge_features_limits.

Parameters:
limits pointer to a ast_bridge_features_limits struct that has been allocted, but not initialized
Return values:
0 on success
-1 on failure

Definition at line 3228 of file bridge.c.

References ast_string_field_init.

Referenced by bridge_builtin_set_limits(), and pre_bridge_setup().

03229 {
03230    memset(limits, 0, sizeof(*limits));
03231 
03232    if (ast_string_field_init(limits, 256)) {
03233       return -1;
03234    }
03235 
03236    return 0;
03237 }

void ast_bridge_features_limits_destroy ( struct ast_bridge_features_limits limits  ) 

Destructor function for ast_bridge_features_limits.

Parameters:
limits pointer to an ast_bridge_features_limits struct that needs to be destroyed
This function does not free memory allocated to the ast_bridge_features_limits struct, it only frees elements within the struct. You must still call ast_free on the the struct if you allocated it with malloc.

Definition at line 3239 of file bridge.c.

References ast_string_field_free_memory.

Referenced by bridge_features_limits_dtor(), and pre_bridge_setup().

03240 {
03241    ast_string_field_free_memory(limits);
03242 }

void ast_bridge_features_merge ( struct ast_bridge_features into,
const struct ast_bridge_features from 
)

Merge one ast_bridge_features into another.

Parameters:
into The ast_bridge_features that will be merged into
from The ast_bridge_features that will be merged from

Definition at line 3431 of file bridge.c.

References ao2_callback, ast_heap_peek(), ast_heap_unlock, ast_heap_wrlock, ast_bridge_features::dtmf_hooks, ast_bridge_features::dtmf_passthrough, ast_bridge_features::feature_flags, ast_flags::flags, ast_bridge_features::interval_hooks, merge_container_cb(), ast_bridge_features::mute, ast_bridge_features::other_hooks, ast_bridge_features::usable, and wrap_hook().

Referenced by bridge_channel_internal_join(), and channel_feature_hooks_set_full().

03432 {
03433    struct ast_bridge_hook_timer *hook;
03434    int idx;
03435 
03436    /* Merge hook containers */
03437    ao2_callback(from->dtmf_hooks, 0, merge_container_cb, into->dtmf_hooks);
03438    ao2_callback(from->other_hooks, 0, merge_container_cb, into->other_hooks);
03439 
03440    /* Merge hook heaps */
03441    ast_heap_wrlock(from->interval_hooks);
03442    for (idx = 1; (hook = ast_heap_peek(from->interval_hooks, idx)); idx++) {
03443       wrap_hook(into, hook);
03444    }
03445    ast_heap_unlock(from->interval_hooks);
03446 
03447    /* Merge feature flags */
03448    into->feature_flags.flags |= from->feature_flags.flags;
03449    into->usable |= from->usable;
03450 
03451    into->mute |= from->mute;
03452    into->dtmf_passthrough |= from->dtmf_passthrough;
03453 }

struct ast_bridge_features* ast_bridge_features_new ( void   )  [read]

Allocate a new bridge features struct.

Since:
12.0.0
Example usage:

 struct ast_bridge_features *features;
 features = ast_bridge_features_new();
 ast_bridge_features_destroy(features);

Return values:
features New allocated features struct.
NULL on error.

Definition at line 3518 of file bridge.c.

References ast_bridge_features_destroy(), ast_bridge_features_init(), ast_malloc, and NULL.

Referenced by ast_bridge_call_with_flags(), ast_bridge_impart(), ast_unreal_channel_push_to_bridge(), bridge_exec(), channel_feature_hooks_set_full(), conf_announce_channel_push(), and conf_start_record().

03519 {
03520    struct ast_bridge_features *features;
03521 
03522    features = ast_malloc(sizeof(*features));
03523    if (features) {
03524       if (ast_bridge_features_init(features)) {
03525          ast_bridge_features_destroy(features);
03526          features = NULL;
03527       }
03528    }
03529 
03530    return features;
03531 }

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.

Parameters:
feature The feature that the handler will be responsible for
callback The callback function that will handle it
dtmf Default DTMF string used to activate the feature
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, bridge_builtin_attended_transfer, "*1");

This registers the function bridge_builtin_attended_transfer as the function responsible for the built in attended transfer feature.

Definition at line 2892 of file bridge.c.

References ARRAY_LEN, ast_copy_string(), and ast_strlen_zero.

Referenced by ast_bridging_init_basic(), load_module(), and load_parking_bridge_features().

02893 {
02894    if (ARRAY_LEN(builtin_features_handlers) <= feature
02895       || builtin_features_handlers[feature]) {
02896       return -1;
02897    }
02898 
02899    if (!ast_strlen_zero(dtmf)) {
02900       ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature]));
02901    }
02902 
02903    builtin_features_handlers[feature] = callback;
02904 
02905    return 0;
02906 }

void ast_bridge_features_remove ( struct ast_bridge_features features,
enum ast_bridge_hook_remove_flags  flags 
)

Remove marked bridge channel feature hooks.

Since:
12.0.0
Parameters:
features Bridge features structure
flags Determinator for whether hook is removed.
Returns:
Nothing

Definition at line 3337 of file bridge.c.

References ast_bridge_features::dtmf_hooks, hooks_remove_container(), hooks_remove_heap(), ast_bridge_features::interval_hooks, and ast_bridge_features::other_hooks.

Referenced by bridge_base_pull(), bridge_channel_internal_join(), bridge_do_merge(), bridge_do_move(), and remove_hooks_on_personality_change().

03338 {
03339    hooks_remove_container(features->dtmf_hooks, remove_flags);
03340    hooks_remove_container(features->other_hooks, remove_flags);
03341    hooks_remove_heap(features->interval_hooks, remove_flags);
03342 }

void ast_bridge_features_set_flag ( struct ast_bridge_features features,
unsigned int  flag 
)

Set a flag on a bridge channel features structure.

Parameters:
features Bridge channel features structure
flag Flag to enable
Returns:
Nothing
Example usage:

This sets the AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP feature to be enabled on the features structure 'features'.

Definition at line 3259 of file bridge.c.

References ast_set_flag, ast_bridge_features::feature_flags, and ast_bridge_features::usable.

03260 {
03261    ast_set_flag(&features->feature_flags, flag);
03262    features->usable = 1;
03263 }

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 time runs out.

Parameters:
features Bridge features structure
limits Configured limits applicable to the channel
remove_flags Dictates what situations the hook should be removed.
Return values:
0 on success
-1 on failure
Example usage:

This sets the maximum time the channel can be in the bridge to 10 seconds and does not play any warnings.

Note:
This API call can only be used on a features structure that will be used in association with a bridge channel.

The ast_bridge_features_limits structure must remain accessible for the lifetime of the features structure.

Definition at line 3244 of file bridge.c.

References AST_BRIDGE_BUILTIN_INTERVAL_LIMITS, ast_log, and LOG_ERROR.

Referenced by pre_bridge_setup().

03247 {
03248    if (builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_LIMITS]) {
03249       ast_bridge_builtin_set_limits_fn callback;
03250 
03251       callback = builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_LIMITS];
03252       return callback(features, limits, remove_flags);
03253    }
03254 
03255    ast_log(LOG_ERROR, "Attempted to set limits without an AST_BRIDGE_BUILTIN_INTERVAL_LIMITS callback registered.\n");
03256    return -1;
03257 }

int ast_bridge_features_unregister ( enum ast_bridge_builtin_feature  feature  ) 

Unregister a handler for a built in feature.

Parameters:
feature The feature to unregister
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER);

This unregisters the function that is handling the built in attended transfer feature.

Definition at line 2908 of file bridge.c.

References ARRAY_LEN, and NULL.

Referenced by unload_module(), and unload_parking_bridge_features().

02909 {
02910    if (ARRAY_LEN(builtin_features_handlers) <= feature
02911       || !builtin_features_handlers[feature]) {
02912       return -1;
02913    }
02914 
02915    builtin_features_handlers[feature] = NULL;
02916 
02917    return 0;
02918 }

struct ast_bridge* ast_bridge_find_by_id ( const char *  bridge_id  )  [read]

Find bridge by id.

Since:
12.0.0
Parameters:
bridge_id Bridge identifier
Returns:
NULL bridge not found

non-NULL reference to bridge

Definition at line 4691 of file bridge.c.

References ao2_find, and OBJ_SEARCH_KEY.

Referenced by complete_bridge_participant(), handle_bridge_kick_channel(), manager_bridge_destroy(), and manager_bridge_kick().

04692 {
04693    return ao2_find(bridges, bridge_id, OBJ_SEARCH_KEY);
04694 }

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.

Parameters:
features Bridge features structure
callback Function to execute upon activation
hook_pvt Unique data
destructor Optional destructor callback for hook_pvt data
remove_flags Dictates what situations the hook should be removed.
Return values:
0 on success
-1 on failure (The caller must cleanup any hook_pvt resources.)
Example usage:

 struct ast_bridge_features features;
 ast_bridge_features_init(&features);
 ast_bridge_hangup_hook(&features, hangup_callback, NULL, NULL, 0);

This makes the bridging core call hangup_callback if a channel that has this hook hangs up. A pointer to useful data may be provided to the hook_pvt parameter.

Definition at line 3097 of file bridge.c.

References AST_BRIDGE_HOOK_TYPE_HANGUP, and bridge_other_hook().

Referenced by add_normal_hooks(), and bridge_personality_atxfer_push().

03102 {
03103    return bridge_other_hook(features, callback, hook_pvt, destructor, remove_flags,
03104       AST_BRIDGE_HOOK_TYPE_HANGUP);
03105 }

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).

Parameters:
bridge Bridge to impart on
chan Channel to impart (The channel reference is stolen if impart successful.)
swap Channel to swap out if swapping. NULL if not swapping.
features Bridge features structure.
flags defined by enum ast_bridge_impart_flags.
Note:
The features parameter must be NULL or obtained by ast_bridge_features_new(). You must not dereference features after calling even if the call fails.

chan is locked by this function.

Return values:
0 on success
-1 on failure (Caller still has ownership of chan)
Example usage:

This adds a channel pointed to by the chan pointer to the bridge pointed to by the bridge pointer. This function will return immediately and will not wait until the channel is no longer part of the bridge.

If this channel will be replacing another channel the other channel can be specified in the swap parameter. The other channel will be thrown out of the bridge in an atomic fashion.

If channel specific features are enabled, a pointer to the features structure can be specified in the features parameter.

Note:
If you impart a channel with AST_BRIDGE_IMPART_CHAN_DEPARTABLE you MUST ast_bridge_depart() the channel if this call succeeds. The bridge channel thread is created join-able. The implication is that the channel is special and will not behave like a normal channel.

If you impart a channel with AST_BRIDGE_IMPART_CHAN_INDEPENDENT you must not ast_bridge_depart() the channel. The bridge channel thread is created non-join-able. The channel must be treated as if it were placed into the bridge by ast_bridge_join(). Channels placed into a bridge by ast_bridge_join() are removed by a third party using ast_bridge_remove().

Definition at line 1637 of file bridge.c.

References ao2_ref, ao2_t_bump, ao2_t_cleanup, ast_bridge_features_destroy(), ast_bridge_features_new(), AST_BRIDGE_IMPART_CHAN_DEPARTABLE, AST_BRIDGE_IMPART_CHAN_INDEPENDENT, AST_BRIDGE_IMPART_CHAN_MASK, AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP, ast_bridge_lock, ast_bridge_unlock, ast_channel_flags(), ast_channel_internal_bridge_channel_set(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_unlock, AST_FLAG_ZOMBIE, ast_log, AST_LOG_NOTICE, AST_LOG_WARNING, ast_pthread_create, ast_pthread_create_detached, ast_read_threadstorage_callid(), ast_test_flag, bridge_channel_depart_thread(), bridge_channel_ind_thread(), bridge_channel_internal_alloc(), bridge_find_channel(), ast_bridge_channel::callid, ast_bridge_channel::chan, ast_bridge_channel::depart_wait, ast_bridge_channel::features, ast_bridge_channel::inhibit_colp, NULL, ast_bridge_methods::push_peek, ast_bridge_channel::swap, ast_bridge_channel::thread, ast_bridge::uniqueid, and ast_bridge::v_table.

Referenced by app_control_dial(), ast_bridge_add_channel(), ast_bridge_call_with_flags(), AST_TEST_DEFINE(), ast_unreal_channel_push_to_bridge(), attended_transfer_bridge(), blind_transfer_bridge(), conf_announce_channel_push(), conf_start_record(), control_add_channel_to_bridge(), feature_attended_transfer(), handle_invite_replaces(), local_call(), parking_blind_transfer_park(), recalling_exit(), refer_incoming_invite_request(), and retransfer_enter().

01642 {
01643    int res = 0;
01644    struct ast_bridge_channel *bridge_channel;
01645 
01646    /* Imparted channels cannot have a PBX. */
01647    if (ast_channel_pbx(chan)) {
01648       ast_log(AST_LOG_WARNING, "Channel %s has a PBX thread and cannot be imparted into bridge %s\n",
01649          ast_channel_name(chan), bridge->uniqueid);
01650       ast_bridge_features_destroy(features);
01651       return -1;
01652    }
01653 
01654    /* Supply an empty features structure if the caller did not. */
01655    if (!features) {
01656       features = ast_bridge_features_new();
01657       if (!features) {
01658          return -1;
01659       }
01660    }
01661 
01662    /* Try to allocate a structure for the bridge channel */
01663    bridge_channel = bridge_channel_internal_alloc(bridge);
01664    if (!bridge_channel) {
01665       ast_bridge_features_destroy(features);
01666       return -1;
01667    }
01668 
01669    ast_channel_lock(chan);
01670    if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)) {
01671       ast_log(AST_LOG_NOTICE, "Channel %s is a zombie and cannot be imparted into bridge %s\n",
01672          ast_channel_name(chan), bridge->uniqueid);
01673       res = -1;
01674    } else {
01675       ast_channel_internal_bridge_channel_set(chan, bridge_channel);
01676    }
01677    ast_channel_unlock(chan);
01678    bridge_channel->chan = chan;
01679    bridge_channel->swap = ao2_t_bump(swap, "Setting up bridge impart");
01680    bridge_channel->features = features;
01681    bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP);
01682    bridge_channel->depart_wait =
01683       (flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_DEPARTABLE;
01684    bridge_channel->callid = ast_read_threadstorage_callid();
01685 
01686    /* allow subclass to peek at swap channel before it can hangup */
01687    if (bridge->v_table->push_peek && !res) {
01688       struct ast_bridge_channel *bcswap = NULL;
01689 
01690       ast_bridge_lock(bridge);
01691       if (bridge_channel->swap) {
01692          bcswap = bridge_find_channel(bridge, bridge_channel->swap);
01693       }
01694       res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
01695       ast_bridge_unlock(bridge);
01696    }
01697 
01698    /* Actually create the thread that will handle the channel */
01699    if (!res) {
01700       if ((flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_INDEPENDENT) {
01701          res = ast_pthread_create_detached(&bridge_channel->thread, NULL,
01702             bridge_channel_ind_thread, bridge_channel);
01703       } else {
01704          res = ast_pthread_create(&bridge_channel->thread, NULL,
01705             bridge_channel_depart_thread, bridge_channel);
01706       }
01707    }
01708 
01709    if (res) {
01710       /* cleanup */
01711       ast_channel_lock(chan);
01712       ast_channel_internal_bridge_channel_set(chan, NULL);
01713       ast_channel_unlock(chan);
01714       bridge_channel->chan = NULL;
01715       ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Impart failed");
01716       bridge_channel->swap = NULL;
01717       ast_bridge_features_destroy(bridge_channel->features);
01718       bridge_channel->features = NULL;
01719 
01720       ao2_ref(bridge_channel, -1);
01721       return -1;
01722    }
01723 
01724    return 0;
01725 }

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.

Parameters:
features Bridge features structure
flags Interval timer callback option flags.
interval The interval that the hook should execute at in milliseconds
callback Function to execute upon activation
hook_pvt Unique data
destructor Optional destructor callback for hook_pvt data
remove_flags Dictates what situations the hook should be removed.
Return values:
0 on success
-1 on failure (The caller must cleanup any hook_pvt resources.)
 struct ast_bridge_features features;
 ast_bridge_features_init(&features);
 ast_bridge_interval_hook(&features, 1000, playback_callback, NULL, NULL, 0);

This makes the bridging core call playback_callback every second. A pointer to useful data may be provided to the hook_pvt parameter.

Definition at line 3151 of file bridge.c.

References ao2_ref, ast_atomic_fetchadd_int(), AST_BRIDGE_HOOK_TYPE_TIMER, ast_debug, ast_heap_push(), ast_heap_unlock, ast_heap_wrlock, ast_samp2tv(), ast_tvadd(), ast_tvnow(), bridge_hook_generic(), ast_bridge_hook::destructor, ast_bridge_hook_timer_parms::flags, ast_bridge_hook_timer::generic, ast_bridge_hook_timer_parms::interval, ast_bridge_features::interval_hooks, ast_bridge_features::interval_sequence, NULL, ast_bridge_hook_timer_parms::seqno, ast_bridge_hook_timer::timer, ast_bridge_hook_timer_parms::trip_time, and ast_bridge_hook::type.

Referenced by agent_request_exec(), apply_option_timeout(), AST_TEST_DEFINE(), bridge_agent_hold_push(), bridge_builtin_set_limits(), parking_set_duration(), and wrap_hook().

03158 {
03159    struct ast_bridge_hook_timer *hook;
03160    int res;
03161 
03162    if (!features ||!interval || !callback) {
03163       return -1;
03164    }
03165 
03166    /* Allocate new hook and setup it's various variables */
03167    hook = (struct ast_bridge_hook_timer *) bridge_hook_generic(sizeof(*hook), callback,
03168       hook_pvt, destructor, remove_flags);
03169    if (!hook) {
03170       return -1;
03171    }
03172    hook->generic.type = AST_BRIDGE_HOOK_TYPE_TIMER;
03173    hook->timer.interval = interval;
03174    hook->timer.trip_time = ast_tvadd(ast_tvnow(), ast_samp2tv(interval, 1000));
03175    hook->timer.seqno = ast_atomic_fetchadd_int((int *) &features->interval_sequence, +1);
03176    hook->timer.flags = flags;
03177 
03178    ast_debug(1, "Putting interval hook %p with interval %u in the heap on features %p\n",
03179       hook, hook->timer.interval, features);
03180    ast_heap_wrlock(features->interval_hooks);
03181    res = ast_heap_push(features->interval_hooks, hook);
03182    ast_heap_unlock(features->interval_hooks);
03183    if (res) {
03184       /*
03185        * Could not push the hook into the heap
03186        *
03187        * Remove the hook_pvt destructor call from the hook since we
03188        * are returning failure to install the hook.
03189        */
03190       hook->generic.destructor = NULL;
03191       ao2_ref(hook, -1);
03192    }
03193 
03194    return res ? -1 : 0;
03195 }

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.

Parameters:
interval The interval feature that the handler will be responsible for
callback the Callback function that will handle it
Return values:
0 on success
-1 on failure
Example usage:

This registers the function bridge_builtin_set_limits as the function responsible for the built in duration limit feature.

Definition at line 2937 of file bridge.c.

References ARRAY_LEN.

Referenced by load_module().

02938 {
02939    if (ARRAY_LEN(builtin_interval_handlers) <= interval
02940       || builtin_interval_handlers[interval]) {
02941       return -1;
02942    }
02943 
02944    builtin_interval_handlers[interval] = callback;
02945 
02946    return 0;
02947 }

int ast_bridge_interval_unregister ( enum ast_bridge_builtin_interval  interval  ) 

Definition at line 2949 of file bridge.c.

References ARRAY_LEN, and NULL.

Referenced by unload_module().

02950 {
02951    if (ARRAY_LEN(builtin_interval_handlers) <= interval
02952       || !builtin_interval_handlers[interval]) {
02953       return -1;
02954    }
02955 
02956    builtin_interval_handlers[interval] = NULL;
02957 
02958    return 0;
02959 
02960 }

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.

Return values:
0 Not a current video source of the bridge.
None 0, is a video source of the bridge, The number returned represents the priority this video stream has on the bridge where 1 is the highest priority.

Definition at line 3655 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, ast_bridge::softmix, ast_bridge_video_mode::talker_src_data, and ast_bridge_softmix::video_mode.

Referenced by handle_video_on_exit(), handle_video_on_join(), softmix_bridge_write_video(), and softmix_pass_video_top_priority().

03656 {
03657    int res = 0;
03658 
03659    ast_bridge_lock(bridge);
03660    switch (bridge->softmix.video_mode.mode) {
03661    case AST_BRIDGE_VIDEO_MODE_NONE:
03662       break;
03663    case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
03664       if (bridge->softmix.video_mode.mode_data.single_src_data.chan_vsrc == chan) {
03665          res = 1;
03666       }
03667       break;
03668    case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
03669       if (bridge->softmix.video_mode.mode_data.talker_src_data.chan_vsrc == chan) {
03670          res = 1;
03671       } else if (bridge->softmix.video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
03672          res = 2;
03673       }
03674 
03675    }
03676    ast_bridge_unlock(bridge);
03677    return res;
03678 }

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).

Parameters:
bridge Bridge to join
chan Channel to join
swap Channel to swap out if swapping (A channel reference is stolen.)
features Bridge features structure
tech_args Optional Bridging tech optimization parameters for this channel.
flags defined by enum ast_bridge_join_flags.
Note:
The passed in swap channel is always unreffed on return. It is not a good idea to access the swap channel on return or for the caller to keep a reference to it.

Absolutely _NO_ locks should be held before calling this function since it blocks.

Return values:
0 if the channel successfully joined the bridge before it exited.
-1 if the channel failed to join the bridge
Example usage:

This adds a channel pointed to by the chan pointer to the bridge pointed to by the bridge pointer. This function will not return until the channel has been removed from the bridge, swapped out for another channel, or has hung up.

If this channel will be replacing another channel the other channel can be specified in the swap parameter. The other channel will be thrown out of the bridge in an atomic fashion.

If channel specific features are enabled a pointer to the features structure can be specified in the features parameter.

Definition at line 1495 of file bridge.c.

References ao2_ref, ao2_t_cleanup, ast_assert, AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP, AST_BRIDGE_JOIN_PASS_REFERENCE, ast_bridge_lock, ast_bridge_run_after_callback(), ast_bridge_setup_after_goto(), ast_bridge_unlock, ast_channel_flags(), ast_channel_internal_bridge_channel_set(), ast_channel_lock, ast_channel_softhangup_internal_flag(), ast_channel_unlock, AST_FLAG_ZOMBIE, AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_test_flag, bridge_channel_internal_alloc(), bridge_channel_internal_join(), bridge_find_channel(), ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_channel::inhibit_colp, NULL, ast_bridge_methods::push_peek, ast_bridge_channel::swap, ast_bridge_channel::tech_args, ast_bridge_channel::thread, and ast_bridge::v_table.

Referenced by agent_request_exec(), agent_run(), ast_bridge_call_with_flags(), bridge_exec(), bridgewait_exec(), confbridge_exec(), park_and_announce_app_exec(), park_app_exec(), and parked_call_app_exec().

01501 {
01502    struct ast_bridge_channel *bridge_channel;
01503    int res = 0;
01504 
01505    bridge_channel = bridge_channel_internal_alloc(bridge);
01506    if (flags & AST_BRIDGE_JOIN_PASS_REFERENCE) {
01507       ao2_ref(bridge, -1);
01508    }
01509    if (!bridge_channel) {
01510       ao2_t_cleanup(swap, "Error exit: bridge_channel alloc failed");
01511       res = -1;
01512       goto join_exit;
01513    }
01514 /* 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. */
01515    ast_assert(features != NULL);
01516    if (!features) {
01517       ao2_ref(bridge_channel, -1);
01518       ao2_t_cleanup(swap, "Error exit: features is NULL");
01519       res = -1;
01520       goto join_exit;
01521    }
01522    if (tech_args) {
01523       bridge_channel->tech_args = *tech_args;
01524    }
01525 
01526    ast_channel_lock(chan);
01527    if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)) {
01528       res = -1;
01529    } else {
01530       ast_channel_internal_bridge_channel_set(chan, bridge_channel);
01531    }
01532    ast_channel_unlock(chan);
01533    bridge_channel->thread = pthread_self();
01534    bridge_channel->chan = chan;
01535    bridge_channel->swap = swap;
01536    bridge_channel->features = features;
01537    bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP);
01538 
01539    /* allow subclass to peek at upcoming push operation */
01540    if (bridge->v_table->push_peek && !res) {
01541       struct ast_bridge_channel *bcswap = NULL;
01542 
01543       ast_bridge_lock(bridge);
01544       if (bridge_channel->swap) {
01545          bcswap = bridge_find_channel(bridge, bridge_channel->swap);
01546       }
01547       res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
01548       ast_bridge_unlock(bridge);
01549    }
01550 
01551    if (!res) {
01552       res = bridge_channel_internal_join(bridge_channel);
01553    }
01554 
01555    /* Cleanup all the data in the bridge channel after it leaves the bridge. */
01556    ast_channel_lock(chan);
01557    ast_channel_internal_bridge_channel_set(chan, NULL);
01558    ast_channel_unlock(chan);
01559    bridge_channel->chan = NULL;
01560    /* If bridge_channel->swap is not NULL then the join failed. */
01561    ao2_t_cleanup(bridge_channel->swap, "Bridge complete: join failed");
01562    bridge_channel->swap = NULL;
01563    bridge_channel->features = NULL;
01564 
01565    ao2_ref(bridge_channel, -1);
01566 
01567 join_exit:;
01568    ast_bridge_run_after_callback(chan);
01569    if (!(ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO)
01570       && !ast_bridge_setup_after_goto(chan)) {
01571       /* Claim the after bridge goto is an async goto destination. */
01572       ast_channel_lock(chan);
01573       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
01574       ast_channel_unlock(chan);
01575    }
01576    return res;
01577 }

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 
)

Unregisters a handler for a built in interval feature.

Parameters:
interval the interval feature to unregister
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_interval_unregister(AST_BRIDGE_BULTIN_INTERVAL_LIMITS)
 /endcode

 This unregisters the function that is handling the built in duration limit feature.
 */
int ast_bridge_interval_unregister(enum ast_bridge_builtin_interval interval);

/*!
 \brief Attach a bridge channel join hook to a bridge features structure

 \param features Bridge features structure
 \param callback Function to execute upon activation
 \param hook_pvt Unique data
 \param destructor Optional destructor callback for hook_pvt data
 \param remove_flags Dictates what situations the hook should be removed.

 \retval 0 on success
 \retval -1 on failure (The caller must cleanup any hook_pvt resources.)

 Example usage:

 \code
 struct ast_bridge_features features;
 ast_bridge_features_init(&features);
 ast_bridge_join_hook(&features, join_callback, NULL, NULL, 0);

This makes the bridging core call join_callback when a channel successfully joins the bridging system. A pointer to useful data may be provided to the hook_pvt parameter.

Definition at line 3107 of file bridge.c.

References AST_BRIDGE_HOOK_TYPE_JOIN, and bridge_other_hook().

Referenced by agent_request_exec().

03112 {
03113    return bridge_other_hook(features, callback, hook_pvt, destructor, remove_flags,
03114       AST_BRIDGE_HOOK_TYPE_JOIN);
03115 }

int ast_bridge_kick ( struct ast_bridge bridge,
struct ast_channel chan 
)

Kick a channel from a bridge.

Parameters:
bridge Bridge that the channel is to be kicked from
chan Channel to kick
Return values:
0 on success
-1 on failure
Example usage:

This kicks the channel pointed to by the chan pointer from the bridge pointed to by the bridge pointer and requests that it be hung up. Control over the channel will NOT be given to the calling thread.

Note:
The functional difference between ast_bridge_kick() and ast_bridge_remove() is that the bridge may dissolve as a result of the channel being kicked.

This API call can be used on channels that were added to the bridge using both ast_bridge_join and ast_bridge_impart.

Definition at line 1796 of file bridge.c.

References ast_bridge_channel_queue_callback(), ast_bridge_lock, ast_bridge_unlock, bridge_find_channel(), kick_it(), and NULL.

Referenced by handle_bridge_kick_channel(), and manager_bridge_kick().

01797 {
01798    struct ast_bridge_channel *bridge_channel;
01799    int res;
01800 
01801    ast_bridge_lock(bridge);
01802 
01803    /* Try to find the channel that we want to kick. */
01804    if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
01805       ast_bridge_unlock(bridge);
01806       return -1;
01807    }
01808 
01809    res = ast_bridge_channel_queue_callback(bridge_channel, 0, kick_it, NULL, 0);
01810 
01811    ast_bridge_unlock(bridge);
01812 
01813    return res;
01814 }

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.

Parameters:
features Bridge features structure
callback Function to execute upon activation
hook_pvt Unique data
destructor Optional destructor callback for hook_pvt data
remove_flags Dictates what situations the hook should be removed.
Return values:
0 on success
-1 on failure (The caller must cleanup any hook_pvt resources.)
Example usage:

 struct ast_bridge_features features;
 ast_bridge_features_init(&features);
 ast_bridge_leave_hook(&features, leave_callback, NULL, NULL, 0);

This makes the bridging core call leave_callback when a channel successfully leaves the bridging system. A pointer to useful data may be provided to the hook_pvt parameter.

Definition at line 3117 of file bridge.c.

References AST_BRIDGE_HOOK_TYPE_LEAVE, and bridge_other_hook().

03122 {
03123    return bridge_other_hook(features, callback, hook_pvt, destructor, remove_flags,
03124       AST_BRIDGE_HOOK_TYPE_LEAVE);
03125 }

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.

Parameters:
dst_bridge Destination bridge of merge.
src_bridge Source bridge of merge.
merge_best_direction TRUE if don't care about which bridge merges into the other.
kick_me Array of channels to kick from the bridges.
num_kick Number of channels in the kick_me array.
Note:
Absolutely _NO_ bridge or channel locks should be held before calling this function.
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_merge(dst_bridge, src_bridge, 0, NULL, 0);

This moves the channels in src_bridge into the bridge pointed to by dst_bridge.

Definition at line 2119 of file bridge.c.

References ast_assert, ast_bridge_lock_both, ast_bridge_unlock, and bridge_merge_locked().

02120 {
02121    int res;
02122 
02123    /* Sanity check. */
02124    ast_assert(dst_bridge && src_bridge);
02125 
02126    ast_bridge_lock_both(dst_bridge, src_bridge);
02127    res = bridge_merge_locked(dst_bridge, src_bridge, merge_best_direction, kick_me, num_kick);
02128    ast_bridge_unlock(src_bridge);
02129    ast_bridge_unlock(dst_bridge);
02130    return res;
02131 }

void ast_bridge_merge_inhibit ( struct ast_bridge bridge,
int  request 
)

Adjust the bridge merge inhibit request count.

Since:
12.0.0
Parameters:
bridge What to operate on.
request Inhibit request increment. (Positive to add requests. Negative to remove requests.)
Returns:
Nothing

Definition at line 2830 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, and bridge_merge_inhibit_nolock().

Referenced by attended_transfer_properties_shutdown(), consulting_exit(), and feature_attended_transfer().

02831 {
02832    ast_bridge_lock(bridge);
02833    bridge_merge_inhibit_nolock(bridge, request);
02834    ast_bridge_unlock(bridge);
02835 }

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.

Since:
12.0.0
Parameters:
dst_bridge Destination bridge of bridge channel move.
src_bridge Source bridge of bridge channel move.
chan Channel to move.
swap Channel to replace in dst_bridge.
attempt_recovery TRUE if failure attempts to push channel back into original bridge.
Note:
Absolutely _NO_ bridge or channel locks should be held before calling this function.
Return values:
0 on success.
-1 on failure.

Definition at line 2280 of file bridge.c.

References ast_bridge_lock_both, ast_bridge_unlock, and bridge_move_locked().

Referenced by agent_connect_caller(), parked_call_app_exec(), and parking_park_bridge_channel().

02281 {
02282    int res;
02283 
02284    ast_bridge_lock_both(dst_bridge, src_bridge);
02285    res = bridge_move_locked(dst_bridge, src_bridge, chan, swap, attempt_recovery);
02286    ast_bridge_unlock(src_bridge);
02287    ast_bridge_unlock(dst_bridge);
02288    return res;
02289 }

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.

Parameters:
features Bridge features structure
callback Function to execute upon activation
hook_pvt Unique data
destructor Optional destructor callback for hook_pvt data
remove_flags Dictates what situations the hook should be removed.
Return values:
0 on success
-1 on failure (The caller must cleanup any hook_pvt resources.)
Example usage:

 struct ast_bridge_features features;
 ast_bridge_features_init(&features);
 ast_bridge_move_hook(&features, move_callback, NULL, NULL, 0);

This makes the bridging core call callback when a channel is moved from one bridge to another. A pointer to useful data may be provided to the hook_pvt parameter.

Definition at line 3139 of file bridge.c.

References AST_BRIDGE_HOOK_TYPE_MOVE, bridge_other_hook(), and hook_cb().

Referenced by bridge_stasis_pull().

03144 {
03145    ast_bridge_hook_callback hook_cb = (ast_bridge_hook_callback) callback;
03146 
03147    return bridge_other_hook(features, hook_cb, hook_pvt, destructor, remove_flags,
03148       AST_BRIDGE_HOOK_TYPE_MOVE);
03149 }

void ast_bridge_notify_masquerade ( struct ast_channel chan  ) 

Notify bridging that this channel was just masqueraded.

Since:
12.0.0
Parameters:
chan Channel just involved in a masquerade
Returns:
Nothing

Definition at line 1454 of file bridge.c.

References ao2_ref, ast_bridge_channel_lock_bridge(), ast_bridge_unlock, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, ast_bridge_channel::bridge, bridge_find_channel(), bridge_reconfigured(), ast_bridge_methods::notify_masquerade, and ast_bridge::v_table.

Referenced by channel_do_masquerade().

01455 {
01456    struct ast_bridge_channel *bridge_channel;
01457    struct ast_bridge *bridge;
01458 
01459    /* Safely get the bridge_channel pointer for the chan. */
01460    ast_channel_lock(chan);
01461    bridge_channel = ast_channel_get_bridge_channel(chan);
01462    ast_channel_unlock(chan);
01463    if (!bridge_channel) {
01464       /* Not in a bridge */
01465       return;
01466    }
01467 
01468    ast_bridge_channel_lock_bridge(bridge_channel);
01469    bridge = bridge_channel->bridge;
01470    if (bridge_channel == bridge_find_channel(bridge, chan)) {
01471 /*
01472  * XXX ASTERISK-22366 this needs more work.  The channels need
01473  * to be made compatible again if the formats change. The
01474  * bridge_channel thread needs to monitor for this case.
01475  */
01476       /* The channel we want to notify is still in a bridge. */
01477       bridge->v_table->notify_masquerade(bridge, bridge_channel);
01478       bridge_reconfigured(bridge, 1);
01479    }
01480    ast_bridge_unlock(bridge);
01481    ao2_ref(bridge_channel, -1);
01482 }

int ast_bridge_number_video_src ( struct ast_bridge bridge  ) 

struct ast_channel* ast_bridge_peer ( struct ast_bridge bridge,
struct ast_channel chan 
) [read]

Get the channel's bridge peer only if the bridge is two-party.

Since:
12.0.0
Parameters:
bridge The bridge
chan Channel desiring the bridge peer channel.
Note:
The returned peer channel is the current peer in the bridge when called.
Return values:
NULL Channel not in a bridge or the bridge is not two-party.
non-NULL Reffed peer channel at time of calling.

Definition at line 3814 of file bridge.c.

References ast_bridge_lock, ast_bridge_peer_nolock(), and ast_bridge_unlock.

Referenced by ast_attended_transfer_message_create(), ast_bridge_transfer_blind(), ast_channel_bridge_peer(), and get_transfer_parties_transferer_bridge().

03815 {
03816    struct ast_channel *peer;
03817 
03818    ast_bridge_lock(bridge);
03819    peer = ast_bridge_peer_nolock(bridge, chan);
03820    ast_bridge_unlock(bridge);
03821 
03822    return peer;
03823 }

struct ast_channel* ast_bridge_peer_nolock ( struct ast_bridge bridge,
struct ast_channel chan 
) [read]

Get the channel's bridge peer only if the bridge is two-party.

Since:
12.0.0
Parameters:
bridge The bridge which is already locked.
chan Channel desiring the bridge peer channel.
Note:
The returned peer channel is the current peer in the bridge when called.
Return values:
NULL Channel not in a bridge or the bridge is not two-party.
non-NULL Reffed peer channel at time of calling.

Definition at line 3786 of file bridge.c.

References AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_NATIVE, ast_channel_ref, AST_LIST_TRAVERSE, ast_bridge_technology::capabilities, ast_bridge_channel::chan, ast_bridge::channels, ast_bridge_channel::in_bridge, NULL, ast_bridge::num_channels, and ast_bridge::technology.

Referenced by ast_bridge_peer(), feature_automixmonitor(), and feature_automonitor().

03787 {
03788    struct ast_channel *peer = NULL;
03789    struct ast_bridge_channel *iter;
03790 
03791    /* Asking for the peer channel only makes sense on a two-party bridge. */
03792    if (bridge->num_channels == 2
03793       && bridge->technology->capabilities
03794          & (AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX)) {
03795       int in_bridge = 0;
03796 
03797       AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
03798          if (iter->chan != chan) {
03799             peer = iter->chan;
03800          } else {
03801             in_bridge = 1;
03802          }
03803       }
03804       if (in_bridge && peer) {
03805          ast_channel_ref(peer);
03806       } else {
03807          peer = NULL;
03808       }
03809    }
03810 
03811    return peer;
03812 }

struct ao2_container* ast_bridge_peers ( struct ast_bridge bridge  )  [read]

Get a container of all channels in the bridge.

Since:
12.0.0
Parameters:
bridge The bridge
Note:
The returned container is a snapshot of channels in the bridge when called.
Return values:
NULL Failed to create container
non-NULL Container of channels in the bridge

Definition at line 3775 of file bridge.c.

References ast_bridge_lock, ast_bridge_peers_nolock(), ast_bridge_unlock, and channels.

03776 {
03777    struct ao2_container *channels;
03778 
03779    ast_bridge_lock(bridge);
03780    channels = ast_bridge_peers_nolock(bridge);
03781    ast_bridge_unlock(bridge);
03782 
03783    return channels;
03784 }

struct ao2_container* ast_bridge_peers_nolock ( struct ast_bridge bridge  )  [read]

Get a container of all channels in the bridge.

Since:
12.0.0
Parameters:
bridge The bridge which is already locked.
Return values:
NULL Failed to create container
non-NULL Container of channels in the bridge

Definition at line 3757 of file bridge.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_options, ao2_link, AST_LIST_TRAVERSE, ast_bridge_channel::chan, channel_cmp(), channel_hash(), ast_bridge::channels, channels, and NULL.

Referenced by ast_bridge_peers(), ast_bridge_transfer_attended(), ast_bridge_transfer_blind(), and two_bridge_attended_transfer().

03758 {
03759    struct ao2_container *channels;
03760    struct ast_bridge_channel *iter;
03761 
03762    channels = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK,
03763       13, channel_hash, channel_cmp);
03764    if (!channels) {
03765       return NULL;
03766    }
03767 
03768    AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
03769       ao2_link(channels, iter->chan);
03770    }
03771 
03772    return channels;
03773 }

int ast_bridge_queue_action ( struct ast_bridge bridge,
struct ast_frame action 
)

Put an action onto the specified bridge.

Since:
12.0.0
Parameters:
bridge What to queue the action on.
action What to do.
Return values:
0 on success.
-1 on error.
Note:
This API call is meant for internal bridging operations.

Definition at line 279 of file bridge.c.

References ast_frdup(), and bridge_queue_action_nodup().

Referenced by bridge_dissolve().

00280 {
00281    struct ast_frame *dup;
00282 
00283    dup = ast_frdup(action);
00284    if (!dup) {
00285       return -1;
00286    }
00287    bridge_queue_action_nodup(bridge, dup);
00288    return 0;
00289 }

int ast_bridge_remove ( struct ast_bridge bridge,
struct ast_channel chan 
)

Remove a channel from a bridge.

Parameters:
bridge Bridge that the channel is to be removed from
chan Channel to remove
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_remove(bridge, chan);

This removes the channel pointed to by the chan pointer from the bridge pointed to by the bridge pointer and requests that it be hung up. Control over the channel will NOT be given to the calling thread.

Note:
This API call can be used on channels that were added to the bridge using both ast_bridge_join and ast_bridge_impart.

Definition at line 1771 of file bridge.c.

References ast_bridge_channel_leave_bridge(), ast_bridge_lock, ast_bridge_unlock, AST_CAUSE_NORMAL_CLEARING, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, and bridge_find_channel().

Referenced by action_kick_last(), ast_bridge_transfer_attended(), ast_bridge_transfer_blind(), execute_menu_entry(), kick_conference_participant(), and leave_marked().

01772 {
01773    struct ast_bridge_channel *bridge_channel;
01774 
01775    ast_bridge_lock(bridge);
01776 
01777    /* Try to find the channel that we want to remove */
01778    if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
01779       ast_bridge_unlock(bridge);
01780       return -1;
01781    }
01782 
01783    ast_bridge_channel_leave_bridge(bridge_channel,
01784       BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
01785 
01786    ast_bridge_unlock(bridge);
01787 
01788    return 0;
01789 }

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 at line 3680 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_channel_unref, ast_bridge_video_talker_src_data::average_talking_energy, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, NULL, ast_bridge_video_mode::single_src_data, ast_bridge::softmix, ast_bridge_video_mode::talker_src_data, and ast_bridge_softmix::video_mode.

Referenced by handle_video_on_exit().

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.

Parameters:
bridge Channel to change the sample rate on.
sample_rate the sample rate to change to. If a value of 0 is passed here, the bridge will be free to pick what ever sample rate it chooses.

Definition at line 3540 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, ast_bridge_softmix::internal_sample_rate, and ast_bridge::softmix.

Referenced by join_conference_bridge().

03541 {
03542    ast_bridge_lock(bridge);
03543    bridge->softmix.internal_sample_rate = sample_rate;
03544    ast_bridge_unlock(bridge);
03545 }

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.

Parameters:
bridge Channel to change the sample rate on.
mixing_interval the sample rate to change to. If 0 is set the bridge tech is free to choose any mixing interval it uses by default.

Definition at line 3533 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, ast_bridge_softmix::internal_mixing_interval, and ast_bridge::softmix.

Referenced by join_conference_bridge().

03534 {
03535    ast_bridge_lock(bridge);
03536    bridge->softmix.internal_mixing_interval = mixing_interval;
03537    ast_bridge_unlock(bridge);
03538 }

void ast_bridge_set_single_src_video_mode ( struct ast_bridge bridge,
struct ast_channel video_src_chan 
)

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 at line 3580 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_test_suite_event_notify, cleanup_video_mode(), ast_bridge_video_mode::mode, ast_bridge::softmix, and ast_bridge_softmix::video_mode.

Referenced by handle_video_on_exit(), and join_conference_bridge().

03581 {
03582    ast_bridge_lock(bridge);
03583    cleanup_video_mode(bridge);
03584    bridge->softmix.video_mode.mode = AST_BRIDGE_VIDEO_MODE_TALKER_SRC;
03585    ast_test_suite_event_notify("BRIDGE_VIDEO_MODE", "Message: video mode set to talker source\r\nVideo Mode: %u",
03586       bridge->softmix.video_mode.mode);
03587    ast_bridge_unlock(bridge);
03588 }

void ast_bridge_set_transfer_variables ( struct ast_channel chan,
const char *  value,
int  is_attended 
)

Set the relevant transfer variables for a single channel.

Sets either the ATTENDEDTRANSFER or BLINDTRANSFER variable for a channel while clearing the opposite.

Parameters:
chan Channel the variable is being set for
value Value the variable is being set to
is_attended false set BLINDTRANSFER and unset ATTENDEDTRANSFER true set ATTENDEDTRANSFER and unset BLINDTRANSFER

Definition at line 4048 of file bridge.c.

References ATTENDEDTRANSFER, BLINDTRANSFER, NULL, and pbx_builtin_setvar_helper().

Referenced by dial_transfer(), manager_park(), park_local_transfer(), parking_park_bridge_channel(), and set_transfer_variables_all().

04049 {
04050    char *writevar;
04051    char *erasevar;
04052 
04053    if (attended) {
04054       writevar = ATTENDEDTRANSFER;
04055       erasevar = BLINDTRANSFER;
04056    } else {
04057       writevar = BLINDTRANSFER;
04058       erasevar = ATTENDEDTRANSFER;
04059    }
04060 
04061    pbx_builtin_setvar_helper(chan, writevar, value);
04062    pbx_builtin_setvar_helper(chan, erasevar, NULL);
04063 }

int ast_bridge_suspend ( struct ast_bridge bridge,
struct ast_channel chan 
)

Suspend a channel temporarily from a bridge.

Parameters:
bridge Bridge to suspend the channel from
chan Channel to suspend
Return values:
0 on success
-1 on failure
Example usage:

This suspends the channel pointed to by chan from the bridge pointed to by bridge temporarily. Control of the channel is given to the calling thread. This differs from ast_bridge_depart as the channel will not be removed from the bridge.

Note:
This API call can be used on channels that were added to the bridge using both ast_bridge_join and ast_bridge_impart.

Definition at line 2837 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, bridge_channel_internal_suspend_nolock(), and bridge_find_channel().

Referenced by conf_moh_start(), and conf_moh_stop().

02838 {
02839    struct ast_bridge_channel *bridge_channel;
02840 /* XXX ASTERISK-21271 the case of a disolved bridge while channel is suspended is not handled. */
02841 /* XXX ASTERISK-21271 suspend/unsuspend needs to be rethought. The caller must block until it has successfully suspended the channel for temporary control. */
02842 /* 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. */
02843 
02844    ast_bridge_lock(bridge);
02845 
02846    if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
02847       ast_bridge_unlock(bridge);
02848       return -1;
02849    }
02850 
02851    bridge_channel_internal_suspend_nolock(bridge_channel);
02852 
02853    ast_bridge_unlock(bridge);
02854 
02855    return 0;
02856 }

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.

Parameters:
features Bridge features structure
callback Function to execute upon activation
hook_pvt Unique data
destructor Optional destructor callback for hook_pvt data
remove_flags Dictates what situations the hook should be removed.
Return values:
0 on success
-1 on failure (The caller must cleanup any hook_pvt resources.)
Example usage:

 struct ast_bridge_features features;
 ast_bridge_features_init(&features);
 ast_bridge_talk_hook(&features, talk_callback, NULL, NULL, 0);

This makes the bridging technology call talk_callback when a channel is recognized as starting and stopping talking. A pointer to useful data may be provided to the hook_pvt parameter.

Note:
This hook is currently only supported by softmix.

Definition at line 3127 of file bridge.c.

References AST_BRIDGE_HOOK_TYPE_TALK, bridge_other_hook(), and hook_cb().

Referenced by confbridge_exec().

03132 {
03133    ast_bridge_hook_callback hook_cb = (ast_bridge_hook_callback) callback;
03134 
03135    return bridge_other_hook(features, hook_cb, hook_pvt, destructor, remove_flags,
03136       AST_BRIDGE_HOOK_TYPE_TALK);
03137 }

void ast_bridge_technology_suspend ( struct ast_bridge_technology technology  ) 

Suspend a bridge technology from consideration.

Parameters:
technology The bridge technology to suspend
Example usage:

 ast_bridge_technology_suspend(&simple_bridge_tech);

This suspends the bridge technology simple_bridge_tech from being considered when creating a new bridge. Existing bridges using the bridge technology are not affected.

Definition at line 2877 of file bridge.c.

References ast_bridge_technology::suspended.

Referenced by handle_bridge_technology_suspend(), and handle_manager_bridge_tech_suspend().

02878 {
02879    technology->suspended = 1;
02880 }

int ast_bridge_technology_unregister ( struct ast_bridge_technology technology  ) 

Unregister a bridge technology from use.

Parameters:
technology The bridge technology to unregister
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_technology_unregister(&simple_bridge_tech);

This unregisters a bridge technlogy declared as the structure simple_bridge_tech with the bridging core. It will no longer be considered when creating a new bridge.

Definition at line 237 of file bridge.c.

References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and ast_bridge_technology::name.

Referenced by dahdi_native_unload(), and unload_module().

00238 {
00239    struct ast_bridge_technology *current;
00240 
00241    AST_RWLIST_WRLOCK(&bridge_technologies);
00242 
00243    /* Ensure the bridge technology is registered before removing it */
00244    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&bridge_technologies, current, entry) {
00245       if (current == technology) {
00246          AST_RWLIST_REMOVE_CURRENT(entry);
00247          ast_verb(2, "Unregistered bridge technology %s\n", technology->name);
00248          break;
00249       }
00250    }
00251    AST_RWLIST_TRAVERSE_SAFE_END;
00252 
00253    AST_RWLIST_UNLOCK(&bridge_technologies);
00254 
00255    return current ? 0 : -1;
00256 }

void ast_bridge_technology_unsuspend ( struct ast_bridge_technology technology  ) 

Unsuspend a bridge technology.

Parameters:
technology The bridge technology to unsuspend
Example usage:

 ast_bridge_technology_unsuspend(&simple_bridge_tech);

This makes the bridge technology simple_bridge_tech considered when creating a new bridge again.

Definition at line 2882 of file bridge.c.

References ast_bridge_technology::suspended.

Referenced by handle_bridge_technology_suspend(), and handle_manager_bridge_tech_suspend().

02883 {
02884    /*
02885     * XXX We may want the act of unsuspending a bridge technology
02886     * to prod all existing bridges to see if they should start
02887     * using it.
02888     */
02889    technology->suspended = 0;
02890 }

enum ast_transfer_result ast_bridge_transfer_attended ( struct ast_channel to_transferee,
struct ast_channel to_transfer_target 
)

Attended transfer.

The two channels are both transferer channels. The first is the channel that is bridged to the transferee (or if unbridged, the 'first' call of the transfer). The second is the channel that is bridged to the transfer target (or if unbridged, the 'second' call of the transfer).

Note:
Absolutely _NO_ channel locks should be held before calling this function.
Parameters:
to_transferee Transferer channel on initial call (presumably bridged to transferee)
to_transfer_target Transferer channel on consultation call (presumably bridged to transfer target)
Returns:
The success or failure of the attended transfer

Definition at line 4373 of file bridge.c.

References acquire_bridge(), ao2_cleanup, ao2_container_count(), app, ast_attended_transfer_message_add_app(), ast_attended_transfer_message_create(), ast_bridge_channel_write_playfile(), ast_bridge_channel_write_unhold(), AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY, AST_BRIDGE_FLAG_TRANSFER_PROHIBITED, ast_bridge_lock, ast_bridge_lock_both, ast_bridge_peers_nolock(), ast_bridge_publish_attended_transfer(), ast_bridge_remove(), AST_BRIDGE_TRANSFER_FAIL, AST_BRIDGE_TRANSFER_INVALID, AST_BRIDGE_TRANSFER_NOT_PERMITTED, AST_BRIDGE_TRANSFER_SUCCESS, ast_bridge_unlock, ast_channel_appl(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_log, ast_softhangup(), AST_SOFTHANGUP_DEV, ast_strdupa, ast_strlen_zero, ast_test_flag, attended_transfer_bridge(), bridge_channel_internal_queue_attended_transfer(), channels, end, ast_bridge::feature_flags, get_transferee(), lock, LOG_ERROR, NULL, pbx_builtin_getvar_helper(), RAII_VAR, SCOPED_LOCK, set_transfer_variables_all(), and two_bridge_attended_transfer().

Referenced by analog_attempt_transfer(), AST_TEST_DEFINE(), attempt_transfer(), local_attended_transfer(), misdn_attempt_transfer(), refer_attended_task(), and skinny_transfer_attended().

04375 {
04376    RAII_VAR(struct ast_bridge *, to_transferee_bridge, NULL, ao2_cleanup);
04377    RAII_VAR(struct ast_bridge *, to_target_bridge, NULL, ao2_cleanup);
04378    RAII_VAR(struct ast_bridge_channel *, to_transferee_bridge_channel, NULL, ao2_cleanup);
04379    RAII_VAR(struct ast_bridge_channel *, to_target_bridge_channel, NULL, ao2_cleanup);
04380    RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup);
04381    RAII_VAR(struct ast_channel *, transferee, NULL, ao2_cleanup);
04382    RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
04383    struct ast_bridge *the_bridge = NULL;
04384    struct ast_channel *chan_bridged;
04385    struct ast_channel *chan_unbridged;
04386    int transfer_prohibited;
04387    int do_bridge_transfer;
04388    enum ast_transfer_result res;
04389    const char *app = NULL;
04390 
04391    to_transferee_bridge = acquire_bridge(to_transferee);
04392    to_target_bridge = acquire_bridge(to_transfer_target);
04393 
04394    transfer_msg = ast_attended_transfer_message_create(1, to_transferee, to_transferee_bridge,
04395          to_transfer_target, to_target_bridge, NULL, NULL);
04396    if (!transfer_msg) {
04397       ast_log(LOG_ERROR, "Unable to create Stasis publication for attended transfer from %s\n",
04398             ast_channel_name(to_transferee));
04399       return AST_BRIDGE_TRANSFER_FAIL;
04400    }
04401 
04402    /* They can't both be unbridged, you silly goose! */
04403    if (!to_transferee_bridge && !to_target_bridge) {
04404       res = AST_BRIDGE_TRANSFER_INVALID;
04405       goto end;
04406    }
04407 
04408    ast_channel_lock(to_transferee);
04409    to_transferee_bridge_channel = ast_channel_get_bridge_channel(to_transferee);
04410    ast_channel_unlock(to_transferee);
04411 
04412    ast_channel_lock(to_transfer_target);
04413    to_target_bridge_channel = ast_channel_get_bridge_channel(to_transfer_target);
04414    ast_channel_unlock(to_transfer_target);
04415 
04416    if (to_transferee_bridge_channel) {
04417       /* Take off hold if they are on hold. */
04418       ast_bridge_channel_write_unhold(to_transferee_bridge_channel);
04419    }
04420 
04421    if (to_target_bridge_channel) {
04422       const char *target_complete_sound;
04423 
04424       /* Take off hold if they are on hold. */
04425       ast_bridge_channel_write_unhold(to_target_bridge_channel);
04426 
04427       /* Is there a courtesy sound to play to the target? */
04428       ast_channel_lock(to_transfer_target);
04429       target_complete_sound = pbx_builtin_getvar_helper(to_transfer_target,
04430          "ATTENDED_TRANSFER_COMPLETE_SOUND");
04431       if (!ast_strlen_zero(target_complete_sound)) {
04432          target_complete_sound = ast_strdupa(target_complete_sound);
04433       } else {
04434          target_complete_sound = NULL;
04435       }
04436       ast_channel_unlock(to_transfer_target);
04437       if (!target_complete_sound) {
04438          ast_channel_lock(to_transferee);
04439          target_complete_sound = pbx_builtin_getvar_helper(to_transferee,
04440             "ATTENDED_TRANSFER_COMPLETE_SOUND");
04441          if (!ast_strlen_zero(target_complete_sound)) {
04442             target_complete_sound = ast_strdupa(target_complete_sound);
04443          } else {
04444             target_complete_sound = NULL;
04445          }
04446          ast_channel_unlock(to_transferee);
04447       }
04448       if (target_complete_sound) {
04449          ast_bridge_channel_write_playfile(to_target_bridge_channel, NULL,
04450             target_complete_sound, NULL);
04451       }
04452    }
04453 
04454    /* Let's get the easy one out of the way first */
04455    if (to_transferee_bridge && to_target_bridge) {
04456 
04457       if (!to_transferee_bridge_channel || !to_target_bridge_channel) {
04458          res = AST_BRIDGE_TRANSFER_INVALID;
04459          goto end;
04460       }
04461 
04462       ast_bridge_lock_both(to_transferee_bridge, to_target_bridge);
04463       res = two_bridge_attended_transfer(to_transferee, to_transferee_bridge_channel,
04464             to_transfer_target, to_target_bridge_channel,
04465             to_transferee_bridge, to_target_bridge, transfer_msg);
04466       ast_bridge_unlock(to_transferee_bridge);
04467       ast_bridge_unlock(to_target_bridge);
04468 
04469       ast_softhangup(to_transfer_target, AST_SOFTHANGUP_DEV);
04470       goto end;
04471    }
04472 
04473    the_bridge = to_transferee_bridge ?: to_target_bridge;
04474    chan_bridged = to_transferee_bridge ? to_transferee : to_transfer_target;
04475    chan_unbridged = to_transferee_bridge ? to_transfer_target : to_transferee;
04476 
04477    {
04478       int chan_count;
04479       SCOPED_LOCK(lock, the_bridge, ast_bridge_lock, ast_bridge_unlock);
04480 
04481       channels = ast_bridge_peers_nolock(the_bridge);
04482       if (!channels) {
04483          res = AST_BRIDGE_TRANSFER_FAIL;
04484          goto end;
04485       }
04486       chan_count = ao2_container_count(channels);
04487       if (chan_count <= 1) {
04488          res = AST_BRIDGE_TRANSFER_INVALID;
04489          goto end;
04490       }
04491       transfer_prohibited = ast_test_flag(&the_bridge->feature_flags,
04492             AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
04493       do_bridge_transfer = ast_test_flag(&the_bridge->feature_flags,
04494             AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY) ||
04495             chan_count > 2;
04496    }
04497 
04498    if (transfer_prohibited) {
04499       res = AST_BRIDGE_TRANSFER_NOT_PERMITTED;
04500       goto end;
04501    }
04502 
04503    set_transfer_variables_all(to_transferee, channels, 1);
04504 
04505    if (do_bridge_transfer) {
04506       ast_bridge_lock(the_bridge);
04507       res = attended_transfer_bridge(chan_bridged, chan_unbridged, the_bridge, NULL, transfer_msg);
04508       ast_bridge_unlock(the_bridge);
04509       goto end;
04510    }
04511 
04512    transferee = get_transferee(channels, chan_bridged);
04513    if (!transferee) {
04514       res = AST_BRIDGE_TRANSFER_FAIL;
04515       goto end;
04516    }
04517 
04518    app = ast_strdupa(ast_channel_appl(chan_unbridged));
04519    if (bridge_channel_internal_queue_attended_transfer(transferee, chan_unbridged)) {
04520       res = AST_BRIDGE_TRANSFER_FAIL;
04521       goto end;
04522    }
04523 
04524    ast_bridge_remove(the_bridge, chan_bridged);
04525 
04526    ast_attended_transfer_message_add_app(transfer_msg, app, NULL);
04527    res = AST_BRIDGE_TRANSFER_SUCCESS;
04528 
04529 end:
04530    transfer_msg->result = res;
04531    ast_bridge_publish_attended_transfer(transfer_msg);
04532    return res;
04533 }

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.

The channel given is bridged to one or multiple channels. Depending on the bridge and the number of participants, the entire bridge could be transferred to the given destination, or a single channel may be redirected.

Callers may also provide a callback to be called on the channel that will be running dialplan. The user data passed into ast_bridge_transfer_blind will be given as the argument to the callback to be interpreted as desired. This callback is guaranteed to be called in the same thread as ast_bridge_transfer_blind() and before ast_bridge_transfer_blind() returns.

Note:
Absolutely _NO_ channel locks should be held before calling this function.
Parameters:
is_external Indicates that transfer was initiated externally
transferer The channel performing the blind transfer
exten The dialplan extension to send the call to
context The dialplan context to send the call to
new_channel_cb A callback to be called on the channel that will be executing dialplan
user_data Argument for new_channel_cb
Returns:
The success or failure result of the blind transfer

Definition at line 4121 of file bridge.c.

References acquire_bridge(), ao2_alloc, ao2_cleanup, ao2_container_count(), ast_blind_transfer_message_create(), ast_bridge_channel_write_unhold(), AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY, AST_BRIDGE_FLAG_TRANSFER_PROHIBITED, ast_bridge_lock, ast_bridge_peer(), ast_bridge_peers_nolock(), ast_bridge_publish_blind_transfer(), ast_bridge_remove(), ast_bridge_snapshot_create(), AST_BRIDGE_TRANSFER_FAIL, AST_BRIDGE_TRANSFER_INVALID, AST_BRIDGE_TRANSFER_NOT_PERMITTED, AST_BRIDGE_TRANSFER_SUCCESS, ast_bridge_unlock, ast_channel_cleanup, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_name(), ast_channel_snapshot_get_latest(), ast_channel_uniqueid(), ast_channel_unlock, ast_log, ast_test_flag, blind_transfer_bridge(), bridge_channel_internal_queue_blind_transfer(), channels, ast_bridge::feature_flags, lock, LOG_ERROR, NULL, publish, RAII_VAR, SCOPED_LOCK, set_transfer_variables_all(), and try_parking().

Referenced by action_blind_transfer(), console_transfer(), feature_blind_transfer(), handle_request_refer(), refer_incoming_attended_request(), refer_incoming_blind_request(), skinny_transfer_blind(), and socket_process_helper().

04124 {
04125    RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
04126    RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
04127    RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup);
04128    RAII_VAR(struct ast_channel *, transferee, NULL, ast_channel_cleanup);
04129    RAII_VAR(struct transfer_channel_data *, user_data_wrapper, NULL, ao2_cleanup);
04130    RAII_VAR(struct ast_blind_transfer_message *, transfer_message, NULL, ao2_cleanup);
04131    int do_bridge_transfer;
04132    int transfer_prohibited;
04133    enum ast_transfer_result transfer_result;
04134 
04135    transfer_message = ast_blind_transfer_message_create(is_external, transferer, exten, context);
04136    if (!transfer_message) {
04137       /* Out of memory. Not even possible to publish a Stasis message about the
04138        * failure
04139        */
04140       ast_log(LOG_ERROR, "Unable to allocate memory for blind transfer publication from %s\n",
04141             ast_channel_name(transferer));
04142       return AST_BRIDGE_TRANSFER_FAIL;
04143    }
04144 
04145    bridge = acquire_bridge(transferer);
04146    if (!bridge) {
04147       transfer_result = AST_BRIDGE_TRANSFER_INVALID;
04148       goto publish;
04149    }
04150 
04151    ast_bridge_lock(bridge);
04152    transfer_message->bridge = ast_bridge_snapshot_create(bridge);
04153    ast_bridge_unlock(bridge);
04154    if (!transfer_message->bridge) {
04155       transfer_result = AST_BRIDGE_TRANSFER_FAIL;
04156       goto publish;
04157    }
04158 
04159    transferee = ast_bridge_peer(bridge, transferer);
04160    if (transferee) {
04161       transfer_message->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee));
04162       if (!transfer_message->transferee) {
04163          transfer_result = AST_BRIDGE_TRANSFER_FAIL;
04164          goto publish;
04165       }
04166    }
04167 
04168    ast_channel_lock(transferer);
04169    bridge_channel = ast_channel_get_bridge_channel(transferer);
04170    ast_channel_unlock(transferer);
04171    if (!bridge_channel) {
04172       transfer_result = AST_BRIDGE_TRANSFER_INVALID;
04173       goto publish;
04174    }
04175 
04176    user_data_wrapper = ao2_alloc(sizeof(*user_data_wrapper), NULL);
04177    if (!user_data_wrapper) {
04178       transfer_result = AST_BRIDGE_TRANSFER_FAIL;
04179       goto publish;
04180    }
04181 
04182    user_data_wrapper->data = user_data;
04183 
04184    /* Take off hold if they are on hold. */
04185    ast_bridge_channel_write_unhold(bridge_channel);
04186 
04187    transfer_result = try_parking(transferer, context, exten, new_channel_cb, user_data_wrapper);
04188    if (transfer_result == AST_BRIDGE_TRANSFER_SUCCESS) {
04189       goto publish;
04190    }
04191 
04192    /* Since parking didn't take control of the user_data_wrapper, we are just going to raise the completed flag now. */
04193    user_data_wrapper->completed = 1;
04194 
04195    {
04196       SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
04197 
04198       channels = ast_bridge_peers_nolock(bridge);
04199       if (!channels) {
04200          transfer_result = AST_BRIDGE_TRANSFER_FAIL;
04201          goto publish;
04202       }
04203       if (ao2_container_count(channels) <= 1) {
04204          transfer_result = AST_BRIDGE_TRANSFER_INVALID;
04205          goto publish;
04206       }
04207       transfer_prohibited = ast_test_flag(&bridge->feature_flags,
04208             AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
04209       do_bridge_transfer = ast_test_flag(&bridge->feature_flags,
04210             AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY) ||
04211             ao2_container_count(channels) > 2;
04212    }
04213 
04214    if (transfer_prohibited) {
04215       transfer_result = AST_BRIDGE_TRANSFER_NOT_PERMITTED;
04216       goto publish;
04217    }
04218 
04219    set_transfer_variables_all(transferer, channels, 0);
04220 
04221    if (do_bridge_transfer) {
04222       transfer_result = blind_transfer_bridge(is_external, transferer, bridge,
04223          exten, context, transferee, new_channel_cb, user_data_wrapper, transfer_message);
04224       goto publish;
04225    }
04226 
04227    /* Reaching this portion means that we're dealing with a two-party bridge */
04228 
04229    if (!transferee) {
04230       transfer_result = AST_BRIDGE_TRANSFER_FAIL;
04231       goto publish;
04232    }
04233 
04234    if (bridge_channel_internal_queue_blind_transfer(transferee, exten, context,
04235             new_channel_cb, user_data_wrapper)) {
04236       transfer_result = AST_BRIDGE_TRANSFER_FAIL;
04237       goto publish;
04238    }
04239 
04240    ast_bridge_remove(bridge, transferer);
04241    transfer_result = AST_BRIDGE_TRANSFER_SUCCESS;
04242 
04243 publish:
04244    transfer_message->result = transfer_result;
04245    ast_bridge_publish_blind_transfer(transfer_message);
04246    return transfer_result;
04247 }

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.

Since:
12.0.0
Parameters:
chan Unreal channel writing a frame into the channel driver.
peer Other unreal channel in the pair.
pvt Private data provided by an implementation of the unreal driver that contains the callbacks that should be called when optimization begins/ends
Note:
It is assumed that chan is already locked.
Return values:
0 if unreal channels were not optimized out.
non-zero if unreal channels were optimized out.

Definition at line 2737 of file bridge.c.

References ast_bridge_channel_unlock, ast_bridge_unlock, ast_channel_internal_bridge_channel(), ast_channel_unlock, optimize_lock_chan_stack(), optimize_lock_peer_stack(), try_merge_optimize_out(), and try_swap_optimize_out().

Referenced by got_optimized_out().

02738 {
02739    struct ast_bridge *chan_bridge;
02740    struct ast_bridge *peer_bridge;
02741    struct ast_bridge_channel *chan_bridge_channel;
02742    struct ast_bridge_channel *peer_bridge_channel;
02743    int res = 0;
02744 
02745    chan_bridge = optimize_lock_chan_stack(chan);
02746    if (!chan_bridge) {
02747       return res;
02748    }
02749    chan_bridge_channel = ast_channel_internal_bridge_channel(chan);
02750 
02751    peer_bridge = optimize_lock_peer_stack(peer);
02752    if (peer_bridge) {
02753       peer_bridge_channel = ast_channel_internal_bridge_channel(peer);
02754 
02755       res = try_swap_optimize_out(chan_bridge, chan_bridge_channel,
02756          peer_bridge, peer_bridge_channel, pvt);
02757       if (!res) {
02758          res = try_merge_optimize_out(chan_bridge, chan_bridge_channel,
02759             peer_bridge, peer_bridge_channel, pvt);
02760       } else if (0 < res) {
02761          res = 0;
02762       }
02763 
02764       /* Release peer locks. */
02765       ast_bridge_unlock(peer_bridge);
02766       ast_bridge_channel_unlock(peer_bridge_channel);
02767       ast_channel_unlock(peer);
02768    }
02769 
02770    /* Release chan locks. */
02771    ast_bridge_unlock(chan_bridge);
02772    ast_bridge_channel_unlock(chan_bridge_channel);
02773 
02774    return res;
02775 }

int ast_bridge_unsuspend ( struct ast_bridge bridge,
struct ast_channel chan 
)

Unsuspend a channel from a bridge.

Parameters:
bridge Bridge to unsuspend the channel from
chan Channel to unsuspend
Return values:
0 on success
-1 on failure
Example usage:

This unsuspends the channel pointed to by chan from the bridge pointed to by bridge. The bridge will go back to handling the channel once this function returns.

Note:
You must not mess with the channel once this function returns. Doing so may result in bad things happening.

Definition at line 2858 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, bridge_channel_internal_unsuspend_nolock(), and bridge_find_channel().

Referenced by conf_moh_start(), and conf_moh_stop().

02859 {
02860    struct ast_bridge_channel *bridge_channel;
02861 /* XXX ASTERISK-21271 the case of a disolved bridge while channel is suspended is not handled. */
02862 
02863    ast_bridge_lock(bridge);
02864 
02865    if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
02866       ast_bridge_unlock(bridge);
02867       return -1;
02868    }
02869 
02870    bridge_channel_internal_unsuspend_nolock(bridge_channel);
02871 
02872    ast_bridge_unlock(bridge);
02873 
02874    return 0;
02875 }

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 at line 3590 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, ast_channel_name(), ast_channel_nativeformats(), ast_channel_ref, ast_channel_unref, AST_CONTROL_VIDUPDATE, ast_format_cap_has_type(), ast_indicate(), AST_MEDIA_TYPE_VIDEO, ast_test_suite_event_notify, ast_bridge_video_talker_src_data::average_talking_energy, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_mode::mode_data, ast_bridge::softmix, ast_bridge_video_mode::talker_src_data, and ast_bridge_softmix::video_mode.

Referenced by softmix_bridge_write_video().

03591 {
03592    struct ast_bridge_video_talker_src_data *data;
03593 
03594    /* If the channel doesn't support video, we don't care about it */
03595    if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO)) {
03596       return;
03597    }
03598 
03599    ast_bridge_lock(bridge);
03600    data = &bridge->softmix.video_mode.mode_data.talker_src_data;
03601 
03602    if (data->chan_vsrc == chan) {
03603       data->average_talking_energy = talker_energy;
03604    } else if ((data->average_talking_energy < talker_energy) && is_keyframe) {
03605       if (data->chan_old_vsrc) {
03606          ast_channel_unref(data->chan_old_vsrc);
03607       }
03608       if (data->chan_vsrc) {
03609          data->chan_old_vsrc = data->chan_vsrc;
03610          ast_indicate(data->chan_old_vsrc, AST_CONTROL_VIDUPDATE);
03611       }
03612       data->chan_vsrc = ast_channel_ref(chan);
03613       data->average_talking_energy = talker_energy;
03614       ast_test_suite_event_notify("BRIDGE_VIDEO_SRC", "Message: video source updated\r\nVideo Channel: %s", ast_channel_name(data->chan_vsrc));
03615       ast_indicate(data->chan_vsrc, AST_CONTROL_VIDUPDATE);
03616    } else if ((data->average_talking_energy < talker_energy) && !is_keyframe) {
03617       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
03618    } else if (!data->chan_vsrc && is_keyframe) {
03619       data->chan_vsrc = ast_channel_ref(chan);
03620       data->average_talking_energy = talker_energy;
03621       ast_test_suite_event_notify("BRIDGE_VIDEO_SRC", "Message: video source updated\r\nVideo Channel: %s", ast_channel_name(data->chan_vsrc));
03622       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
03623    } else if (!data->chan_old_vsrc && is_keyframe) {
03624       data->chan_old_vsrc = ast_channel_ref(chan);
03625       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
03626    }
03627    ast_bridge_unlock(bridge);
03628 }

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.

Since:
12.0.0
Parameters:
chan_bridge First bridge being tested
peer_bridge Second bridge being tested
This determines if two bridges allow for unreal channel optimization to occur between them. The function does not require for unreal channels to already be in the bridges when called.

Note:
It is assumed that both bridges are locked prior to calling this function

A return other than AST_BRIDGE_OPTIMIZE_PROHIBITED does not guarantee that an optimization attempt will succeed. However, a return of AST_BRIDGE_OPTIMIZE_PROHIBITED guarantees that an optimization attempt will never succeed.

Returns:
Optimization allowability for the bridges

Definition at line 2777 of file bridge.c.

References AST_BRIDGE_OPTIMIZE_MERGE_TO_CHAN_BRIDGE, AST_BRIDGE_OPTIMIZE_MERGE_TO_PEER_BRIDGE, AST_BRIDGE_OPTIMIZE_PROHIBITED, AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE, AST_BRIDGE_OPTIMIZE_SWAP_TO_PEER_BRIDGE, bridge_allows_optimization(), bridges_allow_merge_optimization(), bridges_allow_swap_optimization(), merge_direction::dest, MERGE_ALLOWED, SWAP_PROHIBITED, SWAP_TO_CHAN_BRIDGE, and SWAP_TO_PEER_BRIDGE.

Referenced by two_bridge_attended_transfer().

02779 {
02780    struct merge_direction merge;
02781 
02782    if (!bridge_allows_optimization(chan_bridge) || !bridge_allows_optimization(peer_bridge)) {
02783       return AST_BRIDGE_OPTIMIZE_PROHIBITED;
02784    }
02785 
02786    switch (bridges_allow_swap_optimization(chan_bridge, peer_bridge)) {
02787    case SWAP_TO_CHAN_BRIDGE:
02788       return AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE;
02789    case SWAP_TO_PEER_BRIDGE:
02790       return AST_BRIDGE_OPTIMIZE_SWAP_TO_PEER_BRIDGE;
02791    case SWAP_PROHIBITED:
02792    default:
02793       break;
02794    }
02795 
02796    /* Two channels will be kicked from the bridges, the unreal;1 and unreal;2 channels */
02797    if (bridges_allow_merge_optimization(chan_bridge, peer_bridge, 2, &merge) != MERGE_ALLOWED) {
02798       return AST_BRIDGE_OPTIMIZE_PROHIBITED;
02799    }
02800 
02801    if (merge.dest == chan_bridge) {
02802       return AST_BRIDGE_OPTIMIZE_MERGE_TO_CHAN_BRIDGE;
02803    } else {
02804       return AST_BRIDGE_OPTIMIZE_MERGE_TO_PEER_BRIDGE;
02805    }
02806 }

int ast_bridging_init ( void   ) 

Initialize the bridging system.

Since:
12.0.0
Return values:
0 on success.
-1 on error.

Definition at line 5271 of file bridge.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ao2_container_alloc_rbtree, ao2_container_register(), ARRAY_LEN, ast_bridging_init_basic(), ast_cli_register_multiple(), ast_manager_register_xml_core, ast_register_cleanup(), ast_stasis_bridging_init(), bridge_cleanup(), bridge_manager, bridge_manager_create(), bridge_prnt_obj(), bridge_sort_cmp(), manager_bridge_tech_list(), manager_bridge_tech_suspend(), manager_bridge_tech_unsuspend(), and NULL.

Referenced by main().

05272 {
05273    ast_register_cleanup(bridge_cleanup);
05274 
05275    if (ast_stasis_bridging_init()) {
05276       return -1;
05277    }
05278 
05279    bridge_manager = bridge_manager_create();
05280    if (!bridge_manager) {
05281       return -1;
05282    }
05283 
05284    bridges = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX,
05285       AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, bridge_sort_cmp, NULL);
05286    if (!bridges) {
05287       return -1;
05288    }
05289    ao2_container_register("bridges", bridges, bridge_prnt_obj);
05290 
05291    ast_bridging_init_basic();
05292 
05293    ast_cli_register_multiple(bridge_cli, ARRAY_LEN(bridge_cli));
05294 
05295    ast_manager_register_xml_core("BridgeTechnologyList", 0, manager_bridge_tech_list);
05296    ast_manager_register_xml_core("BridgeTechnologySuspend", 0, manager_bridge_tech_suspend);
05297    ast_manager_register_xml_core("BridgeTechnologyUnsuspend", 0, manager_bridge_tech_unsuspend);
05298 
05299    return 0;
05300 }

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 
) [static]

Perform an attended transfer of a bridge.

This performs an attended transfer of an entire bridge to a target. The target varies, depending on what bridges exist during the transfer attempt.

If two bridges exist, then a local channel is created to link the two bridges together.

If only one bridge exists, then a local channel is created with one end placed into the existing bridge and the other end masquerading into the unbridged channel.

Parameters:
chan1 Transferer channel. Guaranteed to be bridged.
chan2 Other transferer channel. May or may not be bridged.
bridge1 Bridge that chan1 is in. Guaranteed to be non-NULL.
bridge2 Bridge that chan2 is in. If NULL, then chan2 is not bridged.
publication Data to publish for a stasis attended transfer message.
Return values:
AST_BRIDGE_TRANSFER_FAIL Internal error occurred
AST_BRIDGE_TRANSFER_SUCCESS Succesfully transferred the bridge

Definition at line 3952 of file bridge.c.

References ao2_cleanup, ao2_ref, app, ast_assert, ast_attended_transfer_message_add_app(), ast_attended_transfer_message_add_link(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, AST_BRIDGE_TRANSFER_FAIL, AST_BRIDGE_TRANSFER_SUCCESS, ast_call(), ast_channel_appl(), ast_channel_lock, ast_channel_lock_both, ast_channel_name(), ast_channel_nativeformats(), ast_channel_req_accountcodes(), AST_CHANNEL_REQUESTOR_REPLACEMENT, ast_channel_unlock, ast_hangup(), ast_local_get_peer(), ast_local_setup_bridge(), ast_local_setup_masquerade(), ast_request(), ast_strdupa, ATTENDEDTRANSFER, locals, NULL, pbx_builtin_setvar_helper(), and RAII_VAR.

Referenced by ast_bridge_transfer_attended(), and two_bridge_attended_transfer().

03955 {
03956    static const char *dest = "_attended@transfer/m";
03957    struct ast_channel *local_chan;
03958    int cause;
03959    int res;
03960    const char *app = NULL;
03961 
03962    local_chan = ast_request("Local", ast_channel_nativeformats(chan1), NULL, chan1,
03963          dest, &cause);
03964    if (!local_chan) {
03965       return AST_BRIDGE_TRANSFER_FAIL;
03966    }
03967 
03968    ast_channel_lock_both(local_chan, chan1);
03969    ast_channel_req_accountcodes(local_chan, chan1, AST_CHANNEL_REQUESTOR_REPLACEMENT);
03970    pbx_builtin_setvar_helper(local_chan, ATTENDEDTRANSFER, ast_channel_name(chan1));
03971    ast_channel_unlock(local_chan);
03972    ast_channel_unlock(chan1);
03973 
03974    if (bridge2) {
03975       res = ast_local_setup_bridge(local_chan, bridge2, chan2, NULL);
03976    } else {
03977       app = ast_strdupa(ast_channel_appl(chan2));
03978       res = ast_local_setup_masquerade(local_chan, chan2);
03979    }
03980 
03981    if (res) {
03982       ast_hangup(local_chan);
03983       return AST_BRIDGE_TRANSFER_FAIL;
03984    }
03985 
03986    if (ast_call(local_chan, dest, 0)) {
03987       ast_hangup(local_chan);
03988       return AST_BRIDGE_TRANSFER_FAIL;
03989    }
03990 
03991    /* Get a ref for use later since this one is being stolen */
03992    ao2_ref(local_chan, +1);
03993    if (ast_bridge_impart(bridge1, local_chan, chan1, NULL,
03994       AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
03995       ast_hangup(local_chan);
03996       ao2_cleanup(local_chan);
03997       return AST_BRIDGE_TRANSFER_FAIL;
03998    }
03999 
04000    if (bridge2) {
04001       RAII_VAR(struct ast_channel *, local_chan2, NULL, ao2_cleanup);
04002       struct ast_channel *locals[2];
04003 
04004       ast_channel_lock(local_chan);
04005       local_chan2 = ast_local_get_peer(local_chan);
04006       ast_channel_unlock(local_chan);
04007 
04008       ast_assert(local_chan2 != NULL);
04009 
04010       locals[0] = local_chan;
04011       locals[1] = local_chan2;
04012 
04013       ast_attended_transfer_message_add_link(transfer_msg, locals);
04014    } else {
04015       ast_attended_transfer_message_add_app(transfer_msg, app, local_chan);
04016    }
04017 
04018    ao2_cleanup(local_chan);
04019    return AST_BRIDGE_TRANSFER_SUCCESS;
04020 }

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 
) [static]

Definition at line 3850 of file bridge.c.

References ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, AST_BRIDGE_TRANSFER_FAIL, AST_BRIDGE_TRANSFER_MULTI_PARTY, AST_BRIDGE_TRANSFER_SUCCESS, ast_call(), ast_channel_lock_both, ast_channel_name(), ast_channel_nativeformats(), ast_channel_req_accountcodes(), AST_CHANNEL_REQUESTOR_REPLACEMENT, ast_channel_snapshot_get_latest(), ast_channel_uniqueid(), ast_channel_unlock, ast_hangup(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_request(), BLINDTRANSFER, NULL, pbx_builtin_setvar_helper(), and ast_blind_transfer_message::replace_channel.

Referenced by ast_bridge_transfer_blind().

03856 {
03857    struct ast_channel *local;
03858    char chan_name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
03859    int cause;
03860 
03861    snprintf(chan_name, sizeof(chan_name), "%s@%s", exten, context);
03862    local = ast_request("Local", ast_channel_nativeformats(transferer), NULL, transferer,
03863          chan_name, &cause);
03864    if (!local) {
03865       return AST_BRIDGE_TRANSFER_FAIL;
03866    }
03867 
03868    ast_channel_lock_both(local, transferer);
03869    ast_channel_req_accountcodes(local, transferer, AST_CHANNEL_REQUESTOR_REPLACEMENT);
03870 
03871    transfer_message->replace_channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(local));
03872    if (!transfer_message->replace_channel) {
03873       ast_hangup(local);
03874       return AST_BRIDGE_TRANSFER_FAIL;
03875    }
03876 
03877    pbx_builtin_setvar_helper(local, BLINDTRANSFER, ast_channel_name(transferer));
03878    ast_channel_unlock(local);
03879    ast_channel_unlock(transferer);
03880 
03881    if (new_channel_cb) {
03882       new_channel_cb(local, user_data_wrapper, AST_BRIDGE_TRANSFER_MULTI_PARTY);
03883    }
03884 
03885    if (ast_call(local, chan_name, 0)) {
03886       ast_hangup(local);
03887       return AST_BRIDGE_TRANSFER_FAIL;
03888    }
03889 
03890    if (ast_bridge_impart(bridge, local, transferer, NULL,
03891       AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
03892       ast_hangup(local);
03893       return AST_BRIDGE_TRANSFER_FAIL;
03894    }
03895 
03896    return AST_BRIDGE_TRANSFER_SUCCESS;
03897 }

static void bridge_action_bridge ( struct ast_bridge bridge,
struct ast_frame action 
) [static]

Definition at line 556 of file bridge.c.

References ao2_ref, ast_assert, ast_bridge_lock, ast_bridge_unlock, BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING, BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY, bridge_tech_deferred_destroy(), ast_bridge_methods::dissolving, ast_frame_subclass::integer, ast_frame::subclass, and ast_bridge::v_table.

Referenced by bridge_handle_actions().

00557 {
00558 #if 0 /* In case we need to know when the destructor is calling us. */
00559    int in_destructor = !ao2_ref(bridge, 0);
00560 #endif
00561 
00562    switch (action->subclass.integer) {
00563    case BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY:
00564       ast_bridge_unlock(bridge);
00565       bridge_tech_deferred_destroy(bridge, action);
00566       ast_bridge_lock(bridge);
00567       break;
00568    case BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING:
00569       ast_bridge_unlock(bridge);
00570       bridge->v_table->dissolving(bridge);
00571       ast_bridge_lock(bridge);
00572       break;
00573    default:
00574       /* Unexpected deferred action type.  Should never happen. */
00575       ast_assert(0);
00576       break;
00577    }
00578 }

struct ast_bridge* bridge_alloc ( size_t  size,
const struct ast_bridge_methods v_table 
) [read]

Definition at line 704 of file bridge.c.

References ao2_alloc, ao2_cleanup, ast_assert, ast_log, ast_string_field_init, ast_bridge_methods::destroy, destroy_bridge(), ast_bridge_methods::dissolving, ast_bridge_methods::get_merge_priority, LOG_ERROR, ast_bridge_methods::name, ast_bridge_methods::notify_masquerade, NULL, ast_bridge_methods::pull, ast_bridge_methods::push, and ast_bridge::v_table.

Referenced by ast_bridge_base_new(), ast_bridge_basic_new(), bridge_agent_hold_new(), bridge_parking_new(), and bridge_stasis_new().

00705 {
00706    struct ast_bridge *bridge;
00707 
00708    /* Check v_table that all methods are present. */
00709    if (!v_table
00710       || !v_table->name
00711       || !v_table->destroy
00712       || !v_table->dissolving
00713       || !v_table->push
00714       || !v_table->pull
00715       || !v_table->notify_masquerade
00716       || !v_table->get_merge_priority) {
00717       ast_log(LOG_ERROR, "Virtual method table for bridge class %s not complete.\n",
00718          v_table && v_table->name ? v_table->name : "<unknown>");
00719       ast_assert(0);
00720       return NULL;
00721    }
00722 
00723    bridge = ao2_alloc(size, destroy_bridge);
00724    if (!bridge) {
00725       return NULL;
00726    }
00727 
00728    if (ast_string_field_init(bridge, 80)) {
00729       ao2_cleanup(bridge);
00730       return NULL;
00731    }
00732 
00733    bridge->v_table = v_table;
00734 
00735    return bridge;
00736 }

static int bridge_allows_optimization ( struct ast_bridge bridge  )  [static]

static void bridge_base_destroy ( struct ast_bridge self  )  [static]

Definition at line 813 of file bridge.c.

00814 {
00815 }

static void bridge_base_dissolving ( struct ast_bridge self  )  [static]

Definition at line 826 of file bridge.c.

References ao2_unlink.

00827 {
00828    ao2_unlink(bridges, self);
00829 }

static int bridge_base_get_merge_priority ( struct ast_bridge self  )  [static]

Definition at line 896 of file bridge.c.

00897 {
00898    return 0;
00899 }

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 
) [read]

Initialize the base class of the bridge.

Parameters:
self Bridge to operate upon. (Tolerates a NULL pointer)
capabilities The capabilities that we require to be used on the bridge
flags Flags that will alter the behavior of the bridge
creator Entity that created the bridge (optional)
name Name given to the bridge by its creator (optional, requires named creator)
id Unique ID given to the bridge by its creator (optional)
Return values:
self on success
NULL on failure, self is already destroyed
Example usage:

This creates a no frills two party bridge that will be destroyed once one of the channels hangs up.

Definition at line 738 of file bridge.c.

References ao2_ref, ast_bridge_topic(), ast_debug, ast_log, ast_set_flag, ast_string_field_set, ast_strlen_zero, ast_uuid_generate_str(), AST_UUID_STR_LEN, bridge_topics_init(), find_best_technology(), LOG_WARNING, NULL, and ast_bridge::uniqueid.

Referenced by ast_bridge_base_new(), ast_bridge_basic_new(), bridge_agent_hold_new(), bridge_parking_new(), and bridge_stasis_new().

00739 {
00740    char uuid_hold[AST_UUID_STR_LEN];
00741 
00742    if (!self) {
00743       return NULL;
00744    }
00745 
00746    if (!ast_strlen_zero(id)) {
00747       ast_string_field_set(self, uniqueid, id);
00748    } else {
00749       ast_uuid_generate_str(uuid_hold, AST_UUID_STR_LEN);
00750       ast_string_field_set(self, uniqueid, uuid_hold);
00751    }
00752    ast_string_field_set(self, creator, creator);
00753    if (!ast_strlen_zero(creator)) {
00754       ast_string_field_set(self, name, name);
00755    }
00756 
00757    ast_set_flag(&self->feature_flags, flags);
00758    self->allowed_capabilities = capabilities;
00759 
00760    if (bridge_topics_init(self) != 0) {
00761       ast_log(LOG_WARNING, "Bridge %s: Could not initialize topics\n",
00762          self->uniqueid);
00763       ao2_ref(self, -1);
00764       return NULL;
00765    }
00766 
00767    /* Use our helper function to find the "best" bridge technology. */
00768    self->technology = find_best_technology(capabilities, self);
00769    if (!self->technology) {
00770       ast_log(LOG_WARNING, "Bridge %s: Could not create class %s.  No technology to support it.\n",
00771          self->uniqueid, self->v_table->name);
00772       ao2_ref(self, -1);
00773       return NULL;
00774    }
00775 
00776    /* Pass off the bridge to the technology to manipulate if needed */
00777    ast_debug(1, "Bridge %s: calling %s technology constructor\n",
00778       self->uniqueid, self->technology->name);
00779    if (self->technology->create && self->technology->create(self)) {
00780       ast_log(LOG_WARNING, "Bridge %s: failed to setup bridge technology %s\n",
00781          self->uniqueid, self->technology->name);
00782       ao2_ref(self, -1);
00783       return NULL;
00784    }
00785    ast_debug(1, "Bridge %s: calling %s technology start\n",
00786       self->uniqueid, self->technology->name);
00787    if (self->technology->start && self->technology->start(self)) {
00788       ast_log(LOG_WARNING, "Bridge %s: failed to start bridge technology %s\n",
00789          self->uniqueid, self->technology->name);
00790       ao2_ref(self, -1);
00791       return NULL;
00792    }
00793 
00794    if (!ast_bridge_topic(self)) {
00795       ao2_ref(self, -1);
00796       return NULL;
00797    }
00798 
00799    return self;
00800 }

static void bridge_base_notify_masquerade ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 880 of file bridge.c.

00881 {
00882    self->reconfigured = 1;
00883 }

static void bridge_base_pull ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel 
) [static]

static int bridge_base_push ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
) [static]

Definition at line 846 of file bridge.c.

00847 {
00848    return 0;
00849 }

static int bridge_base_push_peek ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
) [static]

Definition at line 916 of file bridge.c.

00917 {
00918    return 0;
00919 }

static void bridge_channel_change_bridge ( struct ast_bridge_channel bridge_channel,
struct ast_bridge new_bridge 
) [static]

Definition at line 1826 of file bridge.c.

References ao2_ref, ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_internal_bridge_set(), ast_channel_lock, ast_channel_unlock, ast_bridge_channel::bridge, and ast_bridge_channel::chan.

Referenced by bridge_do_merge(), and bridge_do_move().

01827 {
01828    struct ast_bridge *old_bridge;
01829 
01830    ao2_ref(new_bridge, +1);
01831    ast_bridge_channel_lock(bridge_channel);
01832    ast_channel_lock(bridge_channel->chan);
01833    old_bridge = bridge_channel->bridge;
01834    bridge_channel->bridge = new_bridge;
01835    ast_channel_internal_bridge_set(bridge_channel->chan, new_bridge);
01836    ast_channel_unlock(bridge_channel->chan);
01837    ast_bridge_channel_unlock(bridge_channel);
01838    ao2_ref(old_bridge, -1);
01839 }

static void bridge_channel_complete_join ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 415 of file bridge.c.

References ast_channel_name(), ast_debug, ast_bridge_channel::chan, ast_bridge_technology::join, ast_bridge_channel::just_joined, ast_bridge_technology::name, ast_bridge::technology, and ast_bridge::uniqueid.

Referenced by bridge_complete_join(), and smart_bridge_operation().

00416 {
00417    /* Tell the bridge technology we are joining so they set us up */
00418    ast_debug(1, "Bridge %s: %p(%s) is joining %s technology\n",
00419       bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
00420       bridge->technology->name);
00421    if (bridge->technology->join
00422       && bridge->technology->join(bridge, bridge_channel)) {
00423       ast_debug(1, "Bridge %s: %p(%s) failed to join %s technology\n",
00424          bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
00425          bridge->technology->name);
00426       bridge_channel->just_joined = 1;
00427       return;
00428    }
00429 
00430    bridge_channel->just_joined = 0;
00431 }

static void* bridge_channel_depart_thread ( void *  data  )  [static]

Thread responsible for imparted bridged channels to be departed.

Definition at line 1580 of file bridge.c.

References ao2_t_cleanup, AST_BRIDGE_AFTER_CB_REASON_DEPART, ast_bridge_discard_after_callback(), ast_bridge_discard_after_goto(), ast_bridge_features_destroy(), ast_callid_threadassoc_add(), bridge_channel_internal_join(), ast_bridge_channel::callid, ast_bridge_channel::chan, ast_bridge_channel::features, NULL, and ast_bridge_channel::swap.

Referenced by ast_bridge_impart().

01581 {
01582    struct ast_bridge_channel *bridge_channel = data;
01583 
01584    if (bridge_channel->callid) {
01585       ast_callid_threadassoc_add(bridge_channel->callid);
01586    }
01587 
01588    bridge_channel_internal_join(bridge_channel);
01589 
01590    /*
01591     * cleanup
01592     *
01593     * If bridge_channel->swap is not NULL then the join failed.
01594     */
01595    ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Departable impart join failed");
01596    bridge_channel->swap = NULL;
01597    ast_bridge_features_destroy(bridge_channel->features);
01598    bridge_channel->features = NULL;
01599 
01600    ast_bridge_discard_after_callback(bridge_channel->chan, AST_BRIDGE_AFTER_CB_REASON_DEPART);
01601    ast_bridge_discard_after_goto(bridge_channel->chan);
01602 
01603    return NULL;
01604 }

static void* bridge_channel_ind_thread ( void *  data  )  [static]

Thread responsible for independent imparted bridged channels.

Definition at line 1607 of file bridge.c.

References ao2_ref, ao2_t_cleanup, ast_bridge_features_destroy(), ast_bridge_run_after_callback(), ast_bridge_run_after_goto(), ast_callid_threadassoc_add(), ast_channel_internal_bridge_channel_set(), ast_channel_lock, ast_channel_unlock, bridge_channel_internal_join(), ast_bridge_channel::callid, ast_bridge_channel::chan, ast_bridge_channel::features, NULL, and ast_bridge_channel::swap.

Referenced by ast_bridge_impart().

01608 {
01609    struct ast_bridge_channel *bridge_channel = data;
01610    struct ast_channel *chan;
01611 
01612    if (bridge_channel->callid) {
01613       ast_callid_threadassoc_add(bridge_channel->callid);
01614    }
01615 
01616    bridge_channel_internal_join(bridge_channel);
01617    chan = bridge_channel->chan;
01618 
01619    /* cleanup */
01620    ast_channel_lock(chan);
01621    ast_channel_internal_bridge_channel_set(chan, NULL);
01622    ast_channel_unlock(chan);
01623    bridge_channel->chan = NULL;
01624    /* If bridge_channel->swap is not NULL then the join failed. */
01625    ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Independent impart join failed");
01626    bridge_channel->swap = NULL;
01627    ast_bridge_features_destroy(bridge_channel->features);
01628    bridge_channel->features = NULL;
01629 
01630    ao2_ref(bridge_channel, -1);
01631 
01632    ast_bridge_run_after_callback(chan);
01633    ast_bridge_run_after_goto(chan);
01634    return NULL;
01635 }

static void bridge_channel_moving ( struct ast_bridge_channel bridge_channel,
struct ast_bridge src,
struct ast_bridge dst 
) [static]

Definition at line 1841 of file bridge.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ao2_unlink, AST_BRIDGE_HOOK_TYPE_MOVE, ast_channel_name(), ast_debug, ast_bridge_hook::callback, ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_hook::hook_pvt, ast_bridge_features::other_hooks, and ast_bridge_hook::type.

Referenced by bridge_do_merge(), and bridge_do_move().

01842 {
01843    struct ast_bridge_features *features = bridge_channel->features;
01844    struct ast_bridge_hook *hook;
01845    struct ao2_iterator iter;
01846 
01847    /* Run any moving hooks. */
01848    iter = ao2_iterator_init(features->other_hooks, 0);
01849    for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
01850       int remove_me;
01851       ast_bridge_move_indicate_callback move_cb;
01852 
01853       if (hook->type != AST_BRIDGE_HOOK_TYPE_MOVE) {
01854          continue;
01855       }
01856       move_cb = (ast_bridge_move_indicate_callback) hook->callback;
01857       remove_me = move_cb(bridge_channel, hook->hook_pvt, src, dst);
01858       if (remove_me) {
01859          ast_debug(1, "Move detection hook %p is being removed from %p(%s)\n",
01860             hook, bridge_channel, ast_channel_name(bridge_channel->chan));
01861          ao2_unlink(features->other_hooks, hook);
01862       }
01863    }
01864    ao2_iterator_destroy(&iter);
01865 }

static void bridge_cleanup ( void   )  [static]

Definition at line 5257 of file bridge.c.

References ao2_cleanup, ao2_container_unregister(), ARRAY_LEN, ast_cli_unregister_multiple(), ast_manager_unregister(), bridge_manager, and NULL.

Referenced by ast_bridging_init().

05258 {
05259    ast_manager_unregister("BridgeTechnologyList");
05260    ast_manager_unregister("BridgeTechnologySuspend");
05261    ast_manager_unregister("BridgeTechnologyUnsuspend");
05262    ast_cli_unregister_multiple(bridge_cli, ARRAY_LEN(bridge_cli));
05263    ao2_container_unregister("bridges");
05264 
05265    ao2_cleanup(bridges);
05266    bridges = NULL;
05267    ao2_cleanup(bridge_manager);
05268    bridge_manager = NULL;
05269 }

static void bridge_complete_join ( struct ast_bridge bridge  )  [static]

Definition at line 444 of file bridge.c.

References AST_LIST_TRAVERSE, bridge_channel_complete_join(), ast_bridge::channels, ast_bridge::dissolved, and ast_bridge_channel::just_joined.

Referenced by bridge_reconfigured().

00445 {
00446    struct ast_bridge_channel *bridge_channel;
00447 
00448    if (bridge->dissolved) {
00449       /*
00450        * No sense in completing the join on channels for a dissolved
00451        * bridge.  They are just going to be removed soon anyway.
00452        * However, we do have reason to abort here because the bridge
00453        * technology may not be able to handle the number of channels
00454        * still in the bridge.
00455        */
00456       return;
00457    }
00458 
00459    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00460       if (!bridge_channel->just_joined) {
00461          continue;
00462       }
00463       bridge_channel_complete_join(bridge, bridge_channel);
00464    }
00465 }

void bridge_dissolve ( struct ast_bridge bridge,
int  cause 
)

Definition at line 291 of file bridge.c.

References ast_bridge_channel_leave_bridge(), ast_bridge_queue_action(), ast_cause2str(), AST_CAUSE_NORMAL_CLEARING, ast_debug, AST_FRAME_BRIDGE_ACTION, AST_LIST_TRAVERSE, BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, ast_bridge::cause, ast_bridge::channels, ast_bridge::dissolved, ast_frame::frametype, and ast_bridge::uniqueid.

Referenced by ast_bridge_destroy(), bridge_channel_dissolve_check(), bridge_dissolve_check_stolen(), and bridge_reconfigured().

00292 {
00293    struct ast_bridge_channel *bridge_channel;
00294    struct ast_frame action = {
00295       .frametype = AST_FRAME_BRIDGE_ACTION,
00296       .subclass.integer = BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING,
00297    };
00298 
00299    if (bridge->dissolved) {
00300       return;
00301    }
00302    bridge->dissolved = 1;
00303 
00304    if (cause <= 0) {
00305       cause = AST_CAUSE_NORMAL_CLEARING;
00306    }
00307    bridge->cause = cause;
00308 
00309    ast_debug(1, "Bridge %s: dissolving bridge with cause %d(%s)\n",
00310       bridge->uniqueid, cause, ast_cause2str(cause));
00311 
00312    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00313       ast_bridge_channel_leave_bridge(bridge_channel,
00314          BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, cause);
00315    }
00316 
00317    /* Must defer dissolving bridge because it is already locked. */
00318    ast_bridge_queue_action(bridge, &action);
00319 }

static void bridge_dissolve_check_stolen ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 333 of file bridge.c.

References AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP, AST_BRIDGE_FLAG_DISSOLVE_HANGUP, ast_test_flag, bridge_dissolve(), ast_bridge::dissolved, ast_bridge::feature_flags, ast_bridge_features::feature_flags, ast_bridge_channel::features, ast_bridge::num_channels, and ast_bridge_features::usable.

Referenced by ast_bridge_add_channel().

00334 {
00335    if (bridge->dissolved) {
00336       return;
00337    }
00338 
00339    if (bridge_channel->features->usable
00340       && ast_test_flag(&bridge_channel->features->feature_flags,
00341          AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP)) {
00342       /* The stolen channel controlled the bridge it was stolen from. */
00343       bridge_dissolve(bridge, 0);
00344       return;
00345    }
00346    if (bridge->num_channels < 2
00347       && ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_HANGUP)) {
00348       /*
00349        * The stolen channel has not left enough channels to keep the
00350        * bridge alive.  Assume the stolen channel hung up.
00351        */
00352       bridge_dissolve(bridge, 0);
00353       return;
00354    }
00355 }

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 at line 1867 of file bridge.c.

References AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE, ast_bridge_channel_leave_bridge(), ast_bridge_channel_leave_bridge_nolock(), ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_bridge_features_remove(), AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_bridge_publish_merge(), AST_CAUSE_NORMAL_CLEARING, ast_debug, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_test_flag, ast_bridge_channel::bridge, bridge_channel_change_bridge(), bridge_channel_internal_pull(), bridge_channel_internal_push(), bridge_channel_moving(), BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, BRIDGE_CHANNEL_STATE_WAIT, bridge_reconfigured(), ast_bridge::cause, ast_bridge::channels, ast_bridge_features::feature_flags, ast_bridge_channel::features, ast_bridge_channel::state, and ast_bridge::uniqueid.

Referenced by bridge_merge(), bridge_merge_locked(), try_merge_optimize_out(), and two_bridge_attended_transfer().

01869 {
01870    struct ast_bridge_channel *bridge_channel;
01871    unsigned int idx;
01872 
01873    ast_debug(1, "Merging bridge %s into bridge %s\n",
01874       src_bridge->uniqueid, dst_bridge->uniqueid);
01875 
01876    ast_bridge_publish_merge(dst_bridge, src_bridge);
01877 
01878    /*
01879     * Move channels from src_bridge over to dst_bridge.
01880     *
01881     * We must use AST_LIST_TRAVERSE_SAFE_BEGIN() because
01882     * bridge_channel_internal_pull() alters the list we are traversing.
01883     */
01884    AST_LIST_TRAVERSE_SAFE_BEGIN(&src_bridge->channels, bridge_channel, entry) {
01885       if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
01886          /*
01887           * The channel is already leaving let it leave normally because
01888           * pulling it may delete hooks that should run for this channel.
01889           */
01890          continue;
01891       }
01892       if (ast_test_flag(&bridge_channel->features->feature_flags,
01893          AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE)) {
01894          continue;
01895       }
01896 
01897       if (kick_me) {
01898          for (idx = 0; idx < num_kick; ++idx) {
01899             if (bridge_channel == kick_me[idx]) {
01900                ast_bridge_channel_leave_bridge(bridge_channel,
01901                   BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
01902                break;
01903             }
01904          }
01905       }
01906       bridge_channel_internal_pull(bridge_channel);
01907       if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
01908          /*
01909           * The channel died as a result of being pulled or it was
01910           * kicked.  Leave it pointing to the original bridge.
01911           */
01912          continue;
01913       }
01914 
01915       bridge_channel_moving(bridge_channel, bridge_channel->bridge, dst_bridge);
01916 
01917       /* Point to new bridge.*/
01918       bridge_channel_change_bridge(bridge_channel, dst_bridge);
01919 
01920       if (bridge_channel_internal_push(bridge_channel)) {
01921          ast_bridge_features_remove(bridge_channel->features,
01922             AST_BRIDGE_HOOK_REMOVE_ON_PULL);
01923          ast_bridge_channel_leave_bridge(bridge_channel,
01924             BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
01925       }
01926    }
01927    AST_LIST_TRAVERSE_SAFE_END;
01928 
01929    if (kick_me) {
01930       /*
01931        * Now we can kick any channels in the dst_bridge without
01932        * potentially dissolving the bridge.
01933        */
01934       for (idx = 0; idx < num_kick; ++idx) {
01935          bridge_channel = kick_me[idx];
01936          ast_bridge_channel_lock(bridge_channel);
01937          if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
01938             ast_bridge_channel_leave_bridge_nolock(bridge_channel,
01939                BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
01940             bridge_channel_internal_pull(bridge_channel);
01941          }
01942          ast_bridge_channel_unlock(bridge_channel);
01943       }
01944    }
01945 
01946    bridge_reconfigured(dst_bridge, !optimized);
01947    bridge_reconfigured(src_bridge, !optimized);
01948 
01949    ast_debug(1, "Merged bridge %s into bridge %s\n",
01950       src_bridge->uniqueid, dst_bridge->uniqueid);
01951 }

int bridge_do_move ( struct ast_bridge dst_bridge,
struct ast_bridge_channel bridge_channel,
int  attempt_recovery,
unsigned int  optimized 
)

Definition at line 2133 of file bridge.c.

References ao2_ref, ast_bridge_channel_leave_bridge(), ast_bridge_features_remove(), AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_channel_name(), ast_debug, ast_bridge_channel::bridge, bridge_channel_change_bridge(), bridge_channel_internal_pull(), bridge_channel_internal_push(), bridge_channel_moving(), bridge_channel_settle_owed_events(), BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, BRIDGE_CHANNEL_STATE_WAIT, bridge_reconfigured(), ast_bridge::cause, ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_channel::in_bridge, NULL, ast_bridge_channel::state, ast_bridge_channel::swap, and ast_bridge::uniqueid.

Referenced by bridge_move(), bridge_move_locked(), bridge_swap_attended_transfer(), and try_swap_optimize_out().

02135 {
02136    struct ast_bridge *orig_bridge;
02137    int was_in_bridge;
02138    int res = 0;
02139 
02140    if (bridge_channel->swap) {
02141       ast_debug(1, "Moving %p(%s) into bridge %s swapping with %s\n",
02142          bridge_channel, ast_channel_name(bridge_channel->chan), dst_bridge->uniqueid,
02143          ast_channel_name(bridge_channel->swap));
02144    } else {
02145       ast_debug(1, "Moving %p(%s) into bridge %s\n",
02146          bridge_channel, ast_channel_name(bridge_channel->chan), dst_bridge->uniqueid);
02147    }
02148 
02149    orig_bridge = bridge_channel->bridge;
02150    was_in_bridge = bridge_channel->in_bridge;
02151 
02152    bridge_channel_internal_pull(bridge_channel);
02153    if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
02154       /*
02155        * The channel died as a result of being pulled.  Leave it
02156        * pointing to the original bridge.
02157        *
02158        * Clear out the swap channel pointer.  A ref is not held
02159        * by bridge_channel->swap at this point.
02160        */
02161       bridge_channel->swap = NULL;
02162       bridge_reconfigured(orig_bridge, 0);
02163       return -1;
02164    }
02165 
02166    /* Point to new bridge.*/
02167    ao2_ref(orig_bridge, +1);/* Keep a ref in case the push fails. */
02168    bridge_channel_change_bridge(bridge_channel, dst_bridge);
02169 
02170    bridge_channel_moving(bridge_channel, orig_bridge, dst_bridge);
02171 
02172    if (bridge_channel_internal_push(bridge_channel)) {
02173       /* Try to put the channel back into the original bridge. */
02174       ast_bridge_features_remove(bridge_channel->features,
02175          AST_BRIDGE_HOOK_REMOVE_ON_PULL);
02176       if (attempt_recovery && was_in_bridge) {
02177          /* Point back to original bridge. */
02178          bridge_channel_change_bridge(bridge_channel, orig_bridge);
02179 
02180          if (bridge_channel_internal_push(bridge_channel)) {
02181             ast_bridge_features_remove(bridge_channel->features,
02182                AST_BRIDGE_HOOK_REMOVE_ON_PULL);
02183             ast_bridge_channel_leave_bridge(bridge_channel,
02184                BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
02185             bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
02186          }
02187       } else {
02188          ast_bridge_channel_leave_bridge(bridge_channel,
02189             BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
02190          bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
02191       }
02192       res = -1;
02193    } else {
02194       bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
02195    }
02196 
02197    bridge_reconfigured(dst_bridge, !optimized);
02198    bridge_reconfigured(orig_bridge, !optimized);
02199    ao2_ref(orig_bridge, -1);
02200    return res;
02201 }

static int bridge_dtmf_hook_sort ( const void *  obj_left,
const void *  obj_right,
int  flags 
) [static]

Definition at line 3375 of file bridge.c.

References ast_bridge_hook_dtmf_parms::code, ast_bridge_hook_dtmf::dtmf, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by ast_bridge_features_init().

03376 {
03377    const struct ast_bridge_hook_dtmf *hook_left = obj_left;
03378    const struct ast_bridge_hook_dtmf *hook_right = obj_right;
03379    const char *right_key = obj_right;
03380    int cmp;
03381 
03382    switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
03383    default:
03384    case OBJ_POINTER:
03385       right_key = hook_right->dtmf.code;
03386       /* Fall through */
03387    case OBJ_KEY:
03388       cmp = strcasecmp(hook_left->dtmf.code, right_key);
03389       break;
03390    case OBJ_PARTIAL_KEY:
03391       cmp = strncasecmp(hook_left->dtmf.code, right_key, strlen(right_key));
03392       break;
03393    }
03394    return cmp;
03395 }

struct ast_bridge_channel* bridge_find_channel ( struct ast_bridge bridge,
struct ast_channel chan 
) [read]

Definition at line 1441 of file bridge.c.

References AST_LIST_TRAVERSE, ast_bridge_channel::chan, and ast_bridge::channels.

Referenced by ast_bridge_add_channel(), ast_bridge_impart(), ast_bridge_join(), ast_bridge_kick(), ast_bridge_notify_masquerade(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), bridge_channel_internal_push(), bridge_merge(), bridge_merge_locked(), bridge_move_locked(), and play_uri().

01442 {
01443    struct ast_bridge_channel *bridge_channel;
01444 
01445    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
01446       if (bridge_channel->chan == chan) {
01447          break;
01448       }
01449    }
01450 
01451    return bridge_channel;
01452 }

static void bridge_handle_actions ( struct ast_bridge bridge  )  [static]

Definition at line 592 of file bridge.c.

References ast_bridge::action_queue, ast_assert, AST_FRAME_BRIDGE_ACTION, ast_frfree, AST_LIST_REMOVE_HEAD, bridge_action_bridge(), and ast_frame::frametype.

Referenced by bridge_manager_service(), and destroy_bridge().

00593 {
00594    struct ast_frame *action;
00595 
00596    while ((action = AST_LIST_REMOVE_HEAD(&bridge->action_queue, frame_list))) {
00597       switch (action->frametype) {
00598       case AST_FRAME_BRIDGE_ACTION:
00599          bridge_action_bridge(bridge, action);
00600          break;
00601       default:
00602          /* Unexpected deferred frame type.  Should never happen. */
00603          ast_assert(0);
00604          break;
00605       }
00606       ast_frfree(action);
00607    }
00608 }

static void bridge_hook_destroy ( void *  vhook  )  [static]

Definition at line 2971 of file bridge.c.

References ast_bridge_hook::destructor, and ast_bridge_hook::hook_pvt.

Referenced by bridge_hook_generic().

02972 {
02973    struct ast_bridge_hook *hook = vhook;
02974 
02975    if (hook->destructor) {
02976       hook->destructor(hook->hook_pvt);
02977    }
02978 }

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 
) [static, read]

Definition at line 2994 of file bridge.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ast_set_flag, bridge_hook_destroy(), ast_bridge_hook::callback, ast_bridge_hook::destructor, ast_bridge_hook::hook_pvt, and ast_bridge_hook::remove_flags.

Referenced by ast_bridge_dtmf_hook(), ast_bridge_interval_hook(), and bridge_other_hook().

02999 {
03000    struct ast_bridge_hook *hook;
03001 
03002    /* Allocate new hook and setup it's basic variables */
03003    hook = ao2_alloc_options(size, bridge_hook_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
03004    if (hook) {
03005       hook->callback = callback;
03006       hook->destructor = destructor;
03007       hook->hook_pvt = hook_pvt;
03008       ast_set_flag(&hook->remove_flags, remove_flags);
03009    }
03010 
03011    return hook;
03012 }

static struct bridge_manager_controller* bridge_manager_create ( void   )  [static, read]

Definition at line 4630 of file bridge.c.

References ao2_alloc, ao2_ref, ast_cond_init, AST_LIST_HEAD_INIT_NOLOCK, ast_pthread_create, AST_PTHREADT_NULL, bridge_manager_destroy(), bridge_manager_thread(), bridge_manager_controller::cond, NULL, bridge_manager_controller::service_requests, and bridge_manager_controller::thread.

Referenced by ast_bridging_init().

04631 {
04632    struct bridge_manager_controller *manager;
04633 
04634    manager = ao2_alloc(sizeof(*manager), bridge_manager_destroy);
04635    if (!manager) {
04636       /* Well. This isn't good. */
04637       return NULL;
04638    }
04639    ast_cond_init(&manager->cond, NULL);
04640    AST_LIST_HEAD_INIT_NOLOCK(&manager->service_requests);
04641 
04642    /* Create the bridge manager thread. */
04643    if (ast_pthread_create(&manager->thread, NULL, bridge_manager_thread, manager)) {
04644       /* Well. This isn't good either. */
04645       manager->thread = AST_PTHREADT_NULL;
04646       ao2_ref(manager, -1);
04647       manager = NULL;
04648    }
04649 
04650    return manager;
04651 }

static void bridge_manager_destroy ( void *  obj  )  [static]

Definition at line 4598 of file bridge.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_cond_destroy, ast_cond_signal, ast_debug, ast_free, AST_LIST_REMOVE_HEAD, AST_PTHREADT_NULL, bridge_manager_request::bridge, bridge_manager_controller::cond, NULL, request(), bridge_manager_controller::service_requests, bridge_manager_controller::stop, and bridge_manager_controller::thread.

Referenced by bridge_manager_create().

04599 {
04600    struct bridge_manager_controller *manager = obj;
04601    struct bridge_manager_request *request;
04602 
04603    if (manager->thread != AST_PTHREADT_NULL) {
04604       /* Stop the manager thread. */
04605       ao2_lock(manager);
04606       manager->stop = 1;
04607       ast_cond_signal(&manager->cond);
04608       ao2_unlock(manager);
04609       ast_debug(1, "Waiting for bridge manager thread to die.\n");
04610       pthread_join(manager->thread, NULL);
04611    }
04612 
04613    /* Destroy the service request queue. */
04614    while ((request = AST_LIST_REMOVE_HEAD(&manager->service_requests, node))) {
04615       ao2_ref(request->bridge, -1);
04616       ast_free(request);
04617    }
04618 
04619    ast_cond_destroy(&manager->cond);
04620 }

static void bridge_manager_service ( struct ast_bridge bridge  )  [static]

Definition at line 4544 of file bridge.c.

References ast_bridge_lock, ast_bridge_unlock, ast_callid_threadassoc_change(), bridge_handle_actions(), and ast_bridge::callid.

Referenced by bridge_manager_thread().

04545 {
04546    ast_bridge_lock(bridge);
04547    if (bridge->callid) {
04548       ast_callid_threadassoc_change(bridge->callid);
04549    }
04550 
04551    /* Do any pending bridge actions. */
04552    bridge_handle_actions(bridge);
04553    ast_bridge_unlock(bridge);
04554 }

static void bridge_manager_service_req ( struct ast_bridge bridge  )  [static]

Definition at line 173 of file bridge.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_calloc, ast_cond_signal, AST_LIST_INSERT_TAIL, bridge_manager_request::bridge, and request().

Referenced by bridge_queue_action_nodup().

00174 {
00175    struct bridge_manager_request *request;
00176 
00177    ao2_lock(bridge_manager);
00178    if (bridge_manager->stop) {
00179       ao2_unlock(bridge_manager);
00180       return;
00181    }
00182 
00183    /* Create the service request. */
00184    request = ast_calloc(1, sizeof(*request));
00185    if (!request) {
00186       /* Well. This isn't good. */
00187       ao2_unlock(bridge_manager);
00188       return;
00189    }
00190    ao2_ref(bridge, +1);
00191    request->bridge = bridge;
00192 
00193    /* Put request into the queue and wake the bridge manager. */
00194    AST_LIST_INSERT_TAIL(&bridge_manager->service_requests, request, node);
00195    ast_cond_signal(&bridge_manager->cond);
00196    ao2_unlock(bridge_manager);
00197 }

static void* bridge_manager_thread ( void *  data  )  [static]

Definition at line 4563 of file bridge.c.

References ao2_lock, ao2_object_get_lockaddr(), ao2_ref, ao2_unlock, ast_cond_wait, ast_free, AST_LIST_REMOVE_HEAD, bridge_manager_request::bridge, bridge_manager_service(), bridge_manager_controller::cond, NULL, request(), bridge_manager_controller::service_requests, and bridge_manager_controller::stop.

Referenced by bridge_manager_create().

04564 {
04565    struct bridge_manager_controller *manager = data;
04566    struct bridge_manager_request *request;
04567 
04568    ao2_lock(manager);
04569    while (!manager->stop) {
04570       request = AST_LIST_REMOVE_HEAD(&manager->service_requests, node);
04571       if (!request) {
04572          ast_cond_wait(&manager->cond, ao2_object_get_lockaddr(manager));
04573          continue;
04574       }
04575       ao2_unlock(manager);
04576 
04577       /* Service the bridge. */
04578       bridge_manager_service(request->bridge);
04579       ao2_ref(request->bridge, -1);
04580       ast_free(request);
04581 
04582       ao2_lock(manager);
04583    }
04584    ao2_unlock(manager);
04585 
04586    return NULL;
04587 }

static struct merge_direction bridge_merge_determine_direction ( struct ast_bridge bridge1,
struct ast_bridge bridge2 
) [static, read]

Definition at line 1972 of file bridge.c.

References AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO, ast_test_flag, merge_direction::dest, NULL, and merge_direction::src.

Referenced by bridge_merge_locked(), and bridges_allow_merge_optimization().

01973 {
01974    struct merge_direction merge = { NULL, NULL };
01975    int bridge1_priority;
01976    int bridge2_priority;
01977 
01978    if (!ast_test_flag(&bridge1->feature_flags,
01979          AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)
01980       && !ast_test_flag(&bridge2->feature_flags,
01981          AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
01982       /*
01983        * Can merge either way.  Merge to the higher priority merge
01984        * bridge.  Otherwise merge to the larger bridge.
01985        */
01986       bridge1_priority = bridge1->v_table->get_merge_priority(bridge1);
01987       bridge2_priority = bridge2->v_table->get_merge_priority(bridge2);
01988       if (bridge2_priority < bridge1_priority) {
01989          merge.dest = bridge1;
01990          merge.src = bridge2;
01991       } else if (bridge1_priority < bridge2_priority) {
01992          merge.dest = bridge2;
01993          merge.src = bridge1;
01994       } else {
01995          /* Merge to the larger bridge. */
01996          if (bridge2->num_channels <= bridge1->num_channels) {
01997             merge.dest = bridge1;
01998             merge.src = bridge2;
01999          } else {
02000             merge.dest = bridge2;
02001             merge.src = bridge1;
02002          }
02003       }
02004    } else if (!ast_test_flag(&bridge1->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
02005       && !ast_test_flag(&bridge2->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
02006       /* Can merge only one way. */
02007       merge.dest = bridge1;
02008       merge.src = bridge2;
02009    } else if (!ast_test_flag(&bridge2->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
02010       && !ast_test_flag(&bridge1->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
02011       /* Can merge only one way. */
02012       merge.dest = bridge2;
02013       merge.src = bridge1;
02014    }
02015 
02016    return merge;
02017 }

void bridge_merge_inhibit_nolock ( struct ast_bridge bridge,
int  request 
)

Definition at line 2821 of file bridge.c.

References ast_assert, and ast_bridge::inhibit_merge.

Referenced by ast_bridge_channel_merge_inhibit(), and ast_bridge_merge_inhibit().

02822 {
02823    int new_request;
02824 
02825    new_request = bridge->inhibit_merge + request;
02826    ast_assert(0 <= new_request);
02827    bridge->inhibit_merge = new_request;
02828 }

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 
) [static]

Definition at line 2035 of file bridge.c.

References ast_bridge::allowed_capabilities, ast_alloca, ast_assert, AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_FLAG_MASQUERADE_ONLY, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO, AST_BRIDGE_FLAG_SMART, ast_debug, ast_test_flag, bridge_do_merge(), bridge_find_channel(), bridge_merge_determine_direction(), ast_bridge_technology::capabilities, merge_direction::dest, ast_bridge::dissolved, ast_bridge::feature_flags, ast_bridge::inhibit_merge, NULL, ast_bridge::num_channels, merge_direction::src, ast_bridge::technology, and ast_bridge::uniqueid.

Referenced by ast_bridge_merge().

02036 {
02037    struct merge_direction merge;
02038    struct ast_bridge_channel **kick_them = NULL;
02039 
02040    /* Sanity check. */
02041    ast_assert(dst_bridge && src_bridge && dst_bridge != src_bridge && (!num_kick || kick_me));
02042 
02043    if (dst_bridge->dissolved || src_bridge->dissolved) {
02044       ast_debug(1, "Can't merge bridges %s and %s, at least one bridge is dissolved.\n",
02045          src_bridge->uniqueid, dst_bridge->uniqueid);
02046       return -1;
02047    }
02048    if (ast_test_flag(&dst_bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)
02049       || ast_test_flag(&src_bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)) {
02050       ast_debug(1, "Can't merge bridges %s and %s, masquerade only.\n",
02051          src_bridge->uniqueid, dst_bridge->uniqueid);
02052       return -1;
02053    }
02054    if (dst_bridge->inhibit_merge || src_bridge->inhibit_merge) {
02055       ast_debug(1, "Can't merge bridges %s and %s, merging temporarily inhibited.\n",
02056          src_bridge->uniqueid, dst_bridge->uniqueid);
02057       return -1;
02058    }
02059 
02060    if (merge_best_direction) {
02061       merge = bridge_merge_determine_direction(dst_bridge, src_bridge);
02062    } else {
02063       merge.dest = dst_bridge;
02064       merge.src = src_bridge;
02065    }
02066 
02067    if (!merge.dest
02068       || ast_test_flag(&merge.dest->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
02069       || ast_test_flag(&merge.src->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
02070       ast_debug(1, "Can't merge bridges %s and %s, merging inhibited.\n",
02071          src_bridge->uniqueid, dst_bridge->uniqueid);
02072       return -1;
02073    }
02074    if (merge.src->num_channels < 2) {
02075       /*
02076        * For a two party bridge, a channel may be temporarily removed
02077        * from the source bridge or the initial bridge members have not
02078        * joined yet.
02079        */
02080       ast_debug(1, "Can't merge bridge %s into bridge %s, not enough channels in source bridge.\n",
02081          merge.src->uniqueid, merge.dest->uniqueid);
02082       return -1;
02083    }
02084    if (2 + num_kick < merge.dest->num_channels + merge.src->num_channels
02085       && !(merge.dest->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)
02086       && (!ast_test_flag(&merge.dest->feature_flags, AST_BRIDGE_FLAG_SMART)
02087          || !(merge.dest->allowed_capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX))) {
02088       ast_debug(1, "Can't merge bridge %s into bridge %s, multimix is needed and it cannot be acquired.\n",
02089          merge.src->uniqueid, merge.dest->uniqueid);
02090       return -1;
02091    }
02092 
02093    if (num_kick) {
02094       unsigned int num_to_kick = 0;
02095       unsigned int idx;
02096 
02097       kick_them = ast_alloca(num_kick * sizeof(*kick_them));
02098       for (idx = 0; idx < num_kick; ++idx) {
02099          kick_them[num_to_kick] = bridge_find_channel(merge.src, kick_me[idx]);
02100          if (!kick_them[num_to_kick]) {
02101             kick_them[num_to_kick] = bridge_find_channel(merge.dest, kick_me[idx]);
02102          }
02103          if (kick_them[num_to_kick]) {
02104             ++num_to_kick;
02105          }
02106       }
02107 
02108       if (num_to_kick != num_kick) {
02109          ast_debug(1, "Can't merge bridge %s into bridge %s, at least one kicked channel is not in either bridge.\n",
02110             merge.src->uniqueid, merge.dest->uniqueid);
02111          return -1;
02112       }
02113    }
02114 
02115    bridge_do_merge(merge.dest, merge.src, kick_them, num_kick, 0);
02116    return 0;
02117 }

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 
) [static]

Definition at line 2219 of file bridge.c.

References AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE, AST_BRIDGE_FLAG_MASQUERADE_ONLY, ast_channel_name(), ast_debug, ast_test_flag, BRIDGE_CHANNEL_STATE_WAIT, bridge_do_move(), bridge_find_channel(), ast_bridge::dissolved, ast_bridge_features::feature_flags, ast_bridge::feature_flags, ast_bridge_channel::features, ast_bridge::inhibit_merge, ast_bridge_channel::state, ast_bridge_channel::swap, and ast_bridge::uniqueid.

Referenced by ast_bridge_add_channel(), and ast_bridge_move().

02220 {
02221    struct ast_bridge_channel *bridge_channel;
02222 
02223    if (dst_bridge->dissolved || src_bridge->dissolved) {
02224       ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, at least one bridge is dissolved.\n",
02225          ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
02226       return -1;
02227    }
02228    if (ast_test_flag(&dst_bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)
02229       || ast_test_flag(&src_bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)) {
02230       ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, masquerade only.\n",
02231          ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
02232       return -1;
02233    }
02234    if (dst_bridge->inhibit_merge || src_bridge->inhibit_merge) {
02235       ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, temporarily inhibited.\n",
02236          ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
02237       return -1;
02238    }
02239 
02240    bridge_channel = bridge_find_channel(src_bridge, chan);
02241    if (!bridge_channel) {
02242       ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel not in bridge.\n",
02243          ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
02244       return -1;
02245    }
02246    if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
02247       ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel leaving bridge.\n",
02248          ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
02249       return -1;
02250    }
02251    if (ast_test_flag(&bridge_channel->features->feature_flags,
02252       AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE)) {
02253       ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel immovable.\n",
02254          ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
02255       return -1;
02256    }
02257 
02258    if (swap) {
02259       struct ast_bridge_channel *bridge_channel_swap;
02260 
02261       bridge_channel_swap = bridge_find_channel(dst_bridge, swap);
02262       if (!bridge_channel_swap) {
02263          ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, swap channel %s not in bridge.\n",
02264             ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid,
02265             ast_channel_name(swap));
02266          return -1;
02267       }
02268       if (bridge_channel_swap->state != BRIDGE_CHANNEL_STATE_WAIT) {
02269          ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, swap channel %s leaving bridge.\n",
02270             ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid,
02271             ast_channel_name(swap));
02272          return -1;
02273       }
02274    }
02275 
02276    bridge_channel->swap = swap;
02277    return bridge_do_move(dst_bridge, bridge_channel, attempt_recovery, 0);
02278 }

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 
) [static]

Definition at line 3063 of file bridge.c.

References ao2_link, ao2_ref, bridge_hook_generic(), ast_bridge_hook::destructor, NULL, ast_bridge_features::other_hooks, and ast_bridge_hook::type.

Referenced by ast_bridge_hangup_hook(), ast_bridge_join_hook(), ast_bridge_leave_hook(), ast_bridge_move_hook(), and ast_bridge_talk_detector_hook().

03069 {
03070    struct ast_bridge_hook *hook;
03071    int res;
03072 
03073    /* Allocate new hook and setup it's various variables */
03074    hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor,
03075       remove_flags);
03076    if (!hook) {
03077       return -1;
03078    }
03079    hook->type = type;
03080 
03081    /* Once done we put it in the container. */
03082    res = ao2_link(features->other_hooks, hook) ? 0 : -1;
03083    if (res) {
03084       /*
03085        * Could not link the hook into the container.
03086        *
03087        * Remove the hook_pvt destructor call from the hook since we
03088        * are returning failure to install the hook.
03089        */
03090       hook->destructor = NULL;
03091    }
03092    ao2_ref(hook, -1);
03093 
03094    return res;
03095 }

static void bridge_prnt_obj ( void *  v_obj,
void *  where,
ao2_prnt_fn prnt 
) [static]

Definition at line 5239 of file bridge.c.

References ast_bridge_methods::name, ast_bridge::num_channels, ast_bridge::uniqueid, and ast_bridge::v_table.

Referenced by ast_bridging_init().

05240 {
05241    struct ast_bridge *bridge = v_obj;
05242 
05243    if (!bridge) {
05244       return;
05245    }
05246    prnt(where, "%s %s chans:%u",
05247       bridge->uniqueid, bridge->v_table->name, bridge->num_channels);
05248 }

static void bridge_queue_action_nodup ( struct ast_bridge bridge,
struct ast_frame action 
) [static]

Definition at line 268 of file bridge.c.

References ast_bridge::action_queue, ast_bridge_lock, ast_bridge_unlock, ast_debug, AST_LIST_INSERT_TAIL, bridge_manager_service_req(), ast_frame::frametype, ast_frame_subclass::integer, ast_frame::subclass, and ast_bridge::uniqueid.

Referenced by ast_bridge_queue_action(), and smart_bridge_operation().

00269 {
00270    ast_debug(1, "Bridge %s: queueing action type:%u sub:%d\n",
00271       bridge->uniqueid, action->frametype, action->subclass.integer);
00272 
00273    ast_bridge_lock(bridge);
00274    AST_LIST_INSERT_TAIL(&bridge->action_queue, action, frame_list);
00275    ast_bridge_unlock(bridge);
00276    bridge_manager_service_req(bridge);
00277 }

void bridge_reconfigured ( struct ast_bridge bridge,
unsigned int  colp_update 
)

Definition at line 1415 of file bridge.c.

References AST_BRIDGE_FLAG_SMART, ast_bridge_publish_state(), ast_test_flag, bridge_complete_join(), bridge_dissolve(), bridge_reconfigured_connected_line_update(), check_bridge_play_sounds(), ast_bridge::dissolved, ast_bridge::feature_flags, ast_bridge::reconfigured, set_bridge_peer_vars(), and smart_bridge_operation().

Referenced by ast_bridge_notify_masquerade(), bridge_channel_internal_join(), bridge_channel_wait(), bridge_do_merge(), and bridge_do_move().

01416 {
01417    if (!bridge->reconfigured) {
01418       return;
01419    }
01420    bridge->reconfigured = 0;
01421    if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART)
01422       && smart_bridge_operation(bridge)) {
01423       /* Smart bridge failed. */
01424       bridge_dissolve(bridge, 0);
01425       return;
01426    }
01427    bridge_complete_join(bridge);
01428 
01429    if (bridge->dissolved) {
01430       return;
01431    }
01432    check_bridge_play_sounds(bridge);
01433    set_bridge_peer_vars(bridge);
01434    ast_bridge_publish_state(bridge);
01435 
01436    if (colp_update) {
01437       bridge_reconfigured_connected_line_update(bridge);
01438    }
01439 }

static void bridge_reconfigured_connected_line_update ( struct ast_bridge bridge  )  [static]

Definition at line 365 of file bridge.c.

References AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_NATIVE, ast_bridge_channel_peer(), ast_bridge_channel_queue_control_data(), ast_channel_caller(), ast_channel_flags(), ast_channel_lock, ast_channel_unlock, ast_check_hangup_locked(), ast_connected_line_build_data(), ast_connected_line_copy_from_caller(), AST_CONTROL_CONNECTED_LINE, AST_FLAG_ZOMBIE, AST_LIST_FIRST, ast_party_connected_line_free(), ast_party_connected_line_init(), ast_test_flag, ast_bridge_technology::capabilities, ast_bridge_channel::chan, ast_bridge::channels, NULL, and ast_bridge::technology.

Referenced by bridge_reconfigured().

00366 {
00367    struct ast_party_connected_line connected;
00368    struct ast_bridge_channel *bridge_channel = AST_LIST_FIRST(&bridge->channels), *peer;
00369    unsigned char data[1024];
00370    size_t datalen;
00371 
00372    if (!bridge_channel ||
00373       !(bridge->technology->capabilities & (AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_NATIVE)) ||
00374       !(peer = ast_bridge_channel_peer(bridge_channel)) ||
00375       ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_ZOMBIE) ||
00376       ast_test_flag(ast_channel_flags(peer->chan), AST_FLAG_ZOMBIE) ||
00377       ast_check_hangup_locked(bridge_channel->chan) ||
00378       ast_check_hangup_locked(peer->chan)) {
00379       return;
00380    }
00381 
00382    ast_party_connected_line_init(&connected);
00383 
00384    ast_channel_lock(bridge_channel->chan);
00385    ast_connected_line_copy_from_caller(&connected, ast_channel_caller(bridge_channel->chan));
00386    ast_channel_unlock(bridge_channel->chan);
00387 
00388    if ((datalen = ast_connected_line_build_data(data, sizeof(data), &connected, NULL)) != (size_t) -1) {
00389       ast_bridge_channel_queue_control_data(peer, AST_CONTROL_CONNECTED_LINE, data, datalen);
00390    }
00391 
00392    ast_channel_lock(peer->chan);
00393    ast_connected_line_copy_from_caller(&connected, ast_channel_caller(peer->chan));
00394    ast_channel_unlock(peer->chan);
00395 
00396    if ((datalen = ast_connected_line_build_data(data, sizeof(data), &connected, NULL)) != (size_t) -1) {
00397       ast_bridge_channel_queue_control_data(bridge_channel, AST_CONTROL_CONNECTED_LINE, data, datalen);
00398    }
00399 
00400    ast_party_connected_line_free(&connected);
00401 }

struct ast_bridge* bridge_register ( struct ast_bridge bridge  )  [read]

Register the new bridge with the system.

Since:
12.0.0
Parameters:
bridge What to register. (Tolerates a NULL pointer)
 struct ast_bridge *ast_bridge_basic_new(uint32_t capabilities, int flags, uint32 dtmf_features)
 {
     void *bridge;

     bridge = bridge_alloc(sizeof(struct ast_bridge_basic), &ast_bridge_basic_v_table);
     bridge = bridge_base_init(bridge, capabilities, flags);
     bridge = ast_bridge_basic_init(bridge, dtmf_features);
     bridge = bridge_register(bridge);
     return bridge;
 }

Note:
This must be done after a bridge constructor has completed setting up the new bridge but before it returns.

After a bridge is registered, ast_bridge_destroy() must eventually be called to get rid of the bridge.

Return values:
bridge on success.
NULL on error.

Definition at line 689 of file bridge.c.

References ao2_link, ast_bridge_destroy(), ast_bridge_lock, ast_bridge_publish_state(), ast_bridge_unlock, ast_bridge::construction_completed, and NULL.

Referenced by ast_bridge_base_new(), ast_bridge_basic_new(), bridge_agent_hold_new(), bridge_parking_new(), and bridge_stasis_new().

00690 {
00691    if (bridge) {
00692       bridge->construction_completed = 1;
00693       ast_bridge_lock(bridge);
00694       ast_bridge_publish_state(bridge);
00695       ast_bridge_unlock(bridge);
00696       if (!ao2_link(bridges, bridge)) {
00697          ast_bridge_destroy(bridge, 0);
00698          bridge = NULL;
00699       }
00700    }
00701    return bridge;
00702 }

static int bridge_show_specific_print_channel ( void *  obj,
void *  arg,
int  flags 
) [static]

Internal callback function for sending channels in a bridge to the CLI.

Definition at line 4805 of file bridge.c.

References a, ao2_cleanup, ast_channel_cache(), ast_channel_snapshot_type(), ast_cli(), ast_cli_args::fd, ast_channel_snapshot::name, NULL, RAII_VAR, stasis_cache_get(), stasis_message_data(), and ast_bridge_snapshot::uniqueid.

Referenced by handle_bridge_show_specific().

04806 {
04807    const char *uniqueid = obj;
04808    struct ast_cli_args *a = arg;
04809    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
04810    struct ast_channel_snapshot *snapshot;
04811 
04812    msg = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(), uniqueid);
04813    if (!msg) {
04814       return 0;
04815    }
04816    snapshot = stasis_message_data(msg);
04817 
04818    ast_cli(a->fd, "Channel: %s\n", snapshot->name);
04819 
04820    return 0;
04821 }

static int bridge_sort_cmp ( const void *  obj_left,
const void *  obj_right,
int  flags 
) [static]

Definition at line 4669 of file bridge.c.

References OBJ_KEY, OBJ_PARTIAL_KEY, OBJ_POINTER, and ast_bridge::uniqueid.

Referenced by ast_bridging_init().

04670 {
04671    const struct ast_bridge *bridge_left = obj_left;
04672    const struct ast_bridge *bridge_right = obj_right;
04673    const char *right_key = obj_right;
04674    int cmp;
04675 
04676    switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
04677    default:
04678    case OBJ_POINTER:
04679       right_key = bridge_right->uniqueid;
04680       /* Fall through */
04681    case OBJ_KEY:
04682       cmp = strcmp(bridge_left->uniqueid, right_key);
04683       break;
04684    case OBJ_PARTIAL_KEY:
04685       cmp = strncmp(bridge_left->uniqueid, right_key, strlen(right_key));
04686       break;
04687    }
04688    return cmp;
04689 }

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 
) [static]

Definition at line 4264 of file bridge.c.

References AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE, ast_bridge_channel_leave_bridge(), ast_bridge_channel_peer(), AST_BRIDGE_TRANSFER_FAIL, AST_BRIDGE_TRANSFER_INVALID, AST_BRIDGE_TRANSFER_SUCCESS, AST_CAUSE_NORMAL_CLEARING, ast_test_flag, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, BRIDGE_CHANNEL_STATE_WAIT, bridge_do_move(), ast_bridge_features::feature_flags, ast_bridge_channel::features, ast_bridge_channel::state, and ast_bridge_channel::swap.

Referenced by two_bridge_attended_transfer().

04266 {
04267    struct ast_bridge_channel *bridged_to_source;
04268 
04269    bridged_to_source = ast_bridge_channel_peer(source_bridge_channel);
04270    if (bridged_to_source
04271       && bridged_to_source->state == BRIDGE_CHANNEL_STATE_WAIT
04272       && !ast_test_flag(&bridged_to_source->features->feature_flags,
04273          AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE)) {
04274       bridged_to_source->swap = swap_channel;
04275       if (bridge_do_move(dest_bridge, bridged_to_source, 1, 0)) {
04276          return AST_BRIDGE_TRANSFER_FAIL;
04277       }
04278       /* Must kick the source channel out of its bridge. */
04279       ast_bridge_channel_leave_bridge(source_bridge_channel,
04280          BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
04281       return AST_BRIDGE_TRANSFER_SUCCESS;
04282    } else {
04283       return AST_BRIDGE_TRANSFER_INVALID;
04284    }
04285 }

static void bridge_tech_deferred_destroy ( struct ast_bridge bridge,
struct ast_frame action 
) [static]

Definition at line 526 of file bridge.c.

References ast_debug, ast_module_unref, ast_bridge::creator, ast_frame::data, ast_bridge_technology::destroy, ast_bridge_technology::mod, ast_bridge_technology::name, ast_bridge::name, ast_frame::ptr, tech_deferred_destroy::tech, tech_deferred_destroy::tech_pvt, ast_bridge::technology, and ast_bridge::uniqueid.

Referenced by bridge_action_bridge().

00527 {
00528    struct tech_deferred_destroy *deferred = action->data.ptr;
00529    struct ast_bridge dummy_bridge = {
00530       .technology = deferred->tech,
00531       .tech_pvt = deferred->tech_pvt,
00532       .creator = bridge->creator,
00533       .name = bridge->name,
00534       .uniqueid = bridge->uniqueid,
00535       };
00536 
00537    ast_debug(1, "Bridge %s: calling %s technology destructor (deferred, dummy)\n",
00538       dummy_bridge.uniqueid, dummy_bridge.technology->name);
00539    dummy_bridge.technology->destroy(&dummy_bridge);
00540    ast_module_unref(dummy_bridge.technology->mod);
00541 }

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 
) [static]

static enum bridge_allow_swap bridges_allow_swap_optimization ( struct ast_bridge chan_bridge,
struct ast_bridge peer_bridge 
) [static]

Definition at line 2506 of file bridge.c.

References AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM, AST_BRIDGE_FLAG_SWAP_INHIBIT_TO, AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY, ast_test_flag, ast_bridge::feature_flags, ast_bridge_methods::get_merge_priority, ast_bridge::num_channels, SWAP_PROHIBITED, SWAP_TO_CHAN_BRIDGE, SWAP_TO_PEER_BRIDGE, and ast_bridge::v_table.

Referenced by ast_bridges_allow_optimization(), and try_swap_optimize_out().

02508 {
02509    int chan_priority;
02510    int peer_priority;
02511 
02512    if (!ast_test_flag(&chan_bridge->feature_flags,
02513          AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM |
02514          AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY)
02515       && !ast_test_flag(&peer_bridge->feature_flags,
02516          AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM |
02517          AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY)) {
02518       /*
02519        * Can swap either way.  Swap to the higher priority merge
02520        * bridge.
02521        */
02522       chan_priority = chan_bridge->v_table->get_merge_priority(chan_bridge);
02523       peer_priority = peer_bridge->v_table->get_merge_priority(peer_bridge);
02524       if (chan_bridge->num_channels == 2
02525          && chan_priority <= peer_priority) {
02526          return SWAP_TO_PEER_BRIDGE;
02527       } else if (peer_bridge->num_channels == 2
02528          && peer_priority <= chan_priority) {
02529          return SWAP_TO_CHAN_BRIDGE;
02530       }
02531    } else if (chan_bridge->num_channels == 2
02532       && !ast_test_flag(&chan_bridge->feature_flags, AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY)
02533       && !ast_test_flag(&peer_bridge->feature_flags, AST_BRIDGE_FLAG_SWAP_INHIBIT_TO)) {
02534       /* Can swap optimize only one way. */
02535       return SWAP_TO_PEER_BRIDGE;
02536    } else if (peer_bridge->num_channels == 2
02537       && !ast_test_flag(&peer_bridge->feature_flags, AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY)
02538       && !ast_test_flag(&chan_bridge->feature_flags, AST_BRIDGE_FLAG_SWAP_INHIBIT_TO)) {
02539       /* Can swap optimize only one way. */
02540       return SWAP_TO_CHAN_BRIDGE;
02541    }
02542 
02543    return SWAP_PROHIBITED;
02544 }

static int channel_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 3735 of file bridge.c.

References ast_channel_name(), CMP_MATCH, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by ast_bridge_peers_nolock().

03736 {
03737    const struct ast_channel *left = obj;
03738    const struct ast_channel *right = arg;
03739    const char *right_name = arg;
03740    int cmp;
03741 
03742    switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
03743    default:
03744    case OBJ_POINTER:
03745       right_name = ast_channel_name(right);
03746       /* Fall through */
03747    case OBJ_KEY:
03748       cmp = strcmp(ast_channel_name(left), right_name);
03749       break;
03750    case OBJ_PARTIAL_KEY:
03751       cmp = strncmp(ast_channel_name(left), right_name, strlen(right_name));
03752       break;
03753    }
03754    return cmp ? 0 : CMP_MATCH;
03755 }

static int channel_hash ( const void *  obj,
int  flags 
) [static]

Definition at line 3712 of file bridge.c.

References ast_assert, ast_channel_name(), ast_str_hash(), name, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by ast_bridge_peers_nolock().

03713 {
03714    const struct ast_channel *chan = obj;
03715    const char *name = obj;
03716    int hash;
03717 
03718    switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
03719    default:
03720    case OBJ_POINTER:
03721       name = ast_channel_name(chan);
03722       /* Fall through */
03723    case OBJ_KEY:
03724       hash = ast_str_hash(name);
03725       break;
03726    case OBJ_PARTIAL_KEY:
03727       /* Should never happen in hash callback. */
03728       ast_assert(0);
03729       hash = 0;
03730       break;
03731    }
03732    return hash;
03733 }

static void check_bridge_play_sound ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 1175 of file bridge.c.

References ast_bridge_channel_queue_playfile(), ast_channel_lock, ast_channel_unlock, ast_strdupa, ast_strlen_zero, ast_bridge_channel::chan, NULL, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and play_file().

Referenced by check_bridge_play_sounds().

01176 {
01177    const char *play_file;
01178 
01179    ast_channel_lock(bridge_channel->chan);
01180    play_file = pbx_builtin_getvar_helper(bridge_channel->chan, "BRIDGE_PLAY_SOUND");
01181    if (!ast_strlen_zero(play_file)) {
01182       play_file = ast_strdupa(play_file);
01183       pbx_builtin_setvar_helper(bridge_channel->chan, "BRIDGE_PLAY_SOUND", NULL);
01184    } else {
01185       play_file = NULL;
01186    }
01187    ast_channel_unlock(bridge_channel->chan);
01188 
01189    if (play_file) {
01190       ast_bridge_channel_queue_playfile(bridge_channel, NULL, play_file, NULL);
01191    }
01192 }

static void check_bridge_play_sounds ( struct ast_bridge bridge  )  [static]

Definition at line 1205 of file bridge.c.

References AST_LIST_TRAVERSE, ast_bridge::channels, and check_bridge_play_sound().

Referenced by bridge_reconfigured().

01206 {
01207    struct ast_bridge_channel *bridge_channel;
01208 
01209    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
01210       check_bridge_play_sound(bridge_channel);
01211    }
01212 }

static void cleanup_video_mode ( struct ast_bridge bridge  )  [static]

static char* complete_bridge_live ( const char *  word,
int  state 
) [static]

Definition at line 4713 of file bridge.c.

References ao2_callback_data, ao2_ref, ast_strdup, ast_strlen_zero, complete_bridge_live_search(), NULL, OBJ_PARTIAL_KEY, bridge_complete::state, and ast_bridge::uniqueid.

Referenced by handle_bridge_kick_channel().

04714 {
04715    char *ret;
04716    struct ast_bridge *bridge;
04717    struct bridge_complete search = {
04718       .state = state,
04719       };
04720 
04721    bridge = ao2_callback_data(bridges, ast_strlen_zero(word) ? 0 : OBJ_PARTIAL_KEY,
04722       complete_bridge_live_search, (char *) word, &search);
04723    if (!bridge) {
04724       return NULL;
04725    }
04726    ret = ast_strdup(bridge->uniqueid);
04727    ao2_ref(bridge, -1);
04728    return ret;
04729 }

static int complete_bridge_live_search ( void *  obj,
void *  arg,
void *  data,
int  flags 
) [static]

Definition at line 4703 of file bridge.c.

References CMP_MATCH, bridge_complete::state, and bridge_complete::which.

Referenced by complete_bridge_live().

04704 {
04705    struct bridge_complete *search = data;
04706 
04707    if (++search->which > search->state) {
04708       return CMP_MATCH;
04709    }
04710    return 0;
04711 }

static char* complete_bridge_participant ( const char *  bridge_name,
const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 4898 of file bridge.c.

References ao2_ref, ast_bridge_find_by_id(), ast_bridge_lock, ast_bridge_unlock, ast_channel_name(), AST_LIST_TRAVERSE, ast_strdup, ast_bridge_channel::chan, ast_bridge::channels, NULL, and SCOPED_LOCK.

Referenced by handle_bridge_kick_channel().

04899 {
04900    struct ast_bridge *bridge;
04901    struct ast_bridge_channel *bridge_channel;
04902    int which;
04903    int wordlen;
04904 
04905    bridge = ast_bridge_find_by_id(bridge_name);
04906    if (!bridge) {
04907       return NULL;
04908    }
04909 
04910    if (!state) {
04911       ao2_ref(bridge, -1);
04912       return ast_strdup("all");
04913    }
04914    state--;
04915 
04916    {
04917       SCOPED_LOCK(bridge_lock, bridge, ast_bridge_lock, ast_bridge_unlock);
04918 
04919       which = 0;
04920       wordlen = strlen(word);
04921       AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
04922          if (!strncasecmp(ast_channel_name(bridge_channel->chan), word, wordlen)
04923             && ++which > state) {
04924             ao2_ref(bridge, -1);
04925             return ast_strdup(ast_channel_name(bridge_channel->chan));
04926          }
04927       }
04928    }
04929 
04930    ao2_ref(bridge, -1);
04931 
04932    return NULL;
04933 }

static char* complete_bridge_stasis ( const char *  word,
int  state 
) [static]

Definition at line 4731 of file bridge.c.

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_bridge_cache(), ast_bridge_snapshot_type(), ast_strdup, NULL, RAII_VAR, stasis_cache_dump(), stasis_message_data(), ast_bridge_snapshot::uniqueid, and bridge_complete::which.

Referenced by handle_bridge_show_specific().

04732 {
04733    char *ret = NULL;
04734    int wordlen = strlen(word), which = 0;
04735    RAII_VAR(struct ao2_container *, cached_bridges, NULL, ao2_cleanup);
04736    struct ao2_iterator iter;
04737    struct stasis_message *msg;
04738 
04739    cached_bridges = stasis_cache_dump(ast_bridge_cache(), ast_bridge_snapshot_type());
04740    if (!cached_bridges) {
04741       return NULL;
04742    }
04743 
04744    iter = ao2_iterator_init(cached_bridges, 0);
04745    for (; (msg = ao2_iterator_next(&iter)); ao2_ref(msg, -1)) {
04746       struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);
04747 
04748       if (!strncasecmp(word, snapshot->uniqueid, wordlen) && (++which > state)) {
04749          ret = ast_strdup(snapshot->uniqueid);
04750          ao2_ref(msg, -1);
04751          break;
04752       }
04753    }
04754    ao2_iterator_destroy(&iter);
04755 
04756    return ret;
04757 }

static char* complete_bridge_technology ( const char *  word,
int  state 
) [static]

Definition at line 5054 of file bridge.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_bridge_technology::name, and NULL.

Referenced by handle_bridge_technology_suspend().

05055 {
05056    struct ast_bridge_technology *cur;
05057    char *res;
05058    int which;
05059    int wordlen;
05060 
05061    which = 0;
05062    wordlen = strlen(word);
05063    AST_RWLIST_RDLOCK(&bridge_technologies);
05064    AST_RWLIST_TRAVERSE(&bridge_technologies, cur, entry) {
05065       if (!strncasecmp(cur->name, word, wordlen) && ++which > state) {
05066          res = ast_strdup(cur->name);
05067          AST_RWLIST_UNLOCK(&bridge_technologies);
05068          return res;
05069       }
05070    }
05071    AST_RWLIST_UNLOCK(&bridge_technologies);
05072    return NULL;
05073 }

static struct stasis_message* create_bridge_snapshot_message ( struct ast_bridge bridge  )  [static, read]

Definition at line 610 of file bridge.c.

References ao2_cleanup, ast_bridge_lock, ast_bridge_snapshot_create(), ast_bridge_snapshot_type(), ast_bridge_unlock, NULL, RAII_VAR, and stasis_message_create().

Referenced by destroy_bridge().

00611 {
00612    RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
00613 
00614    if (!ast_bridge_snapshot_type()) {
00615       return NULL;
00616    }
00617 
00618    ast_bridge_lock(bridge);
00619    snapshot = ast_bridge_snapshot_create(bridge);
00620    ast_bridge_unlock(bridge);
00621 
00622    if (!snapshot) {
00623       return NULL;
00624    }
00625 
00626    return stasis_message_create(ast_bridge_snapshot_type(), snapshot);
00627 }

static void destroy_bridge ( void *  obj  )  [static]

Definition at line 629 of file bridge.c.

References ao2_cleanup, ast_assert, ast_bridge_lock, ast_bridge_topic(), ast_bridge_unlock, ast_debug, AST_LIST_EMPTY, ast_module_unref, ast_string_field_free_memory, bridge_handle_actions(), ast_bridge::callid, ast_bridge::channels, cleanup_video_mode(), ast_bridge::construction_completed, create_bridge_snapshot_message(), ast_bridge_technology::destroy, ast_bridge_methods::destroy, ast_bridge_technology::mod, ast_bridge_technology::name, ast_bridge_methods::name, NULL, RAII_VAR, stasis_cache_clear_create(), stasis_cp_single_unsubscribe(), stasis_publish(), ast_bridge_technology::stop, ast_bridge::technology, ast_bridge::topics, ast_bridge::uniqueid, and ast_bridge::v_table.

Referenced by bridge_alloc().

00630 {
00631    struct ast_bridge *bridge = obj;
00632 
00633    ast_debug(1, "Bridge %s: actually destroying %s bridge, nobody wants it anymore\n",
00634       bridge->uniqueid, bridge->v_table->name);
00635 
00636    if (bridge->construction_completed) {
00637       RAII_VAR(struct stasis_message *, clear_msg, NULL, ao2_cleanup);
00638 
00639       clear_msg = create_bridge_snapshot_message(bridge);
00640       if (clear_msg) {
00641          RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
00642 
00643          msg = stasis_cache_clear_create(clear_msg);
00644          if (msg) {
00645             stasis_publish(ast_bridge_topic(bridge), msg);
00646          }
00647       }
00648    }
00649 
00650    /* Do any pending actions in the context of destruction. */
00651    ast_bridge_lock(bridge);
00652    bridge_handle_actions(bridge);
00653    ast_bridge_unlock(bridge);
00654 
00655    /* There should not be any channels left in the bridge. */
00656    ast_assert(AST_LIST_EMPTY(&bridge->channels));
00657 
00658    ast_debug(1, "Bridge %s: calling %s bridge destructor\n",
00659       bridge->uniqueid, bridge->v_table->name);
00660    bridge->v_table->destroy(bridge);
00661 
00662    /* Pass off the bridge to the technology to destroy if needed */
00663    if (bridge->technology) {
00664       ast_debug(1, "Bridge %s: calling %s technology stop\n",
00665          bridge->uniqueid, bridge->technology->name);
00666       if (bridge->technology->stop) {
00667          ast_bridge_lock(bridge);
00668          bridge->technology->stop(bridge);
00669          ast_bridge_unlock(bridge);
00670       }
00671       ast_debug(1, "Bridge %s: calling %s technology destructor\n",
00672          bridge->uniqueid, bridge->technology->name);
00673       if (bridge->technology->destroy) {
00674          bridge->technology->destroy(bridge);
00675       }
00676       ast_module_unref(bridge->technology->mod);
00677       bridge->technology = NULL;
00678    }
00679 
00680    bridge->callid = 0;
00681 
00682    cleanup_video_mode(bridge);
00683 
00684    stasis_cp_single_unsubscribe(bridge->topics);
00685 
00686    ast_string_field_free_memory(bridge);
00687 }

static void fill_bridgepeer_buf ( char *  buf,
unsigned int  cur_idx,
const char *  names[],
unsigned int  num_names 
) [static]

Definition at line 1275 of file bridge.c.

Referenced by set_bridge_peer_vars_multiparty().

01276 {
01277    int need_separator = 0;
01278    unsigned int idx;
01279    const char *src;
01280    char *pos;
01281 
01282    pos = buf;
01283    for (idx = 0; idx < num_names; ++idx) {
01284       if (idx == cur_idx) {
01285          continue;
01286       }
01287 
01288       if (need_separator) {
01289          *pos++ = ',';
01290       }
01291       need_separator = 1;
01292 
01293       /* Copy name into buffer. */
01294       src = names[idx];
01295       while (*src) {
01296          *pos++ = *src++;
01297       }
01298    }
01299    *pos = '\0';
01300 }

static struct ast_bridge_technology* find_best_technology ( uint32_t  capabilities,
struct ast_bridge bridge 
) [static, read]

Helper function used to find the "best" bridge technology given specified capabilities.

Definition at line 468 of file bridge.c.

References ast_debug, ast_module_ref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_bridge_technology::capabilities, ast_bridge_technology::compatible, ast_bridge_technology::mod, ast_bridge_technology::name, NULL, ast_bridge_technology::preference, and ast_bridge_technology::suspended.

Referenced by bridge_base_init(), and smart_bridge_operation().

00469 {
00470    struct ast_bridge_technology *current;
00471    struct ast_bridge_technology *best = NULL;
00472 
00473    AST_RWLIST_RDLOCK(&bridge_technologies);
00474    AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) {
00475       if (current->suspended) {
00476          ast_debug(1, "Bridge technology %s is suspended. Skipping.\n",
00477             current->name);
00478          continue;
00479       }
00480       if (!(current->capabilities & capabilities)) {
00481          ast_debug(1, "Bridge technology %s does not have any capabilities we want.\n",
00482             current->name);
00483          continue;
00484       }
00485       if (best && current->preference <= best->preference) {
00486          ast_debug(1, "Bridge technology %s has less preference than %s (%u <= %u). Skipping.\n",
00487             current->name, best->name, current->preference, best->preference);
00488          continue;
00489       }
00490       if (current->compatible && !current->compatible(bridge)) {
00491          ast_debug(1, "Bridge technology %s is not compatible with properties of existing bridge.\n",
00492             current->name);
00493          continue;
00494       }
00495       best = current;
00496    }
00497 
00498    if (best) {
00499       /* Increment it's module reference count if present so it does not get unloaded while in use */
00500       ast_module_ref(best->mod);
00501       ast_debug(1, "Chose bridge technology %s\n", best->name);
00502    }
00503 
00504    AST_RWLIST_UNLOCK(&bridge_technologies);
00505 
00506    return best;
00507 }

static struct ast_channel* get_transferee ( struct ao2_container channels,
struct ast_channel transferer 
) [static, read]

Definition at line 3913 of file bridge.c.

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), and ao2_iterator_next.

Referenced by ast_bridge_transfer_attended().

03914 {
03915    struct ao2_iterator channel_iter;
03916    struct ast_channel *transferee;
03917 
03918    for (channel_iter = ao2_iterator_init(channels, 0);
03919          (transferee = ao2_iterator_next(&channel_iter));
03920          ao2_cleanup(transferee)) {
03921       if (transferee != transferer) {
03922          break;
03923       }
03924    }
03925 
03926    ao2_iterator_destroy(&channel_iter);
03927    return transferee;
03928 }

static char* handle_bridge_kick_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4935 of file bridge.c.

References ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_bridge_channel_queue_callback(), ast_bridge_find_by_id(), ast_bridge_kick(), ast_bridge_lock, ast_bridge_unlock, ast_channel_get_by_name_prefix(), ast_channel_name(), ast_channel_unref, ast_cli(), AST_LIST_TRAVERSE, ast_bridge::channels, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_bridge_live(), complete_bridge_participant(), ast_cli_args::fd, kick_it(), ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

04936 {
04937    struct ast_bridge *bridge;
04938 
04939    switch (cmd) {
04940    case CLI_INIT:
04941       e->command = "bridge kick";
04942       e->usage =
04943          "Usage: bridge kick <bridge-id> <channel-name | all>\n"
04944          "       Kick the <channel-name> channel out of the <bridge-id> bridge\n"
04945          "       If all is specified as the channel name then all channels will be\n"
04946          "       kicked out of the bridge.\n";
04947       return NULL;
04948    case CLI_GENERATE:
04949       if (a->pos == 2) {
04950          return complete_bridge_live(a->word, a->n);
04951       }
04952       if (a->pos == 3) {
04953          return complete_bridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
04954       }
04955       return NULL;
04956    }
04957 
04958    if (a->argc != 4) {
04959       return CLI_SHOWUSAGE;
04960    }
04961 
04962    bridge = ast_bridge_find_by_id(a->argv[2]);
04963    if (!bridge) {
04964       ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
04965       return CLI_SUCCESS;
04966    }
04967 
04968    if (!strcasecmp(a->argv[3], "all")) {
04969       struct ast_bridge_channel *bridge_channel;
04970 
04971       ast_cli(a->fd, "Kicking all channels from bridge '%s'\n", a->argv[2]);
04972 
04973       ast_bridge_lock(bridge);
04974       AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
04975          ast_bridge_channel_queue_callback(bridge_channel, 0, kick_it, NULL, 0);
04976       }
04977       ast_bridge_unlock(bridge);
04978    } else {
04979       struct ast_channel *chan;
04980 
04981       chan = ast_channel_get_by_name_prefix(a->argv[3], strlen(a->argv[3]));
04982       if (!chan) {
04983          ast_cli(a->fd, "Channel '%s' not found\n", a->argv[3]);
04984          ao2_ref(bridge, -1);
04985          return CLI_SUCCESS;
04986       }
04987 
04988       ast_cli(a->fd, "Kicking channel '%s' from bridge '%s'\n",
04989          ast_channel_name(chan), a->argv[2]);
04990       ast_bridge_kick(bridge, chan);
04991       ast_channel_unref(chan);
04992    }
04993 
04994    ao2_ref(bridge, -1);
04995    return CLI_SUCCESS;
04996 }

static char* handle_bridge_show_all ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4759 of file bridge.c.

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_bridge_cache(), ast_bridge_snapshot_type(), ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT_HDR, FORMAT_ROW, NULL, ast_bridge_snapshot::num_channels, RAII_VAR, S_OR, stasis_cache_dump(), stasis_message_data(), ast_bridge_snapshot::subclass, ast_bridge_snapshot::technology, ast_bridge_snapshot::uniqueid, and ast_cli_entry::usage.

04760 {
04761 #define FORMAT_HDR "%-36s %5s %-15s %s\n"
04762 #define FORMAT_ROW "%-36s %5u %-15s %s\n"
04763 
04764    RAII_VAR(struct ao2_container *, cached_bridges, NULL, ao2_cleanup);
04765    struct ao2_iterator iter;
04766    struct stasis_message *msg;
04767 
04768    switch (cmd) {
04769    case CLI_INIT:
04770       e->command = "bridge show all";
04771       e->usage =
04772          "Usage: bridge show all\n"
04773          "       List all bridges\n";
04774       return NULL;
04775    case CLI_GENERATE:
04776       return NULL;
04777    }
04778 
04779    cached_bridges = stasis_cache_dump(ast_bridge_cache(), ast_bridge_snapshot_type());
04780    if (!cached_bridges) {
04781       ast_cli(a->fd, "Failed to retrieve cached bridges\n");
04782       return CLI_SUCCESS;
04783    }
04784 
04785    ast_cli(a->fd, FORMAT_HDR, "Bridge-ID", "Chans", "Type", "Technology");
04786 
04787    iter = ao2_iterator_init(cached_bridges, 0);
04788    for (; (msg = ao2_iterator_next(&iter)); ao2_ref(msg, -1)) {
04789       struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);
04790 
04791       ast_cli(a->fd, FORMAT_ROW,
04792          snapshot->uniqueid,
04793          snapshot->num_channels,
04794          S_OR(snapshot->subclass, "<unknown>"),
04795          S_OR(snapshot->technology, "<unknown>"));
04796    }
04797    ao2_iterator_destroy(&iter);
04798    return CLI_SUCCESS;
04799 
04800 #undef FORMAT_HDR
04801 #undef FORMAT_ROW
04802 }

static char* handle_bridge_show_specific ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4823 of file bridge.c.

References ao2_callback, ao2_cleanup, ast_cli_args::argc, ast_cli_args::argv, ast_bridge_cache(), ast_bridge_snapshot_type(), ast_cli(), bridge_show_specific_print_channel(), ast_bridge_snapshot::channels, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_bridge_stasis(), ast_cli_args::fd, ast_cli_args::n, NULL, ast_bridge_snapshot::num_channels, OBJ_NODATA, ast_cli_args::pos, RAII_VAR, S_OR, stasis_cache_get(), stasis_message_data(), ast_bridge_snapshot::subclass, ast_bridge_snapshot::technology, ast_bridge_snapshot::uniqueid, ast_cli_entry::usage, and ast_cli_args::word.

04824 {
04825    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
04826    struct ast_bridge_snapshot *snapshot;
04827 
04828    switch (cmd) {
04829    case CLI_INIT:
04830       e->command = "bridge show";
04831       e->usage =
04832          "Usage: bridge show <bridge-id>\n"
04833          "       Show information about the <bridge-id> bridge\n";
04834       return NULL;
04835    case CLI_GENERATE:
04836       if (a->pos == 2) {
04837          return complete_bridge_stasis(a->word, a->n);
04838       }
04839       return NULL;
04840    }
04841 
04842    if (a->argc != 3) {
04843       return CLI_SHOWUSAGE;
04844    }
04845 
04846    msg = stasis_cache_get(ast_bridge_cache(), ast_bridge_snapshot_type(), a->argv[2]);
04847    if (!msg) {
04848       ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
04849       return CLI_SUCCESS;
04850    }
04851 
04852    snapshot = stasis_message_data(msg);
04853    ast_cli(a->fd, "Id: %s\n", snapshot->uniqueid);
04854    ast_cli(a->fd, "Type: %s\n", S_OR(snapshot->subclass, "<unknown>"));
04855    ast_cli(a->fd, "Technology: %s\n", S_OR(snapshot->technology, "<unknown>"));
04856    ast_cli(a->fd, "Num-Channels: %u\n", snapshot->num_channels);
04857    ao2_callback(snapshot->channels, OBJ_NODATA, bridge_show_sp