[asterisk-commits] mmichelson: branch mmichelson/transfer r386618 - in /team/mmichelson/transfer...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Apr 26 12:00:02 CDT 2013
Author: mmichelson
Date: Fri Apr 26 11:59:58 2013
New Revision: 386618
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386618
Log:
Resolve conflict and reset automerge.
Modified:
team/mmichelson/transfer/ (props changed)
team/mmichelson/transfer/apps/app_bridgewait.c
team/mmichelson/transfer/apps/confbridge/conf_config_parser.c
team/mmichelson/transfer/bridges/bridge_simple.c
team/mmichelson/transfer/configs/res_sip.conf.sample
team/mmichelson/transfer/include/asterisk/bridging.h
team/mmichelson/transfer/include/asterisk/bridging_features.h
team/mmichelson/transfer/main/bridging.c
Propchange: team/mmichelson/transfer/
------------------------------------------------------------------------------
automerge = *
Propchange: team/mmichelson/transfer/
------------------------------------------------------------------------------
--- bridge_construction-integrated (original)
+++ bridge_construction-integrated Fri Apr 26 11:59:58 2013
@@ -1,1 +1,1 @@
-/trunk:1-386543
+/trunk:1-386590
Propchange: team/mmichelson/transfer/
------------------------------------------------------------------------------
--- transfer-integrated (original)
+++ transfer-integrated Fri Apr 26 11:59:58 2013
@@ -1,1 +1,1 @@
-/team/group/bridge_construction:1-386571
+/team/group/bridge_construction:1-386617
Modified: team/mmichelson/transfer/apps/app_bridgewait.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/apps/app_bridgewait.c?view=diff&rev=386618&r1=386617&r2=386618
==============================================================================
--- team/mmichelson/transfer/apps/app_bridgewait.c (original)
+++ team/mmichelson/transfer/apps/app_bridgewait.c Fri Apr 26 11:59:58 2013
@@ -196,8 +196,8 @@
ast_mutex_lock(&bridgewait_lock);
if (!holding_bridge) {
holding_bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING,
- AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM |
- AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
+ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
+ | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
}
ast_mutex_unlock(&bridgewait_lock);
if (!holding_bridge) {
Modified: team/mmichelson/transfer/apps/confbridge/conf_config_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/apps/confbridge/conf_config_parser.c?view=diff&rev=386618&r1=386617&r2=386618
==============================================================================
--- team/mmichelson/transfer/apps/confbridge/conf_config_parser.c (original)
+++ team/mmichelson/transfer/apps/confbridge/conf_config_parser.c Fri Apr 26 11:59:58 2013
@@ -1915,6 +1915,7 @@
/* This option should only be used with the CONFBRIDGE dialplan function */
aco_option_register_custom(&cfg_info, "template", ACO_EXACT, user_types, NULL, user_template_handler, 0);
+/* BUGBUG need a user supplied bridge merge_priority to merge ConfBridges (default = 1, range 1-INT_MAX) */
/* Bridge options */
aco_option_register(&cfg_info, "type", ACO_EXACT, bridge_types, NULL, OPT_NOOP_T, 0, 0);
aco_option_register(&cfg_info, "jitterbuffer", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), USER_OPT_JITTERBUFFER);
Modified: team/mmichelson/transfer/bridges/bridge_simple.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/bridges/bridge_simple.c?view=diff&rev=386618&r1=386617&r2=386618
==============================================================================
--- team/mmichelson/transfer/bridges/bridge_simple.c (original)
+++ team/mmichelson/transfer/bridges/bridge_simple.c Fri Apr 26 11:59:58 2013
@@ -70,15 +70,10 @@
{
struct ast_bridge_channel *other;
- /* If this is the only channel in this bridge then immediately exit */
- if (AST_LIST_FIRST(&bridge->channels) == AST_LIST_LAST(&bridge->channels)) {
+ /* Find the channel we actually want to write to */
+ other = ast_bridge_channel_peer(bridge_channel);
+ if (!other) {
return -1;
- }
-
- /* Find the channel we actually want to write to */
- other = AST_LIST_FIRST(&bridge->channels);
- if (other == bridge_channel) {
- other = AST_LIST_LAST(&bridge->channels);
}
/* The bridging core takes care of freeing the passed in frame. */
Modified: team/mmichelson/transfer/configs/res_sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/configs/res_sip.conf.sample?view=diff&rev=386618&r1=386617&r2=386618
==============================================================================
--- team/mmichelson/transfer/configs/res_sip.conf.sample (original)
+++ team/mmichelson/transfer/configs/res_sip.conf.sample Fri Apr 26 11:59:58 2013
@@ -1,10 +1,10 @@
; This is an in-flux configuration file for the res_sip module, it will change as things progress
;;; Transports
-[local]
-type=transport
-protocol=udp ; Supported protocols are udp, tcp, and tls
-bind=0.0.0.0 ; This supports both IPv4 and IPv6, port is optional
+;[local]
+;type=transport
+;protocol=udp ; Supported protocols are udp, tcp, and tls
+;bind=0.0.0.0 ; This supports both IPv4 and IPv6, port is optional
;;; Endpoints
[endpoint]
Modified: team/mmichelson/transfer/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/include/asterisk/bridging.h?view=diff&rev=386618&r1=386617&r2=386618
==============================================================================
--- team/mmichelson/transfer/include/asterisk/bridging.h (original)
+++ team/mmichelson/transfer/include/asterisk/bridging.h Fri Apr 26 11:59:58 2013
@@ -351,6 +351,17 @@
typedef void (*ast_bridge_notify_masquerade_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel);
/*!
+ * \brief Get the merge priority of this bridge.
+ *
+ * \param self Bridge to operate upon.
+ *
+ * \note On entry, self is already locked.
+ *
+ * \return Merge priority
+ */
+typedef int (*ast_bridge_merge_priority_fn)(struct ast_bridge *self);
+
+/*!
* \brief Bridge virtual methods table definition.
*
* \note Any changes to this struct must be reflected in
@@ -369,6 +380,8 @@
ast_bridge_pull_channel_fn pull;
/*! Notify the bridge of a masquerade with the channel. */
ast_bridge_notify_masquerade_fn notify_masquerade;
+ /*! Get the bridge merge priority. */
+ ast_bridge_merge_priority_fn get_merge_priority;
};
/*!
@@ -768,6 +781,21 @@
int ast_bridge_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge);
/*!
+ * \brief Move a channel from one bridge to another.
+ * \since 12.0.0
+ *
+ * \param dst_bridge Destination bridge of bridge channel move.
+ * \param src_bridge Source bridge of bridge channel move.
+ * \param chan Channel to move.
+ * \param swap Channel to replace in dst_bridge.
+ * \param attempt_recovery TRUE if failure attempts to push channel back into original bridge.
+ *
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ */
+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);
+
+/*!
* \brief Adjust the bridge merge inhibit request count.
* \since 12.0.0
*
@@ -1163,6 +1191,21 @@
* \param bridge_channel Channel to restore
*/
void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel);
+
+/*!
+ * \brief Get the peer bridge channel of a two party bridge.
+ * \since 12.0.0
+ *
+ * \param bridge_channel What to get the peer of.
+ *
+ * \note On entry, bridge_channel->bridge is already locked.
+ *
+ * \note This is an internal bridge function.
+ *
+ * \retval peer on success.
+ * \retval NULL no peer channel.
+ */
+struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Adjust the internal mixing sample rate of a bridge
Modified: team/mmichelson/transfer/include/asterisk/bridging_features.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/include/asterisk/bridging_features.h?view=diff&rev=386618&r1=386617&r2=386618
==============================================================================
--- team/mmichelson/transfer/include/asterisk/bridging_features.h (original)
+++ team/mmichelson/transfer/include/asterisk/bridging_features.h Fri Apr 26 11:59:58 2013
@@ -40,8 +40,12 @@
AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM = (1 << 3),
/*! Bridge channels cannot be merged to this bridge. */
AST_BRIDGE_FLAG_MERGE_INHIBIT_TO = (1 << 4),
+ /*! Bridge channels cannot be local channel swap optimized from this bridge. */
+ AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM = (1 << 5),
+ /*! Bridge channels cannot be local channel swap optimized to this bridge. */
+ AST_BRIDGE_FLAG_SWAP_INHIBIT_TO = (1 << 6),
/*! Bridge channels can be moved to another bridge only by masquerade (ConfBridge) */
- AST_BRIDGE_FLAG_MASQUERADE_ONLY = (1 << 5),
+ AST_BRIDGE_FLAG_MASQUERADE_ONLY = (1 << 7),
/*! Bridge does not allow transfers of channels out */
AST_BRIDGE_FLAG_TRANSFER_PROHIBITED = (1 << 6),
/*! Bridge transfers require transfer of entire bridge rather than individual channels */
Modified: team/mmichelson/transfer/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/main/bridging.c?view=diff&rev=386618&r1=386617&r2=386618
==============================================================================
--- team/mmichelson/transfer/main/bridging.c (original)
+++ team/mmichelson/transfer/main/bridging.c Fri Apr 26 11:59:58 2013
@@ -1214,7 +1214,8 @@
|| !v_table->dissolving
|| !v_table->push
|| !v_table->pull
- || !v_table->notify_masquerade) {
+ || !v_table->notify_masquerade
+ || !v_table->get_merge_priority) {
ast_log(LOG_ERROR, "Virtual method table for bridge class %s not complete.\n",
v_table && v_table->name ? v_table->name : "<unknown>");
ast_assert(0);
@@ -1360,6 +1361,22 @@
self->reconfigured = 1;
}
+/*!
+ * \internal
+ * \brief Get the merge priority of this bridge.
+ * \since 12.0.0
+ *
+ * \param self Bridge to operate upon.
+ *
+ * \note On entry, self is already locked.
+ *
+ * \return Merge priority
+ */
+static int bridge_base_get_merge_priority(struct ast_bridge *self)
+{
+ return 0;
+}
+
struct ast_bridge_methods ast_bridge_base_v_table = {
.name = "base",
.destroy = bridge_base_destroy,
@@ -1367,6 +1384,7 @@
.push = bridge_base_push,
.pull = bridge_base_pull,
.notify_masquerade = bridge_base_notify_masquerade,
+ .get_merge_priority = bridge_base_get_merge_priority,
};
struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags)
@@ -3149,6 +3167,114 @@
/*!
* \internal
+ * \brief Move a bridge channel from one bridge to another.
+ * \since 12.0.0
+ *
+ * \param dst_bridge Destination bridge of bridge channel move.
+ * \param bridge_channel Channel moving from one bridge to another.
+ * \param attempt_recovery TRUE if failure attempts to push channel back into original bridge.
+ *
+ * \note The dst_bridge and bridge_channel->bridge are assumed already locked.
+ *
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ */
+static int bridge_move_do(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel, int attempt_recovery)
+{
+ struct ast_bridge *orig_bridge;
+ int was_in_bridge;
+ int res = 0;
+
+/* BUGBUG need bridge move stasis event and a success/fail event. */
+ if (bridge_channel->swap) {
+ ast_debug(1, "Moving %p(%s) into bridge %s swapping with %s\n",
+ bridge_channel, ast_channel_name(bridge_channel->chan), dst_bridge->uniqueid,
+ ast_channel_name(bridge_channel->swap));
+ } else {
+ ast_debug(1, "Moving %p(%s) into bridge %s\n",
+ bridge_channel, ast_channel_name(bridge_channel->chan), dst_bridge->uniqueid);
+ }
+
+ orig_bridge = bridge_channel->bridge;
+ was_in_bridge = bridge_channel->in_bridge;
+
+ bridge_channel_pull(bridge_channel);
+
+ /* Point to new bridge.*/
+ ao2_ref(dst_bridge, +1);
+ ast_bridge_channel_lock(bridge_channel);
+ bridge_channel->bridge = dst_bridge;
+ ast_bridge_channel_unlock(bridge_channel);
+
+ if (bridge_channel_push(bridge_channel)) {
+ /* Try to put the channel back into the original bridge. */
+ if (attempt_recovery && was_in_bridge) {
+ /* Point back to original bridge. */
+ ao2_ref(orig_bridge, +1);
+ ast_bridge_channel_lock(bridge_channel);
+ bridge_channel->bridge = orig_bridge;
+ ast_bridge_channel_unlock(bridge_channel);
+ ao2_ref(dst_bridge, -1);
+
+ if (bridge_channel_push(bridge_channel)) {
+ ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+ }
+ } else {
+ ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+ }
+ res = -1;
+ }
+
+ bridge_reconfigured(dst_bridge);
+ bridge_reconfigured(orig_bridge);
+ ao2_ref(orig_bridge, -1);
+ return res;
+}
+
+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)
+{
+ struct ast_bridge_channel *bridge_channel;
+ int res = -1;
+
+ ast_bridge_lock_both(dst_bridge, src_bridge);
+
+ bridge_channel = find_bridge_channel(src_bridge, chan);
+ if (!bridge_channel) {
+ ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel not in bridge.\n",
+ ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
+ } else if (bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT) {
+ ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, channel leaving bridge.\n",
+ ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
+ } else if (dst_bridge->dissolved || src_bridge->dissolved) {
+ ast_debug(1, "Can't move channel %s from bridge %s into bridge %s, one or both bridges are dissolved.\n",
+ ast_channel_name(chan), src_bridge->uniqueid, dst_bridge->uniqueid);
+ } else {
+ bridge_channel->swap = swap;
+ res = bridge_move_do(dst_bridge, bridge_channel, attempt_recovery);
+ }
+
+ ast_bridge_unlock(src_bridge);
+ ast_bridge_unlock(dst_bridge);
+ return res;
+}
+
+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) {
+ other = AST_LIST_FIRST(&bridge->channels);
+ if (other == bridge_channel) {
+ other = AST_LIST_LAST(&bridge->channels);
+ }
+ }
+
+ return other;
+}
+
+/*!
+ * \internal
* \brief Lock the local channel stack for chan and prequalify it.
* \since 12.0.0
*
@@ -3181,6 +3307,7 @@
if (bridge->inhibit_merge
|| bridge->dissolved
|| ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)
+ || !bridge_channel->in_bridge
|| !AST_LIST_EMPTY(&bridge_channel->wr_queue)) {
ast_bridge_unlock(bridge);
ast_bridge_channel_unlock(bridge_channel);
@@ -3227,6 +3354,7 @@
if (bridge->inhibit_merge
|| bridge->dissolved
|| ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)
+ || !bridge_channel->in_bridge
|| !AST_LIST_EMPTY(&bridge_channel->wr_queue)) {
ast_bridge_unlock(bridge);
ast_bridge_channel_unlock(bridge_channel);
@@ -3236,76 +3364,207 @@
return bridge;
}
-int ast_bridge_local_optimized_out(struct ast_channel *chan, struct ast_channel *peer)
-{
- struct ast_bridge *chan_bridge;
- struct ast_bridge *peer_bridge;
- struct ast_bridge_channel *chan_bridge_channel;
- struct ast_bridge_channel *peer_bridge_channel;
+/*!
+ * \internal
+ * \brief Check and attempt to swap optimize out the local channels.
+ * \since 12.0.0
+ *
+ * \param chan_bridge
+ * \param chan_bridge_channel
+ * \param peer_bridge
+ * \param peer_bridge_channel
+ *
+ * \retval 1 if local channels failed to optimize out.
+ * \retval 0 if local channels were not optimized out.
+ * \retval -1 if local channels were optimized out.
+ */
+static int check_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_bridge *dst_bridge = NULL;
+ struct ast_bridge *src_bridge = NULL;
+ struct ast_bridge_channel *dst_bridge_channel = NULL;
+ struct ast_bridge_channel *src_bridge_channel = NULL;
+ int peer_priority;
+ int chan_priority;
int res = 0;
- chan_bridge = optimize_lock_chan_stack(chan);
- if (!chan_bridge) {
- return res;
- }
- chan_bridge_channel = ast_channel_internal_bridge_channel(chan);
-
- peer_bridge = optimize_lock_peer_stack(peer);
- if (peer_bridge) {
- struct ast_bridge *dst_bridge = NULL;
- struct ast_bridge *src_bridge = NULL;
-
- peer_bridge_channel = ast_channel_internal_bridge_channel(peer);
-
- if (!ast_test_flag(&chan_bridge->feature_flags,
- AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)
- && !ast_test_flag(&peer_bridge->feature_flags,
- AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
-/* BUGBUG need to have a merge priority bridge class method to help determine which way to optimize merge. */
- /* Can merge either way. */
+ if (!ast_test_flag(&chan_bridge->feature_flags,
+ AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM)
+ && !ast_test_flag(&peer_bridge->feature_flags,
+ AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM)) {
+ /*
+ * Can swap either way. Swap to the higher priority merge
+ * bridge.
+ */
+ chan_priority = chan_bridge->v_table->get_merge_priority(chan_bridge);
+ peer_priority = peer_bridge->v_table->get_merge_priority(peer_bridge);
+ if (chan_bridge->num_channels == 2
+ && chan_priority <= peer_priority) {
+ dst_bridge = peer_bridge;
+ src_bridge = chan_bridge;
+ dst_bridge_channel = peer_bridge_channel;
+ src_bridge_channel = chan_bridge_channel;
+ } else if (peer_bridge->num_channels == 2
+ && peer_priority <= chan_priority) {
+ dst_bridge = chan_bridge;
+ src_bridge = peer_bridge;
+ dst_bridge_channel = chan_bridge_channel;
+ src_bridge_channel = peer_bridge_channel;
+ }
+ } else if (chan_bridge->num_channels == 2
+ && !ast_test_flag(&chan_bridge->feature_flags, AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM)
+ && !ast_test_flag(&peer_bridge->feature_flags, AST_BRIDGE_FLAG_SWAP_INHIBIT_TO)) {
+ /* Can swap optimize only one way. */
+ dst_bridge = peer_bridge;
+ src_bridge = chan_bridge;
+ dst_bridge_channel = peer_bridge_channel;
+ src_bridge_channel = chan_bridge_channel;
+ } else if (peer_bridge->num_channels == 2
+ && !ast_test_flag(&peer_bridge->feature_flags, AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM)
+ && !ast_test_flag(&chan_bridge->feature_flags, AST_BRIDGE_FLAG_SWAP_INHIBIT_TO)) {
+ /* Can swap optimize only one way. */
+ dst_bridge = chan_bridge;
+ src_bridge = peer_bridge;
+ dst_bridge_channel = chan_bridge_channel;
+ src_bridge_channel = peer_bridge_channel;
+ }
+ if (dst_bridge) {
+ struct ast_bridge_channel *other;
+
+ res = 1;
+ other = ast_bridge_channel_peer(src_bridge_channel);
+ if (other) {
+ ast_debug(1, "Move-swap optimizing %s <-- %s.\n",
+ ast_channel_name(dst_bridge_channel->chan),
+ ast_channel_name(other->chan));
+
+ other->swap = dst_bridge_channel->chan;
+ if (!bridge_move_do(dst_bridge, other, 1)) {
+ ast_bridge_change_state(src_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+ res = -1;
+ }
+ }
+ }
+ return res;
+}
+
+/*!
+ * \internal
+ * \brief Check and attempt to merge optimize out the local channels.
+ * \since 12.0.0
+ *
+ * \param chan_bridge
+ * \param chan_bridge_channel
+ * \param peer_bridge
+ * \param peer_bridge_channel
+ *
+ * \retval 0 if local channels were not optimized out.
+ * \retval -1 if local channels were optimized out.
+ */
+static int check_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_bridge *dst_bridge = NULL;
+ struct ast_bridge *src_bridge = NULL;
+ int peer_priority;
+ int chan_priority;
+ int res = 0;
+
+ if (!ast_test_flag(&chan_bridge->feature_flags,
+ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)
+ && !ast_test_flag(&peer_bridge->feature_flags,
+ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
+ /*
+ * Can merge either way. Merge to the higher priority merge
+ * bridge. Otherwise merge to the larger bridge.
+ */
+ chan_priority = chan_bridge->v_table->get_merge_priority(chan_bridge);
+ peer_priority = peer_bridge->v_table->get_merge_priority(peer_bridge);
+ if (peer_priority < chan_priority) {
+ dst_bridge = chan_bridge;
+ src_bridge = peer_bridge;
+ } else if (chan_priority < peer_priority) {
+ dst_bridge = peer_bridge;
+ src_bridge = chan_bridge;
+ } else {
+ /* Merge to the larger bridge. */
if (peer_bridge->num_channels <= chan_bridge->num_channels) {
- /* Merge to the larger bridge. */
dst_bridge = chan_bridge;
src_bridge = peer_bridge;
} else {
dst_bridge = peer_bridge;
src_bridge = chan_bridge;
}
- } else if (!ast_test_flag(&chan_bridge->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
- && !ast_test_flag(&peer_bridge->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
- /* Can merge only one way. */
- dst_bridge = chan_bridge;
- src_bridge = peer_bridge;
- } else if (!ast_test_flag(&peer_bridge->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
- && !ast_test_flag(&chan_bridge->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
- /* Can merge only one way. */
- dst_bridge = peer_bridge;
- src_bridge = chan_bridge;
- }
-
- if (dst_bridge) {
- if (src_bridge->num_channels < 2 || dst_bridge->num_channels < 2) {
- ast_debug(4, "Can't optimize %s -- %s out, not enough channels in a bridge.\n",
- ast_channel_name(chan), ast_channel_name(peer));
- } else if ((2 + 2) < dst_bridge->num_channels + src_bridge->num_channels
- && !(dst_bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)
- && !ast_test_flag(&dst_bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
- ast_debug(4, "Can't optimize %s -- %s out, multimix is needed and it cannot be acquired.\n",
- ast_channel_name(chan), ast_channel_name(peer));
- } else {
- struct ast_bridge_channel *kick_me[] = {
- chan_bridge_channel,
- peer_bridge_channel,
- };
-
- ast_debug(1, "Optimizing %s -- %s out.\n",
- ast_channel_name(chan), ast_channel_name(peer));
-
- bridge_merge_do(dst_bridge, src_bridge, kick_me, ARRAY_LEN(kick_me));
- res = -1;
- }
+ }
+ } else if (!ast_test_flag(&chan_bridge->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
+ && !ast_test_flag(&peer_bridge->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
+ /* Can merge only one way. */
+ dst_bridge = chan_bridge;
+ src_bridge = peer_bridge;
+ } else if (!ast_test_flag(&peer_bridge->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
+ && !ast_test_flag(&chan_bridge->feature_flags, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
+ /* Can merge only one way. */
+ dst_bridge = peer_bridge;
+ src_bridge = chan_bridge;
+ }
+
+ if (dst_bridge) {
+ if (src_bridge->num_channels < 2 || dst_bridge->num_channels < 2) {
+ ast_debug(4, "Can't optimize %s -- %s out, not enough channels in a bridge.\n",
+ ast_channel_name(chan_bridge_channel->chan),
+ ast_channel_name(peer_bridge_channel->chan));
+ } else if ((2 + 2) < dst_bridge->num_channels + src_bridge->num_channels
+ && !(dst_bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)
+ && !ast_test_flag(&dst_bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
+ ast_debug(4, "Can't optimize %s -- %s out, multimix is needed and it cannot be acquired.\n",
+ ast_channel_name(chan_bridge_channel->chan),
+ ast_channel_name(peer_bridge_channel->chan));
} else {
-/* BUGBUG this is where we would decide if we can swap a channel instead of merging. */
+ struct ast_bridge_channel *kick_me[] = {
+ chan_bridge_channel,
+ peer_bridge_channel,
+ };
+
+ ast_debug(1, "Merge optimizing %s -- %s out.\n",
+ ast_channel_name(chan_bridge_channel->chan),
+ ast_channel_name(peer_bridge_channel->chan));
+
+ bridge_merge_do(dst_bridge, src_bridge, kick_me, ARRAY_LEN(kick_me));
+ res = -1;
+ }
+ }
+
+ return res;
+}
+
+int ast_bridge_local_optimized_out(struct ast_channel *chan, struct ast_channel *peer)
+{
+ struct ast_bridge *chan_bridge;
+ struct ast_bridge *peer_bridge;
+ struct ast_bridge_channel *chan_bridge_channel;
+ struct ast_bridge_channel *peer_bridge_channel;
+ int res = 0;
+
+ chan_bridge = optimize_lock_chan_stack(chan);
+ if (!chan_bridge) {
+ return res;
+ }
+ chan_bridge_channel = ast_channel_internal_bridge_channel(chan);
+
+ peer_bridge = optimize_lock_peer_stack(peer);
+ if (peer_bridge) {
+ peer_bridge_channel = ast_channel_internal_bridge_channel(peer);
+
+ res = check_swap_optimize_out(chan_bridge, chan_bridge_channel,
+ peer_bridge, peer_bridge_channel);
+ if (!res) {
+ res = check_merge_optimize_out(chan_bridge, chan_bridge_channel,
+ peer_bridge, peer_bridge_channel);
+ } else if (0 < res) {
+ res = 0;
}
/* Release peer locks. */
More information about the asterisk-commits
mailing list