Skip to content
Snippets Groups Projects
bridge_channel.c 85.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * Asterisk -- An open source telephony toolkit.
     *
     * Copyright (C) 2007 - 2009, Digium, Inc.
     *
     * Joshua Colp <jcolp@digium.com>
     *
     * See http://www.asterisk.org for more information about
     * the Asterisk project. Please do not directly contact
     * any of the maintainers of this project for assistance;
     * the project provides a web site, mailing lists and IRC
     * channels for your use.
     *
     * This program is free software, distributed under the terms of
     * the GNU General Public License Version 2. See the LICENSE file
     * at the top of the source tree.
     */
    
    /*! \file
     *
     * \brief Bridging Channel API
     *
     * \author Joshua Colp <jcolp@digium.com>
     * \author Richard Mudgett <rmudgett@digium.com>
     * \author Matt Jordan <mjordan@digium.com>
     *
     */
    
    /*** MODULEINFO
    	<support_level>core</support_level>
     ***/
    
    #include "asterisk.h"
    
    
    ASTERISK_REGISTER_FILE()
    
    
    #include <signal.h>
    
    #include "asterisk/heap.h"
    #include "asterisk/astobj2.h"
    #include "asterisk/stringfields.h"
    #include "asterisk/app.h"
    #include "asterisk/pbx.h"
    #include "asterisk/channel.h"
    #include "asterisk/timing.h"
    
    #include "asterisk/bridge.h"
    #include "asterisk/bridge_channel.h"
    #include "asterisk/bridge_after.h"
    #include "asterisk/bridge_channel_internal.h"
    #include "asterisk/bridge_internal.h"
    #include "asterisk/stasis_bridges.h"
    
    #include "asterisk/stasis_channels.h"
    #include "asterisk/musiconhold.h"
    #include "asterisk/features_config.h"
    #include "asterisk/parking.h"
    
    David M. Lee's avatar
    David M. Lee committed
    #include "asterisk/sem.h"
    
    /*!
     * \brief Used to queue an action frame onto a bridge channel and write an action frame into a bridge.
     * \since 12.0.0
     *
     * \param bridge_channel Which channel work with.
     * \param action Type of bridge action frame.
     * \param data Frame payload data to pass.
     * \param datalen Frame payload data length to pass.
     *
     * \retval 0 on success.
     * \retval -1 on error.
     */
    typedef int (*ast_bridge_channel_post_action_data)(struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen);
    
    /*!
     * \brief Counter used for assigning synchronous bridge action IDs
     */
    static int sync_ids;
    
    /*!
     * \brief Frame payload for synchronous bridge actions.
     *
     * The payload serves as a wrapper around the actual payload of the
     * frame, with the addition of an id used to find the associated
     * bridge_sync object.
     */
    struct sync_payload {
    	/*! Unique ID for this synchronous action */
    	unsigned int id;
    	/*! Actual frame data to process */
    	unsigned char data[0];
    };
    
    /*!
     * \brief Synchronous bridge action object.
     *
     * Synchronous bridge actions require the ability for one thread to wait
     * and for another thread to indicate that the action has completed. This
     * structure facilitates that goal by providing synchronization structures.
     */
    struct bridge_sync {
    	/*! Unique ID of this synchronization object. Corresponds with ID in synchronous frame payload */
    	unsigned int id;
    	/*! Semaphore used for synchronization */
    
    David M. Lee's avatar
    David M. Lee committed
    	struct ast_sem sem;
    
    	/*! Pointer to next entry in the list */
    	AST_LIST_ENTRY(bridge_sync) list;
    };
    
    /*!
     * \brief List holding active synchronous action objects.
     */
    static AST_RWLIST_HEAD_STATIC(sync_structs, bridge_sync);
    
    /*!
     * \brief initialize a synchronous bridge object.
     *
     * This both initializes the structure and adds it to the list of
     * synchronization structures.
     *
     * \param sync_struct The synchronization object to initialize.
     * \param id ID to assign to the synchronization object.
     */
    static void bridge_sync_init(struct bridge_sync *sync_struct, unsigned int id)
    {
    	memset(sync_struct, 0, sizeof(*sync_struct));
    	sync_struct->id = id;
    
    David M. Lee's avatar
    David M. Lee committed
    	ast_sem_init(&sync_struct->sem, 0, 0);
    
    
    	AST_RWLIST_WRLOCK(&sync_structs);
    	AST_RWLIST_INSERT_TAIL(&sync_structs, sync_struct, list);
    	AST_RWLIST_UNLOCK(&sync_structs);
    }
    
    /*!
     * \brief Clean up a syncrhonization bridge object.
     *
     * This frees fields within the synchronization object and removes
     * it from the list of active synchronization objects.
     *
     * Since synchronization objects are stack-allocated, it is vital
     * that this is called before the synchronization object goes
     * out of scope.
     *
     * \param sync_struct Synchronization object to clean up.
     */
    static void bridge_sync_cleanup(struct bridge_sync *sync_struct)
    {
    	struct bridge_sync *iter;
    
    	AST_RWLIST_WRLOCK(&sync_structs);
    	AST_LIST_TRAVERSE_SAFE_BEGIN(&sync_structs, iter, list) {
    		if (iter->id == sync_struct->id) {
    			AST_LIST_REMOVE_CURRENT(list);
    			break;
    		}
    	}
    	AST_LIST_TRAVERSE_SAFE_END;
    	AST_RWLIST_UNLOCK(&sync_structs);
    
    
    David M. Lee's avatar
    David M. Lee committed
    	ast_sem_destroy(&sync_struct->sem);
    
    }
    
    /*!
     * \brief Failsafe for synchronous bridge action waiting.
     *
     * When waiting for a synchronous bridge action to complete,
     * if there is a frame resource leak somewhere, it is possible
     * that we will never get notified that the synchronous action
     * completed.
     *
     * If a significant amount of time passes, then we will abandon
     * waiting for the synchrnous bridge action to complete.
     *
     * This constant represents the number of milliseconds we will
     * wait for the bridge action to complete.
     */
    #define PLAYBACK_TIMEOUT (600 * 1000)
    
    /*!
     * \brief Wait for a synchronous bridge action to complete.
     *
     * \param sync_struct Synchronization object corresponding to the bridge action.
     */
    static void bridge_sync_wait(struct bridge_sync *sync_struct)
    {
    	struct timeval timeout_val = ast_tvadd(ast_tvnow(), ast_samp2tv(PLAYBACK_TIMEOUT, 1000));
    	struct timespec timeout_spec = {
    		.tv_sec = timeout_val.tv_sec,
    		.tv_nsec = timeout_val.tv_usec * 1000,
    	};
    
    
    David M. Lee's avatar
    David M. Lee committed
    	ast_sem_timedwait(&sync_struct->sem, &timeout_spec);
    
    }
    
    /*!
     * \brief Signal that waiting for a synchronous bridge action is no longer necessary.
     *
     * This may occur for several reasons
     * \li The synchronous bridge action has completed.
     * \li The bridge channel has been removed from the bridge.
     * \li The synchronous bridge action could not be queued.
     *
     * \param sync_struct Synchronization object corresponding to the bridge action.
     */
    static void bridge_sync_signal(struct bridge_sync *sync_struct)
    {
    
    David M. Lee's avatar
    David M. Lee committed
    	ast_sem_post(&sync_struct->sem);
    
    void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
    {
    	struct ast_bridge *bridge;
    
    	for (;;) {
    		/* Safely get the bridge pointer */
    		ast_bridge_channel_lock(bridge_channel);
    		bridge = bridge_channel->bridge;
    		ao2_ref(bridge, +1);
    		ast_bridge_channel_unlock(bridge_channel);
    
    		/* Lock the bridge and see if it is still the bridge we need to lock. */
    		ast_bridge_lock(bridge);
    		if (bridge == bridge_channel->bridge) {
    			ao2_ref(bridge, -1);
    			return;
    		}
    		ast_bridge_unlock(bridge);
    		ao2_ref(bridge, -1);
    	}
    }
    
    
    int ast_bridge_channel_notify_talking(struct ast_bridge_channel *bridge_channel, int started_talking)
    {
    	struct ast_frame action = {
    		.frametype = AST_FRAME_BRIDGE_ACTION,
    		.subclass.integer = started_talking
    			? BRIDGE_CHANNEL_ACTION_TALKING_START : BRIDGE_CHANNEL_ACTION_TALKING_STOP,
    	};
    
    	return ast_bridge_channel_queue_frame(bridge_channel, &action);
    }
    
    
    Richard Mudgett's avatar
    Richard Mudgett committed
    /*!
     * \internal
     * \brief Poke the bridge_channel thread
     */
    
    static void bridge_channel_poke(struct ast_bridge_channel *bridge_channel)
    {
    	if (!pthread_equal(pthread_self(), bridge_channel->thread)) {
    
    		/* Wake up the bridge channel thread. */
    		ast_queue_frame(bridge_channel->chan, &ast_null_frame);
    
    /*!
     * \internal
     * \brief Set actual cause on channel.
     * \since 12.0.0
     *
     * \param chan Channel to set cause.
     * \param cause Cause to set on channel.
     *   If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.
     *
     * \return Actual cause set on channel.
     */
    static int channel_set_cause(struct ast_channel *chan, int cause)
    {
    	ast_channel_lock(chan);
    	if (cause <= 0) {
    		cause = ast_channel_hangupcause(chan);
    		if (cause <= 0) {
    			cause = AST_CAUSE_NORMAL_CLEARING;
    		}
    	}
    	ast_channel_hangupcause_set(chan, cause);
    	ast_channel_unlock(chan);
    	return cause;
    }
    
    void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
    
    {
    	if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
    		return;
    	}
    
    
    	ast_debug(1, "Setting %p(%s) state from:%u to:%u\n",
    
    		bridge_channel, ast_channel_name(bridge_channel->chan), bridge_channel->state,
    		new_state);
    
    
    	channel_set_cause(bridge_channel->chan, cause);
    
    
    	/* Change the state on the bridge channel */
    	bridge_channel->state = new_state;
    
    	bridge_channel_poke(bridge_channel);
    }
    
    
    void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
    {
    	ast_bridge_channel_lock(bridge_channel);
    	ast_bridge_channel_leave_bridge_nolock(bridge_channel, new_state, cause);
    	ast_bridge_channel_unlock(bridge_channel);
    }
    
    
    struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel)
    {
    	struct ast_bridge *bridge = bridge_channel->bridge;
    	struct ast_bridge_channel *other = NULL;
    
    	if (bridge_channel->in_bridge && bridge->num_channels == 2) {
    		AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
    			if (other != bridge_channel) {
    				break;
    			}
    		}
    	}
    
    	return other;
    }
    
    void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel)
    {
    
    	ast_assert(bridge_channel->read_format != NULL);
    	ast_assert(bridge_channel->write_format != NULL);
    
    
    	ast_channel_lock(bridge_channel->chan);
    
    
    	/* Restore original formats of the channel as they came in */
    
    	if (ast_format_cmp(ast_channel_readformat(bridge_channel->chan), bridge_channel->read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
    
    		ast_debug(1, "Bridge is returning %p(%s) to read format %s\n",
    			bridge_channel, ast_channel_name(bridge_channel->chan),
    
    			ast_format_get_name(bridge_channel->read_format));
    		if (ast_set_read_format(bridge_channel->chan, bridge_channel->read_format)) {
    
    			ast_debug(1, "Bridge failed to return %p(%s) to read format %s\n",
    				bridge_channel, ast_channel_name(bridge_channel->chan),
    
    				ast_format_get_name(bridge_channel->read_format));
    
    	if (ast_format_cmp(ast_channel_writeformat(bridge_channel->chan), bridge_channel->write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
    
    		ast_debug(1, "Bridge is returning %p(%s) to write format %s\n",
    			bridge_channel, ast_channel_name(bridge_channel->chan),
    
    			ast_format_get_name(bridge_channel->write_format));
    		if (ast_set_write_format(bridge_channel->chan, bridge_channel->write_format)) {
    
    			ast_debug(1, "Bridge failed to return %p(%s) to write format %s\n",
    				bridge_channel, ast_channel_name(bridge_channel->chan),
    
    				ast_format_get_name(bridge_channel->write_format));
    
    
    	ast_channel_unlock(bridge_channel->chan);
    
    }
    
    struct ast_bridge *ast_bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request)
    {
    	struct ast_bridge *bridge;
    
    	ast_bridge_channel_lock_bridge(bridge_channel);
    	bridge = bridge_channel->bridge;
    	ao2_ref(bridge, +1);
    	bridge_merge_inhibit_nolock(bridge, request);
    	ast_bridge_unlock(bridge);
    	return bridge;
    }
    
    void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
    {
    
    	struct ast_bridge_channel *other;
    
    	struct ast_bridge *bridge = bridge_channel->bridge;
    
    	struct ast_channel *oldest_linkedid_chan = bridge_channel->chan;
    
    
    	AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
    		if (other == swap) {
    			continue;
    		}
    
    		oldest_linkedid_chan = ast_channel_internal_oldest_linkedid(
    			oldest_linkedid_chan, other->chan);
    
    	ast_channel_lock(bridge_channel->chan);
    
    	ast_channel_internal_copy_linkedid(bridge_channel->chan, oldest_linkedid_chan);
    
    	ast_channel_unlock(bridge_channel->chan);
    
    	AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
    		if (other == swap) {
    			continue;
    		}
    
    		ast_channel_lock(other->chan);
    
    		ast_channel_internal_copy_linkedid(other->chan, oldest_linkedid_chan);
    
    		ast_channel_unlock(other->chan);
    
    /*!
     * \internal
     * \brief Set dest's empty peeraccount with the src's non-empty accountcode.
     * \since 12.5.0
     *
     * \param dest Channel to update peeraccount.
     * \param src Channel to get accountcode from.
     *
     * \note Both channels are already locked.
     *
     * \return Nothing
     */
    static void channel_fill_empty_peeraccount(struct ast_channel *dest, struct ast_channel *src)
    
    	if (ast_strlen_zero(ast_channel_peeraccount(dest))
    		&& !ast_strlen_zero(ast_channel_accountcode(src))) {
    		ast_debug(1, "Setting channel %s peeraccount with channel %s accountcode '%s'.\n",
    			ast_channel_name(dest),
    			ast_channel_name(src), ast_channel_accountcode(src));
    		ast_channel_peeraccount_set(dest, ast_channel_accountcode(src));
    	}
    }
    
    /*!
     * \internal
     * \brief Set dest's empty accountcode with the src's non-empty peeraccount.
     * \since 12.5.0
     *
     * \param dest Channel to update accountcode.
     * \param src Channel to get peeraccount from.
     *
     * \note Both channels are already locked.
     *
     * \return Nothing
     */
    static void channel_fill_empty_accountcode(struct ast_channel *dest, struct ast_channel *src)
    {
    	if (ast_strlen_zero(ast_channel_accountcode(dest))
    		&& !ast_strlen_zero(ast_channel_peeraccount(src))) {
    		ast_debug(1, "Setting channel %s accountcode with channel %s peeraccount '%s'.\n",
    			ast_channel_name(dest),
    			ast_channel_name(src), ast_channel_peeraccount(src));
    		ast_channel_accountcode_set(dest, ast_channel_peeraccount(src));
    	}
    }
    
    /*!
     * \internal
     * \brief Set empty peeraccount and accountcode in a channel from the other channel.
     * \since 12.5.0
     *
     * \param c0 First bridge channel to update.
     * \param c1 Second bridge channel to update.
     *
     * \note Both channels are already locked.
     *
     * \return Nothing
     */
    static void channel_set_empty_accountcodes(struct ast_channel *c0, struct ast_channel *c1)
    {
    	/* Set empty peeraccount from the other channel's accountcode. */
    	channel_fill_empty_peeraccount(c0, c1);
    	channel_fill_empty_peeraccount(c1, c0);
    
    	/* Set empty accountcode from the other channel's peeraccount. */
    	channel_fill_empty_accountcode(c0, c1);
    	channel_fill_empty_accountcode(c1, c0);
    }
    
    /*!
     * \internal
     * \brief Update dest's peeraccount with the src's different accountcode.
     * \since 12.5.0
     *
     * \param dest Channel to update peeraccount.
     * \param src Channel to get accountcode from.
     *
     * \note Both channels are already locked.
     *
     * \return Nothing
     */
    static void channel_update_peeraccount(struct ast_channel *dest, struct ast_channel *src)
    {
    	if (strcmp(ast_channel_accountcode(src), ast_channel_peeraccount(dest))) {
    		ast_debug(1, "Changing channel %s peeraccount '%s' to match channel %s accountcode '%s'.\n",
    			ast_channel_name(dest), ast_channel_peeraccount(dest),
    			ast_channel_name(src), ast_channel_accountcode(src));
    		ast_channel_peeraccount_set(dest, ast_channel_accountcode(src));
    	}
    }
    
    /*!
     * \internal
     * \brief Update peeraccounts to match the other channel's accountcode.
     * \since 12.5.0
     *
     * \param c0 First channel to update.
     * \param c1 Second channel to update.
     *
     * \note Both channels are already locked.
     *
     * \return Nothing
     */
    static void channel_update_peeraccounts(struct ast_channel *c0, struct ast_channel *c1)
    {
    	channel_update_peeraccount(c0, c1);
    	channel_update_peeraccount(c1, c0);
    }
    
    /*!
     * \internal
     * \brief Update channel accountcodes because a channel is joining a bridge.
     * \since 12.5.0
     *
     * \param joining Channel joining the bridge.
     * \param swap Channel being replaced by the joining channel.  May be NULL.
     *
     * \note The bridge must be locked prior to calling this function.
     *
     * \return Nothing
     */
    static void bridge_channel_update_accountcodes_joining(struct ast_bridge_channel *joining, struct ast_bridge_channel *swap)
    {
    	struct ast_bridge *bridge = joining->bridge;
    	struct ast_bridge_channel *other;
    	unsigned int swap_in_bridge = 0;
    	unsigned int will_be_two_party;
    
    	/*
    	 * Only update the peeraccount to match if the joining channel
    	 * will make it a two party bridge.
    	 */
    	if (bridge->num_channels <= 2 && swap) {
    		AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
    			if (other == swap) {
    				swap_in_bridge = 1;
    				break;
    			}
    		}
    	}
    	will_be_two_party = (1 == bridge->num_channels - swap_in_bridge);
    
    
    	AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
    		if (other == swap) {
    			continue;
    		}
    
    		ast_assert(joining != other);
    		ast_channel_lock_both(joining->chan, other->chan);
    		channel_set_empty_accountcodes(joining->chan, other->chan);
    		if (will_be_two_party) {
    			channel_update_peeraccounts(joining->chan, other->chan);
    
    		ast_channel_unlock(joining->chan);
    
    		ast_channel_unlock(other->chan);
    
    /*!
     * \internal
     * \brief Update channel peeraccount codes because a channel has left a bridge.
     * \since 12.5.0
     *
     * \param leaving Channel leaving the bridge. (Has already been removed actually)
     *
     * \note The bridge must be locked prior to calling this function.
     *
     * \return Nothing
     */
    static void bridge_channel_update_accountcodes_leaving(struct ast_bridge_channel *leaving)
    {
    	struct ast_bridge *bridge = leaving->bridge;
    	struct ast_bridge_channel *first;
    	struct ast_bridge_channel *second;
    
    	if (bridge->num_channels != 2 || bridge->dissolved) {
    		return;
    	}
    
    	first = AST_LIST_FIRST(&bridge->channels);
    	second = AST_LIST_LAST(&bridge->channels);
    	ast_assert(first && first != second);
    	ast_channel_lock_both(first->chan, second->chan);
    	channel_set_empty_accountcodes(first->chan, second->chan);
    	channel_update_peeraccounts(first->chan, second->chan);
    	ast_channel_unlock(second->chan);
    	ast_channel_unlock(first->chan);
    }
    
    void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *joining, struct ast_bridge_channel *leaving)
    {
    	if (joining) {
    		bridge_channel_update_accountcodes_joining(joining, leaving);
    	} else {
    		bridge_channel_update_accountcodes_leaving(leaving);
    	}
    }
    
    
    void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel, int cause)
    
    	struct ast_bridge_features *features = bridge_channel->features;
    	struct ast_bridge_hook *hook;
    	struct ao2_iterator iter;
    
    	ast_bridge_channel_lock(bridge_channel);
    	if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
    		channel_set_cause(bridge_channel->chan, cause);
    		cause = 0;
    	}
    	ast_bridge_channel_unlock(bridge_channel);
    
    
    	/* Run any hangup hooks. */
    	iter = ao2_iterator_init(features->other_hooks, 0);
    	for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
    		int remove_me;
    
    		if (hook->type != AST_BRIDGE_HOOK_TYPE_HANGUP) {
    
    		remove_me = hook->callback(bridge_channel, hook->hook_pvt);
    
    		if (remove_me) {
    			ast_debug(1, "Hangup hook %p is being removed from %p(%s)\n",
    				hook, bridge_channel, ast_channel_name(bridge_channel->chan));
    			ao2_unlink(features->other_hooks, hook);
    		}
    
    	ao2_iterator_destroy(&iter);
    
    	/* Default hangup action. */
    
    	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, cause);
    
    /*!
     * \internal
     * \brief Write an \ref ast_frame onto the bridge channel
     * \since 12.0.0
     *
     * \param bridge_channel Which channel to queue the frame onto.
     * \param frame The frame to write onto the bridge_channel
     *
     * \retval 0 on success.
     * \retval -1 on error.
     */
    static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
    {
    
    	ast_assert(frame->frametype != AST_FRAME_BRIDGE_ACTION_SYNC);
    
    
    	ast_bridge_channel_lock_bridge(bridge_channel);
    /*
    
     * XXX need to implement a deferred write queue for when there
     * is no peer channel in the bridge (yet or it was kicked).
    
     *
     * The tech decides if a frame needs to be pushed back for deferral.
     * simple_bridge/native_bridge are likely the only techs that will do this.
     */
    	bridge_channel->bridge->technology->write(bridge_channel->bridge, bridge_channel, frame);
    
    
    	/* Remember any owed events to the bridge. */
    	switch (frame->frametype) {
    	case AST_FRAME_DTMF_BEGIN:
    		bridge_channel->owed.dtmf_tv = ast_tvnow();
    		bridge_channel->owed.dtmf_digit = frame->subclass.integer;
    		break;
    	case AST_FRAME_DTMF_END:
    		bridge_channel->owed.dtmf_digit = '\0';
    		break;
    	case AST_FRAME_CONTROL:
    		/*
    		 * We explicitly will not remember HOLD/UNHOLD frames because
    		 * things like attended transfers will handle them.
    		 */
    	default:
    		break;
    	}
    
    	ast_bridge_unlock(bridge_channel->bridge);
    
    	/*
    	 * Claim successful write to bridge.  If deferred frame
    	 * support is added, claim successfully deferred.
    	 */
    	return 0;
    }
    
    
    void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct ast_bridge_channel *bridge_channel)
    {
    	if (bridge_channel->owed.dtmf_digit) {
    		struct ast_frame frame = {
    			.frametype = AST_FRAME_DTMF_END,
    			.subclass.integer = bridge_channel->owed.dtmf_digit,
    			.src = "Bridge channel owed DTMF",
    		};
    
    		frame.len = ast_tvdiff_ms(ast_tvnow(), bridge_channel->owed.dtmf_tv);
    		if (frame.len < option_dtmfminduration) {
    			frame.len = option_dtmfminduration;
    		}
    		ast_log(LOG_DTMF, "DTMF end '%c' simulated to bridge %s because %s left.  Duration %ld ms.\n",
    			bridge_channel->owed.dtmf_digit, orig_bridge->uniqueid,
    			ast_channel_name(bridge_channel->chan), frame.len);
    		bridge_channel->owed.dtmf_digit = '\0';
    		orig_bridge->technology->write(orig_bridge, NULL, &frame);
    	}
    }
    
    
    /*!
     * \internal
     * \brief Suspend a channel from a bridge.
     *
     * \param bridge_channel Channel to suspend.
     *
     * \note This function assumes bridge_channel->bridge is locked.
     *
     * \return Nothing
     */
    void bridge_channel_internal_suspend_nolock(struct ast_bridge_channel *bridge_channel)
    {
    	bridge_channel->suspended = 1;
    	if (bridge_channel->in_bridge) {
    		--bridge_channel->bridge->num_active;
    	}
    
    	/* Get technology bridge threads off of the channel. */
    	if (bridge_channel->bridge->technology->suspend) {
    		bridge_channel->bridge->technology->suspend(bridge_channel->bridge, bridge_channel);
    	}
    }
    
    /*!
     * \internal
     * \brief Suspend a channel from a bridge.
     *
     * \param bridge_channel Channel to suspend.
     *
     * \return Nothing
     */
    static void bridge_channel_suspend(struct ast_bridge_channel *bridge_channel)
    {
    	ast_bridge_channel_lock_bridge(bridge_channel);
    	bridge_channel_internal_suspend_nolock(bridge_channel);
    	ast_bridge_unlock(bridge_channel->bridge);
    }
    
    /*!
     * \internal
     * \brief Unsuspend a channel from a bridge.
     *
     * \param bridge_channel Channel to unsuspend.
     *
     * \note This function assumes bridge_channel->bridge is locked.
     *
     * \return Nothing
     */
    void bridge_channel_internal_unsuspend_nolock(struct ast_bridge_channel *bridge_channel)
    {
    	bridge_channel->suspended = 0;
    	if (bridge_channel->in_bridge) {
    		++bridge_channel->bridge->num_active;
    	}
    
    	/* Wake technology bridge threads to take care of channel again. */
    	if (bridge_channel->bridge->technology->unsuspend) {
    		bridge_channel->bridge->technology->unsuspend(bridge_channel->bridge, bridge_channel);
    	}
    
    	/* Wake suspended channel. */
    	ast_bridge_channel_lock(bridge_channel);
    	ast_cond_signal(&bridge_channel->cond);
    	ast_bridge_channel_unlock(bridge_channel);
    }
    
    /*!
     * \internal
     * \brief Unsuspend a channel from a bridge.
     *
     * \param bridge_channel Channel to unsuspend.
     *
     * \return Nothing
     */
    static void bridge_channel_unsuspend(struct ast_bridge_channel *bridge_channel)
    {
    	ast_bridge_channel_lock_bridge(bridge_channel);
    	bridge_channel_internal_unsuspend_nolock(bridge_channel);
    	ast_bridge_unlock(bridge_channel->bridge);
    }
    
    
    /*!
     * \internal
     * \brief Queue an action frame onto the bridge channel with data.
     * \since 12.0.0
     *
     * \param bridge_channel Which channel to queue the frame onto.
     * \param action Type of bridge action frame.
     * \param data Frame payload data to pass.
     * \param datalen Frame payload data length to pass.
     *
     * \retval 0 on success.
     * \retval -1 on error.
     */
    
    static int bridge_channel_queue_action_data(struct ast_bridge_channel *bridge_channel,
    	enum bridge_channel_action_type action, const void *data, size_t datalen)
    
    {
    	struct ast_frame frame = {
    		.frametype = AST_FRAME_BRIDGE_ACTION,
    		.subclass.integer = action,
    		.datalen = datalen,
    		.data.ptr = (void *) data,
    	};
    
    	return ast_bridge_channel_queue_frame(bridge_channel, &frame);
    }
    
    
    /*!
     * \internal
     * \brief Queue an action frame onto the bridge channel with data synchronously.
     * \since 12.2.0
     *
     * The function will not return until the queued frame is freed.
     *
     * \param bridge_channel Which channel to queue the frame onto.
     * \param action Type of bridge action frame.
     * \param data Frame payload data to pass.
     * \param datalen Frame payload data length to pass.
     *
     * \retval 0 on success.
     * \retval -1 on error.
     */
    static int bridge_channel_queue_action_data_sync(struct ast_bridge_channel *bridge_channel,
    	enum bridge_channel_action_type action, const void *data, size_t datalen)
    {
    	struct sync_payload *sync_payload;
    	int sync_payload_len = sizeof(*sync_payload) + datalen;
    	struct bridge_sync sync_struct;
    	struct ast_frame frame = {
    		.frametype = AST_FRAME_BRIDGE_ACTION_SYNC,
    		.subclass.integer = action,
    	};
    
    	/* Make sure we don't end up trying to wait on ourself to deliver the frame */
    	ast_assert(!pthread_equal(pthread_self(), bridge_channel->thread));
    
    	sync_payload = ast_alloca(sync_payload_len);
    	sync_payload->id = ast_atomic_fetchadd_int(&sync_ids, +1);
    	memcpy(sync_payload->data, data, datalen);
    
    	frame.datalen = sync_payload_len;
    	frame.data.ptr = sync_payload;
    
    	bridge_sync_init(&sync_struct, sync_payload->id);
    	if (ast_bridge_channel_queue_frame(bridge_channel, &frame)) {
    		bridge_sync_cleanup(&sync_struct);
    		return -1;
    	}
    
    	bridge_sync_wait(&sync_struct);
    	bridge_sync_cleanup(&sync_struct);
    	return 0;
    }
    
    /*!
     * \internal
     * \brief Write an action frame onto the bridge channel with data.
     * \since 12.0.0
     *
     * \param bridge_channel Which channel to queue the frame onto.
     * \param action Type of bridge action frame.
     * \param data Frame payload data to pass.
     * \param datalen Frame payload data length to pass.
     *
     * \retval 0 on success.
     * \retval -1 on error.
     */
    
    static int bridge_channel_write_action_data(struct ast_bridge_channel *bridge_channel,
    	enum bridge_channel_action_type action, const void *data, size_t datalen)
    
    {
    	struct ast_frame frame = {
    		.frametype = AST_FRAME_BRIDGE_ACTION,
    		.subclass.integer = action,
    		.datalen = datalen,
    		.data.ptr = (void *) data,
    	};
    
    	return bridge_channel_write_frame(bridge_channel, &frame);
    
    static void bridge_frame_free(struct ast_frame *frame)
    {
    	if (frame->frametype == AST_FRAME_BRIDGE_ACTION_SYNC) {
    		struct sync_payload *sync_payload = frame->data.ptr;
    		struct bridge_sync *sync;
    
    		AST_RWLIST_RDLOCK(&sync_structs);
    		AST_RWLIST_TRAVERSE(&sync_structs, sync, list) {
    			if (sync->id == sync_payload->id) {
    				break;
    			}
    		}
    		if (sync) {
    			bridge_sync_signal(sync);
    		}
    		AST_RWLIST_UNLOCK(&sync_structs);
    	}
    
    	ast_frfree(frame);
    }
    
    
    int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
    {
    	struct ast_frame *dup;
    	char nudge = 0;
    
    	if (bridge_channel->suspended
    		/* Also defer DTMF frames. */
    		&& fr->frametype != AST_FRAME_DTMF_BEGIN
    		&& fr->frametype != AST_FRAME_DTMF_END
    		&& !ast_is_deferrable_frame(fr)) {
    		/* Drop non-deferable frames when suspended. */
    		return 0;
    	}
    	if (fr->frametype == AST_FRAME_NULL) {
    		/* "Accept" the frame and discard it. */
    		return 0;
    	}
    
    	dup = ast_frdup(fr);
    	if (!dup) {
    		return -1;
    	}
    
    	ast_bridge_channel_lock(bridge_channel);
    
    	if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
    
    		/* Drop frames on channels leaving the bridge. */
    		ast_bridge_channel_unlock(bridge_channel);
    
    		return 0;
    	}
    
    	AST_LIST_INSERT_TAIL(&bridge_channel->wr_queue, dup, frame_list);
    	if (write(bridge_channel->alert_pipe[1], &nudge, sizeof(nudge)) != sizeof(nudge)) {
    		ast_log(LOG_ERROR, "We couldn't write alert pipe for %p(%s)... something is VERY wrong\n",
    			bridge_channel, ast_channel_name(bridge_channel->chan));
    	}
    
    	ast_bridge_channel_unlock(bridge_channel);
    	return 0;
    
    }
    
    int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
    {
    	struct ast_bridge_channel *cur;
    	int not_written = -1;
    
    	if (frame->frametype == AST_FRAME_NULL) {
    		/* "Accept" the frame and discard it. */
    		return 0;
    	}
    
    	AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
    		if (cur == bridge_channel) {
    			continue;
    		}
    		if (!ast_bridge_channel_queue_frame(cur, frame)) {
    			not_written = 0;
    		}
    	}
    	return not_written;
    }
    
    
    int ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
    
    {
    	struct ast_frame frame = {
    
    		.frametype = AST_FRAME_CONTROL,
    		.subclass.integer = control,
    
    		.datalen = datalen,
    		.data.ptr = (void *) data,
    	};
    
    
    	return ast_bridge_channel_queue_frame(bridge_channel, &frame);
    
    }
    
    int ast_bridge_channel_write_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
    {
    	struct ast_frame frame = {
    		.frametype = AST_FRAME_CONTROL,
    		.subclass.integer = control,
    		.datalen = datalen,
    		.data.ptr = (void *) data,
    	};
    
    	return bridge_channel_write_frame(bridge_channel, &frame);
    }
    
    int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class)
    {
    
    	struct ast_json *blob;
    	int res;
    
    	size_t datalen;
    
    	if (!ast_strlen_zero(moh_class)) {
    		datalen = strlen(moh_class) + 1;
    
    		blob = ast_json_pack("{s: s}",
    			"musicclass", moh_class);
    	} else {
    		moh_class = NULL;
    		datalen = 0;
    
    	ast_channel_publish_cached_blob(bridge_channel->chan, ast_channel_hold_type(), blob);
    
    
    	res = ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
    
    		moh_class, datalen);