Skip to content
Snippets Groups Projects
bridge.c 162 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		ast_debug(1, "Bridge %s is dissolved, not performing smart bridge operation.\n",
    			bridge->uniqueid);
    		return 0;
    
    	/* Determine new bridge technology capabilities needed. */
    	if (2 < bridge->num_channels) {
    		new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
    		new_capabilities &= bridge->allowed_capabilities;
    	} else {
    		new_capabilities = AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX;
    		new_capabilities &= bridge->allowed_capabilities;
    		if (!new_capabilities
    			&& (bridge->allowed_capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)) {
    			/* Allow switching between different multimix bridge technologies. */
    			new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
    		}
    	}
    
    	/* Find a bridge technology to satisfy the new capabilities. */
    	new_technology = find_best_technology(new_capabilities, bridge);
    	if (!new_technology) {
    		int is_compatible = 0;
    
    		if (old_technology->compatible) {
    			is_compatible = old_technology->compatible(bridge);
    		} else if (old_technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
    			is_compatible = 1;
    		} else if (bridge->num_channels <= 2
    			&& (old_technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX)) {
    			is_compatible = 1;
    
    		if (is_compatible) {
    			ast_debug(1, "Bridge %s could not get a new technology, staying with old technology.\n",
    				bridge->uniqueid);
    			return 0;
    
    		ast_log(LOG_WARNING, "Bridge %s has no technology available to support it.\n",
    			bridge->uniqueid);
    		return -1;
    	}
    	if (new_technology == old_technology) {
    		ast_debug(1, "Bridge %s is already using the new technology.\n",
    			bridge->uniqueid);
    		ast_module_unref(old_technology->mod);
    		return 0;
    	}
    
    	if (old_technology->destroy) {
    		struct tech_deferred_destroy deferred_tech_destroy = {
    			.tech = dummy_bridge.technology,
    			.tech_pvt = dummy_bridge.tech_pvt,
    		};
    		struct ast_frame action = {
    			.frametype = AST_FRAME_BRIDGE_ACTION,
    
    			.subclass.integer = BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY,
    
    			.data.ptr = &deferred_tech_destroy,
    			.datalen = sizeof(deferred_tech_destroy),
    		};
    
    		 * We need to defer the bridge technology destroy callback
    		 * because we have the bridge locked.
    
    		deferred_action = ast_frdup(&action);
    		if (!deferred_action) {
    			ast_module_unref(new_technology->mod);
    			return -1;
    
    	} else {
    		deferred_action = NULL;
    
    	/*
    	 * We are now committed to changing the bridge technology.  We
    	 * must not release the bridge lock until we have installed the
    	 * new bridge technology.
    	 */
    	ast_verb(4, "Bridge %s: switching from %s technology to %s\n",
    		bridge->uniqueid, old_technology->name, new_technology->name);
    
    	/*
    	 * Since we are soon going to pass this bridge to a new
    	 * technology we need to NULL out the tech_pvt pointer but
    	 * don't worry as it still exists in dummy_bridge, ditto for the
    	 * old technology.
    	 */
    	bridge->tech_pvt = NULL;
    	bridge->technology = new_technology;
    
    	/* Setup the new bridge technology. */
    	ast_debug(1, "Bridge %s: calling %s technology constructor\n",
    		bridge->uniqueid, new_technology->name);
    	if (new_technology->create && new_technology->create(bridge)) {
    		ast_log(LOG_WARNING, "Bridge %s: failed to setup bridge technology %s\n",
    			bridge->uniqueid, new_technology->name);
    		bridge->tech_pvt = dummy_bridge.tech_pvt;
    		bridge->technology = dummy_bridge.technology;
    		ast_module_unref(new_technology->mod);
    		return -1;
    
    	/* To ensure that things are sane for the old technology move the channels it
    	 * expects to the dummy bridge
    	 */
    	AST_LIST_TRAVERSE_SAFE_BEGIN(&bridge->channels, bridge_channel, entry) {
    		if (bridge_channel->just_joined) {
    			continue;
    		}
    		ast_debug(1, "Bridge %s: moving %p(%s) to dummy bridge temporarily\n",
    			bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
    		AST_LIST_REMOVE_CURRENT(entry);
    		AST_LIST_INSERT_TAIL(&dummy_bridge.channels, bridge_channel, entry);
    		dummy_bridge.num_channels++;
    		if (ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
    			dummy_bridge.num_lonely++;
    		}
    		if (!bridge_channel->suspended) {
    			dummy_bridge.num_active++;
    		}
    	}
    	AST_LIST_TRAVERSE_SAFE_END;
    
    	/* Take all the channels out of the old technology */
    	AST_LIST_TRAVERSE_SAFE_BEGIN(&dummy_bridge.channels, bridge_channel, entry) {
    		ast_debug(1, "Bridge %s: %p(%s) is leaving %s technology (dummy)\n",
    			dummy_bridge.uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
    			old_technology->name);
    		if (old_technology->leave) {
    			old_technology->leave(&dummy_bridge, bridge_channel);
    		}
    		AST_LIST_REMOVE_CURRENT(entry);
    		AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
    		dummy_bridge.num_channels--;
    		if (ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
    			dummy_bridge.num_lonely--;
    		}
    		if (!bridge_channel->suspended) {
    			dummy_bridge.num_active--;
    		}
    	}
    	AST_LIST_TRAVERSE_SAFE_END;
    
    
    	ast_debug(1, "Bridge %s: calling %s technology stop\n",
    		dummy_bridge.uniqueid, old_technology->name);
    	if (old_technology->stop) {
    		old_technology->stop(&dummy_bridge);
    	}
    
    	/* Add any new channels or re-add existing channels to the bridge. */
    
    	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
    		bridge_channel_complete_join(bridge, bridge_channel);
    
    	ast_debug(1, "Bridge %s: calling %s technology start\n",
    		bridge->uniqueid, new_technology->name);
    	if (new_technology->start && new_technology->start(bridge)) {
    		ast_log(LOG_WARNING, "Bridge %s: failed to start bridge technology %s\n",
    			bridge->uniqueid, new_technology->name);
    
    	/*
    	 * Now that all the channels have been moved over we need to get
    	 * rid of all the information the old technology may have left
    	 * around.
    	 */
    	if (old_technology->destroy) {
    		ast_debug(1, "Bridge %s: deferring %s technology destructor\n",
    			dummy_bridge.uniqueid, old_technology->name);
    		bridge_queue_action_nodup(bridge, deferred_action);
    	} else {
    		ast_debug(1, "Bridge %s: calling %s technology destructor\n",
    			dummy_bridge.uniqueid, old_technology->name);
    		ast_module_unref(old_technology->mod);
    	}
    
    /*!
     * \internal
     * \brief Bridge channel to check if a BRIDGE_PLAY_SOUND needs to be played.
     * \since 12.0.0
     *
     * \param bridge_channel What to check.
     *
     * \return Nothing
     */
    static void check_bridge_play_sound(struct ast_bridge_channel *bridge_channel)
    
    	const char *play_file;
    
    	ast_channel_lock(bridge_channel->chan);
    	play_file = pbx_builtin_getvar_helper(bridge_channel->chan, "BRIDGE_PLAY_SOUND");
    	if (!ast_strlen_zero(play_file)) {
    		play_file = ast_strdupa(play_file);
    		pbx_builtin_setvar_helper(bridge_channel->chan, "BRIDGE_PLAY_SOUND", NULL);
    	} else {
    		play_file = NULL;
    
    	ast_channel_unlock(bridge_channel->chan);
    
    	if (play_file) {
    		ast_bridge_channel_queue_playfile(bridge_channel, NULL, play_file, NULL);
    
    /*!
     * \internal
     * \brief Check for any BRIDGE_PLAY_SOUND channel variables in the bridge.
     * \since 12.0.0
     *
     * \param bridge What to operate on.
     *
     * \note On entry, the bridge is already locked.
     *
     * \return Nothing
     */
    static void check_bridge_play_sounds(struct ast_bridge *bridge)
    
    	struct ast_bridge_channel *bridge_channel;
    
    	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
    		check_bridge_play_sound(bridge_channel);
    	}
    
    void ast_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
    
    	ast_channel_stage_snapshot(chan);
    
    	pbx_builtin_setvar_helper(chan, "BRIDGEPEER", name);
    	pbx_builtin_setvar_helper(chan, "BRIDGEPVTCALLID", pvtid);
    
    	ast_channel_stage_snapshot_done(chan);
    
     * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a 2 party bridge.
    
     * \param c0 Party of the first part.
     * \param c1 Party of the second part.
     *
     * \note On entry, the bridge is already locked.
     * \note The bridge is expected to have exactly two parties.
    
    static void set_bridge_peer_vars_2party(struct ast_channel *c0, struct ast_channel *c1)
    
    	const char *c0_name;
    	const char *c1_name;
    	const char *c0_pvtid = NULL;
    	const char *c1_pvtid = NULL;
    #define UPDATE_BRIDGE_VARS_GET(chan, name, pvtid)									\
    	do {																			\
    		name = ast_strdupa(ast_channel_name(chan));									\
    		if (ast_channel_tech(chan)->get_pvt_uniqueid) {								\
    			pvtid = ast_strdupa(ast_channel_tech(chan)->get_pvt_uniqueid(chan));	\
    		}																			\
    	} while (0)
    
    	ast_channel_lock(c1);
    	UPDATE_BRIDGE_VARS_GET(c1, c1_name, c1_pvtid);
    	ast_channel_unlock(c1);
    
    	ast_channel_lock(c0);
    
    	ast_bridge_vars_set(c0, c1_name, c1_pvtid);
    
    	UPDATE_BRIDGE_VARS_GET(c0, c0_name, c0_pvtid);
    	ast_channel_unlock(c0);
    
    	ast_channel_lock(c1);
    
    	ast_bridge_vars_set(c1, c0_name, c0_pvtid);
    
    	ast_channel_unlock(c1);
    
     * \brief Fill the BRIDGEPEER value buffer with a comma separated list of channel names.
    
     * \param buf Buffer to fill.  The caller must guarantee the buffer is large enough.
     * \param cur_idx Which index into names[] to skip.
     * \param names Channel names to put in the buffer.
     * \param num_names Number of names in the array.
    
    static void fill_bridgepeer_buf(char *buf, unsigned int cur_idx, const char *names[], unsigned int num_names)
    
    	int need_separator = 0;
    	unsigned int idx;
    	const char *src;
    	char *pos;
    
    	pos = buf;
    	for (idx = 0; idx < num_names; ++idx) {
    		if (idx == cur_idx) {
    			continue;
    
    
    		if (need_separator) {
    			*pos++ = ',';
    
    		need_separator = 1;
    
    		/* Copy name into buffer. */
    		src = names[idx];
    		while (*src) {
    			*pos++ = *src++;
    
     * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a multi-party bridge.
    
     * \param bridge What to operate on.
     *
     * \note On entry, the bridge is already locked.
     * \note The bridge is expected to have more than two parties.
    
    static void set_bridge_peer_vars_multiparty(struct ast_bridge *bridge)
    
    /*
     * Set a maximum number of channel names for the BRIDGEPEER
     * list.  The plus one is for the current channel which is not
     * put in the list.
     */
    #define MAX_BRIDGEPEER_CHANS	(10 + 1)
    
    	unsigned int idx;
    	unsigned int num_names;
    	unsigned int len;
    	const char **names;
    	char *buf;
    	struct ast_bridge_channel *bridge_channel;
    
    	/* Get first MAX_BRIDGEPEER_CHANS channel names. */
    	num_names = MIN(bridge->num_channels, MAX_BRIDGEPEER_CHANS);
    	names = ast_alloca(num_names * sizeof(*names));
    	idx = 0;
    	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
    		if (num_names <= idx) {
    			break;
    
    		ast_channel_lock(bridge_channel->chan);
    		names[idx++] = ast_strdupa(ast_channel_name(bridge_channel->chan));
    		ast_channel_unlock(bridge_channel->chan);
    
    
    	/* Determine maximum buf size needed. */
    	len = num_names;
    	for (idx = 0; idx < num_names; ++idx) {
    		len += strlen(names[idx]);
    
    	buf = ast_alloca(len);
    
    	/* Set the bridge channel variables. */
    	idx = 0;
    	buf[0] = '\0';
    	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
    		if (idx < num_names) {
    			fill_bridgepeer_buf(buf, idx, names, num_names);
    
    		++idx;
    
    		ast_channel_lock(bridge_channel->chan);
    
    		ast_bridge_vars_set(bridge_channel->chan, buf, NULL);
    
    		ast_channel_unlock(bridge_channel->chan);
    
     * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a holding bridge.
    
     * \param bridge What to operate on.
    
     * \note On entry, the bridge is already locked.
    
    static void set_bridge_peer_vars_holding(struct ast_bridge *bridge)
    
    	struct ast_bridge_channel *bridge_channel;
    
    	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
    		ast_channel_lock(bridge_channel->chan);
    
    		ast_bridge_vars_set(bridge_channel->chan, NULL, NULL);
    
    		ast_channel_unlock(bridge_channel->chan);
    
     * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in the bridge.
    
     * \param bridge What to operate on.
     *
     * \note On entry, the bridge is already locked.
    
    static void set_bridge_peer_vars(struct ast_bridge *bridge)
    
    	if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
    		set_bridge_peer_vars_holding(bridge);
    		return;
    	}
    	if (bridge->num_channels < 2) {
    		return;
    	}
    	if (bridge->num_channels == 2) {
    		set_bridge_peer_vars_2party(AST_LIST_FIRST(&bridge->channels)->chan,
    			AST_LIST_LAST(&bridge->channels)->chan);
    	} else {
    		set_bridge_peer_vars_multiparty(bridge);
    
    void bridge_reconfigured(struct ast_bridge *bridge, unsigned int colp_update)
    
    	if (!bridge->reconfigured) {
    		return;
    
    	bridge->reconfigured = 0;
    	if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART)
    		&& smart_bridge_operation(bridge)) {
    		/* Smart bridge failed. */
    
    	bridge_complete_join(bridge);
    
    	if (bridge->dissolved) {
    		return;
    
    	check_bridge_play_sounds(bridge);
    	set_bridge_peer_vars(bridge);
    	ast_bridge_publish_state(bridge);
    
    	if (colp_update) {
    		bridge_reconfigured_connected_line_update(bridge);
    
    struct ast_bridge_channel *bridge_find_channel(struct ast_bridge *bridge, struct ast_channel *chan)
    
    	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
    		if (bridge_channel->chan == chan) {
    
    	return bridge_channel;
    
    }
    
    void ast_bridge_notify_masquerade(struct ast_channel *chan)
    {
    	struct ast_bridge_channel *bridge_channel;
    	struct ast_bridge *bridge;
    
    	/* Safely get the bridge_channel pointer for the chan. */
    	ast_channel_lock(chan);
    	bridge_channel = ast_channel_get_bridge_channel(chan);
    	ast_channel_unlock(chan);
    	if (!bridge_channel) {
    		/* Not in a bridge */
    		return;
    	}
    
    	ast_bridge_channel_lock_bridge(bridge_channel);
    	bridge = bridge_channel->bridge;
    
    	if (bridge_channel == bridge_find_channel(bridge, chan)) {
    
    Richard Mudgett's avatar
    Richard Mudgett committed
    /*
     * XXX ASTERISK-22366 this needs more work.  The channels need
     * to be made compatible again if the formats change. The
     * bridge_channel thread needs to monitor for this case.
     */
    
    		/* The channel we want to notify is still in a bridge. */
    		bridge->v_table->notify_masquerade(bridge, bridge_channel);
    
    /*!
     * \brief Internal bridge impart wait condition and associated conditional.
     */
    struct bridge_channel_impart_cond {
    	AST_LIST_ENTRY(bridge_channel_impart_cond) node;
    	/*! Lock for the data structure */
    	ast_mutex_t lock;
    	/*! Wait condition */
    	ast_cond_t cond;
    	/*! Wait until done */
    	int done;
    };
    
    AST_LIST_HEAD_NOLOCK(bridge_channel_impart_ds_head, bridge_channel_impart_cond);
    
    /*!
     * \internal
     * \brief Signal imparting threads to wake up.
     * \since 13.9.0
     *
     * \param ds_head List of imparting threads to wake up.
     *
     * \return Nothing
     */
    static void bridge_channel_impart_ds_head_signal(struct bridge_channel_impart_ds_head *ds_head)
    {
    	if (ds_head) {
    		struct bridge_channel_impart_cond *cond;
    
    		while ((cond = AST_LIST_REMOVE_HEAD(ds_head, node))) {
    			ast_mutex_lock(&cond->lock);
    			cond->done = 1;
    			ast_cond_signal(&cond->cond);
    			ast_mutex_unlock(&cond->lock);
    		}
    	}
    }
    
    static void bridge_channel_impart_ds_head_dtor(void *doomed)
    {
    	bridge_channel_impart_ds_head_signal(doomed);
    	ast_free(doomed);
    }
    
    /*!
     * \internal
     * \brief Fixup the bridge impart datastore.
     * \since 13.9.0
     *
     * \param data Bridge impart datastore data to fixup from old_chan.
     * \param old_chan The datastore is moving from this channel.
     * \param new_chan The datastore is moving to this channel.
     *
     * \return Nothing
     */
    static void bridge_channel_impart_ds_head_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
    {
    	/*
    	 * Signal any waiting impart threads.  The masquerade is going to kill
    	 * old_chan and we don't need to be waiting on new_chan.
    	 */
    	bridge_channel_impart_ds_head_signal(data);
    }
    
    static const struct ast_datastore_info bridge_channel_impart_ds_info = {
    	.type = "bridge-impart-ds",
    	.destroy = bridge_channel_impart_ds_head_dtor,
    	.chan_fixup = bridge_channel_impart_ds_head_fixup,
    };
    
    /*!
     * \internal
     * \brief Add impart wait datastore conditional to channel.
     * \since 13.9.0
     *
     * \param chan Channel to add the impart wait conditional.
     * \param cond Imparting conditional to add.
     *
     * \retval 0 on success.
     * \retval -1 on error.
     */
    static int bridge_channel_impart_add(struct ast_channel *chan, struct bridge_channel_impart_cond *cond)
    {
    	struct ast_datastore *datastore;
    	struct bridge_channel_impart_ds_head *ds_head;
    
    	ast_channel_lock(chan);
    
    	datastore = ast_channel_datastore_find(chan, &bridge_channel_impart_ds_info, NULL);
    	if (!datastore) {
    		datastore = ast_datastore_alloc(&bridge_channel_impart_ds_info, NULL);
    		if (!datastore) {
    			ast_channel_unlock(chan);
    			return -1;
    		}
    		ds_head = ast_calloc(1, sizeof(*ds_head));
    		if (!ds_head) {
    			ast_channel_unlock(chan);
    			ast_datastore_free(datastore);
    			return -1;
    		}
    		datastore->data = ds_head;
    		ast_channel_datastore_add(chan, datastore);
    	} else {
    		ds_head = datastore->data;
    		ast_assert(ds_head != NULL);
    	}
    
    	AST_LIST_INSERT_TAIL(ds_head, cond, node);
    
    	ast_channel_unlock(chan);
    	return 0;
    }
    
    void bridge_channel_impart_signal(struct ast_channel *chan)
    {
    	struct ast_datastore *datastore;
    
    	ast_channel_lock(chan);
    	datastore = ast_channel_datastore_find(chan, &bridge_channel_impart_ds_info, NULL);
    	if (datastore) {
    		bridge_channel_impart_ds_head_signal(datastore->data);
    	}
    	ast_channel_unlock(chan);
    }
    
    /*!
     * \internal
     * \brief Block imparting channel thread until signaled.
     * \since 13.9.0
     *
     * \param cond Imparting conditional to wait for.
     *
     * \return Nothing
     */
    static void bridge_channel_impart_wait(struct bridge_channel_impart_cond *cond)
    {
    	ast_mutex_lock(&cond->lock);
    	while (!cond->done) {
    		ast_cond_wait(&cond->cond, &cond->lock);
    	}
    	ast_mutex_unlock(&cond->lock);
    }
    
    
     * XXX ASTERISK-21271 make ast_bridge_join() require features to be allocated just like ast_bridge_impart() and not expect the struct back.
    
     *
     * This change is really going to break ConfBridge.  All other
     * users are easily changed.  However, it is needed so the
     * bridging code can manipulate features on all channels
     * consistently no matter how they joined.
     *
     * Need to update the features parameter doxygen when this
     * change is made to be like ast_bridge_impart().
     */
    
    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)
    
    	bridge_channel = bridge_channel_internal_alloc(bridge);
    
    	if (flags & AST_BRIDGE_JOIN_PASS_REFERENCE) {
    
    		ao2_t_cleanup(swap, "Error exit: bridge_channel alloc failed");
    
    /* 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. */
    
    	ast_assert(features != NULL);
    	if (!features) {
    		ao2_ref(bridge_channel, -1);
    
    		ao2_t_cleanup(swap, "Error exit: features is NULL");
    
    		goto join_exit;
    	}
    	if (tech_args) {
    		bridge_channel->tech_args = *tech_args;
    	}
    
    	ast_channel_lock(chan);
    
    	if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)) {
    		res = -1;
    	} else {
    		ast_channel_internal_bridge_channel_set(chan, bridge_channel);
    	}
    
    	ast_channel_unlock(chan);
    	bridge_channel->thread = pthread_self();
    	bridge_channel->chan = chan;
    	bridge_channel->swap = swap;
    	bridge_channel->features = features;
    
    	bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP);
    
    	/* allow subclass to peek at upcoming push operation */
    	if (bridge->v_table->push_peek && !res) {
    		struct ast_bridge_channel *bcswap = NULL;
    
    		ast_bridge_lock(bridge);
    		if (bridge_channel->swap) {
    			bcswap = bridge_find_channel(bridge, bridge_channel->swap);
    		}
    		res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
    		ast_bridge_unlock(bridge);
    	}
    
    
    		res = bridge_channel_internal_join(bridge_channel);
    
    
    	/* Cleanup all the data in the bridge channel after it leaves the bridge. */
    	ast_channel_lock(chan);
    	ast_channel_internal_bridge_channel_set(chan, NULL);
    	ast_channel_unlock(chan);
    	bridge_channel->chan = NULL;
    
    	/* If bridge_channel->swap is not NULL then the join failed. */
    	ao2_t_cleanup(bridge_channel->swap, "Bridge complete: join failed");
    
    	bridge_channel->swap = NULL;
    	bridge_channel->features = NULL;
    
    	ao2_ref(bridge_channel, -1);
    
    join_exit:;
    
    	ast_bridge_run_after_callback(chan);
    
    	bridge_channel_impart_signal(chan);
    
    	if (!(ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO)
    
    		&& !ast_bridge_setup_after_goto(chan)) {
    
    		/* Claim the after bridge goto is an async goto destination. */
    		ast_channel_lock(chan);
    		ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
    		ast_channel_unlock(chan);
    	}
    
    }
    
    /*! \brief Thread responsible for imparted bridged channels to be departed */
    static void *bridge_channel_depart_thread(void *data)
    {
    
    	struct ast_bridge_channel *bridge_channel = data;
    
    
    	if (bridge_channel->callid) {
    		ast_callid_threadassoc_add(bridge_channel->callid);
    	}
    
    
    	res = bridge_channel_internal_join(bridge_channel);
    
    	/*
    	 * cleanup
    	 *
    	 * If bridge_channel->swap is not NULL then the join failed.
    	 */
    	ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Departable impart join failed");
    
    	bridge_channel->swap = NULL;
    	ast_bridge_features_destroy(bridge_channel->features);
    	bridge_channel->features = NULL;
    
    
    	ast_bridge_discard_after_callback(bridge_channel->chan,
    		res ? AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED : AST_BRIDGE_AFTER_CB_REASON_DEPART);
    
    	/* If join failed there will be impart threads waiting. */
    	bridge_channel_impart_signal(bridge_channel->chan);
    
    	ast_bridge_discard_after_goto(bridge_channel->chan);
    
    
    	return NULL;
    }
    
    /*! \brief Thread responsible for independent imparted bridged channels */
    static void *bridge_channel_ind_thread(void *data)
    {
    
    	struct ast_bridge_channel *bridge_channel = data;
    
    	struct ast_channel *chan;
    
    	if (bridge_channel->callid) {
    		ast_callid_threadassoc_add(bridge_channel->callid);
    	}
    
    
    	bridge_channel_internal_join(bridge_channel);
    
    	chan = bridge_channel->chan;
    
    	/* cleanup */
    	ast_channel_lock(chan);
    	ast_channel_internal_bridge_channel_set(chan, NULL);
    	ast_channel_unlock(chan);
    	bridge_channel->chan = NULL;
    
    	/* If bridge_channel->swap is not NULL then the join failed. */
    	ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Independent impart join failed");
    
    	bridge_channel->swap = NULL;
    	ast_bridge_features_destroy(bridge_channel->features);
    	bridge_channel->features = NULL;
    
    	ao2_ref(bridge_channel, -1);
    
    
    	ast_bridge_run_after_callback(chan);
    
    	/* If join failed there will be impart threads waiting. */
    	bridge_channel_impart_signal(chan);
    
    	ast_bridge_run_after_goto(chan);
    
    static int bridge_impart_internal(struct ast_bridge *bridge,
    
    	struct ast_channel *chan,
    	struct ast_channel *swap,
    	struct ast_bridge_features *features,
    
    	enum ast_bridge_impart_flags flags,
    	struct bridge_channel_impart_cond *cond)
    
    	/* Imparted channels cannot have a PBX. */
    	if (ast_channel_pbx(chan)) {
    		ast_log(AST_LOG_WARNING, "Channel %s has a PBX thread and cannot be imparted into bridge %s\n",
    			ast_channel_name(chan), bridge->uniqueid);
    
    	/* Supply an empty features structure if the caller did not. */
    	if (!features) {
    		features = ast_bridge_features_new();
    		if (!features) {
    			return -1;
    		}
    	}
    
    	/* Try to allocate a structure for the bridge channel */
    
    	bridge_channel = bridge_channel_internal_alloc(bridge);
    
    	if (!bridge_channel) {
    		ast_bridge_features_destroy(features);
    		return -1;
    	}
    
    	ast_channel_lock(chan);
    
    	if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)) {
    		ast_log(AST_LOG_NOTICE, "Channel %s is a zombie and cannot be imparted into bridge %s\n",
    			ast_channel_name(chan), bridge->uniqueid);
    		res = -1;
    	} else {
    		ast_channel_internal_bridge_channel_set(chan, bridge_channel);
    	}
    
    	ast_channel_unlock(chan);
    	bridge_channel->chan = chan;
    
    	bridge_channel->swap = ao2_t_bump(swap, "Setting up bridge impart");
    
    	bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP);
    	bridge_channel->depart_wait =
    		(flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_DEPARTABLE;
    
    	bridge_channel->callid = ast_read_threadstorage_callid();
    
    
    	/* allow subclass to peek at swap channel before it can hangup */
    	if (bridge->v_table->push_peek && !res) {
    		struct ast_bridge_channel *bcswap = NULL;
    
    		ast_bridge_lock(bridge);
    		if (bridge_channel->swap) {
    			bcswap = bridge_find_channel(bridge, bridge_channel->swap);
    		}
    		res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
    		ast_bridge_unlock(bridge);
    	}
    
    
    	/* Actually create the thread that will handle the channel */
    
    		res = bridge_channel_impart_add(chan, cond);
    	}
    	if (!res) {
    
    		if ((flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_INDEPENDENT) {
    
    			res = ast_pthread_create_detached(&bridge_channel->thread, NULL,
    
    				bridge_channel_ind_thread, bridge_channel);
    
    		} else {
    			res = ast_pthread_create(&bridge_channel->thread, NULL,
    
    				bridge_channel_depart_thread, bridge_channel);
    
    			bridge_channel_impart_wait(cond);
    
    	}
    
    	if (res) {
    		/* cleanup */
    		ast_channel_lock(chan);
    		ast_channel_internal_bridge_channel_set(chan, NULL);
    		ast_channel_unlock(chan);
    		bridge_channel->chan = NULL;
    
    		ao2_t_cleanup(bridge_channel->swap, "Bridge complete: Impart failed");
    
    		bridge_channel->swap = NULL;
    		ast_bridge_features_destroy(bridge_channel->features);
    		bridge_channel->features = NULL;
    
    		ao2_ref(bridge_channel, -1);
    		return -1;
    	}
    
    	return 0;
    }
    
    
    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)
    {
    	struct bridge_channel_impart_cond cond = {
    		.done = 0,
    	};
    	int res;
    
    	ast_mutex_init(&cond.lock);
    	ast_cond_init(&cond.cond, NULL);
    
    	res = bridge_impart_internal(bridge, chan, swap, features, flags, &cond);
    	if (res) {
    		/* Impart failed.  Signal any other waiting impart threads */
    		bridge_channel_impart_signal(chan);
    	}
    
    	ast_cond_destroy(&cond.cond);
    	ast_mutex_destroy(&cond.lock);
    
    	return res;
    }
    
    
    int ast_bridge_depart(struct ast_channel *chan)
    {
    	struct ast_bridge_channel *bridge_channel;
    	int departable;
    
    	ast_channel_lock(chan);
    	bridge_channel = ast_channel_internal_bridge_channel(chan);
    	departable = bridge_channel && bridge_channel->depart_wait;
    	ast_channel_unlock(chan);
    	if (!departable) {
    		ast_log(LOG_ERROR, "Channel %s cannot be departed.\n",
    			ast_channel_name(chan));
    		/*
    		 * Should never happen.  It likely means that
    		 * ast_bridge_depart() is called by two threads for the same
    		 * channel, the channel was never imparted to be departed, or it
    		 * has already been departed.
    		 */
    		ast_assert(0);
    		return -1;
    	}
    
    	/*
    
    	 * We are claiming the bridge_channel reference held by
    	 * bridge_channel_depart_thread().
    
    	ast_bridge_channel_leave_bridge(bridge_channel,
    		BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
    
    
    	/* Wait for the depart thread to die */
    	ast_debug(1, "Waiting for %p(%s) bridge thread to die.\n",
    		bridge_channel, ast_channel_name(bridge_channel->chan));
    	pthread_join(bridge_channel->thread, NULL);
    
    	ast_channel_lock(chan);
    	ast_channel_internal_bridge_channel_set(chan, NULL);
    	ast_channel_unlock(chan);
    
    	/* We can get rid of the bridge_channel after the depart thread has died. */
    	ao2_ref(bridge_channel, -1);
    	return 0;
    }
    
    int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
    {
    	struct ast_bridge_channel *bridge_channel;
    
    	ast_bridge_lock(bridge);
    
    	/* Try to find the channel that we want to remove */
    
    	if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
    
    	ast_bridge_channel_leave_bridge(bridge_channel,
    		BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
    
    static void kick_it(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
    {
    
    	ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
    
    }
    
    int ast_bridge_kick(struct ast_bridge *bridge, struct ast_channel *chan)
    {
    	struct ast_bridge_channel *bridge_channel;