[asterisk-commits] rmudgett: branch group/bridge_construction r388109 - in /team/group/bridge_co...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed May 8 22:33:52 CDT 2013


Author: rmudgett
Date: Wed May  8 22:33:50 2013
New Revision: 388109

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=388109
Log:
Rework smart bridge technology selection and bridge preference priority.

Modified:
    team/group/bridge_construction/bridges/bridge_builtin_features.c
    team/group/bridge_construction/bridges/bridge_holding.c
    team/group/bridge_construction/bridges/bridge_simple.c
    team/group/bridge_construction/bridges/bridge_softmix.c
    team/group/bridge_construction/include/asterisk/bridging.h
    team/group/bridge_construction/include/asterisk/bridging_technology.h
    team/group/bridge_construction/main/bridging.c
    team/group/bridge_construction/main/bridging_basic.c

Modified: team/group/bridge_construction/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/bridges/bridge_builtin_features.c?view=diff&rev=388109&r1=388108&r2=388109
==============================================================================
--- team/group/bridge_construction/bridges/bridge_builtin_features.c (original)
+++ team/group/bridge_construction/bridges/bridge_builtin_features.c Wed May  8 22:33:50 2013
@@ -308,8 +308,7 @@
 	}
 
 	/* Create a bridge to use to talk to the person we are calling */
-	attended_bridge = ast_bridge_base_new(
-		AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX,
+	attended_bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_1TO1MIX,
 		AST_BRIDGE_FLAG_DISSOLVE_HANGUP);
 	if (!attended_bridge) {
 		ast_bridge_features_cleanup(&caller_features);

Modified: team/group/bridge_construction/bridges/bridge_holding.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/bridges/bridge_holding.c?view=diff&rev=388109&r1=388108&r2=388109
==============================================================================
--- team/group/bridge_construction/bridges/bridge_holding.c (original)
+++ team/group/bridge_construction/bridges/bridge_holding.c Wed May  8 22:33:50 2013
@@ -283,7 +283,7 @@
 static struct ast_bridge_technology holding_bridge = {
 	.name = "holding_bridge",
 	.capabilities = AST_BRIDGE_CAPABILITY_HOLDING,
-	.preference = AST_BRIDGE_PREFERENCE_MEDIUM,
+	.preference = AST_BRIDGE_PREFERENCE_BASE_HOLDING,
 	.write = holding_bridge_write,
 	.join = holding_bridge_join,
 	.leave = holding_bridge_leave,

Modified: team/group/bridge_construction/bridges/bridge_simple.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/bridges/bridge_simple.c?view=diff&rev=388109&r1=388108&r2=388109
==============================================================================
--- team/group/bridge_construction/bridges/bridge_simple.c (original)
+++ team/group/bridge_construction/bridges/bridge_simple.c Wed May  8 22:33:50 2013
@@ -85,7 +85,7 @@
 static struct ast_bridge_technology simple_bridge = {
 	.name = "simple_bridge",
 	.capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX,
-	.preference = AST_BRIDGE_PREFERENCE_MEDIUM,
+	.preference = AST_BRIDGE_PREFERENCE_BASE_1TO1MIX,
 	.join = simple_bridge_join,
 	.write = simple_bridge_write,
 };

Modified: team/group/bridge_construction/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/bridges/bridge_softmix.c?view=diff&rev=388109&r1=388108&r2=388109
==============================================================================
--- team/group/bridge_construction/bridges/bridge_softmix.c (original)
+++ team/group/bridge_construction/bridges/bridge_softmix.c Wed May  8 22:33:50 2013
@@ -1091,7 +1091,7 @@
 static struct ast_bridge_technology softmix_bridge = {
 	.name = "softmix",
 	.capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX,
-	.preference = AST_BRIDGE_PREFERENCE_LOW,
+	.preference = AST_BRIDGE_PREFERENCE_BASE_MULTIMIX,
 	.create = softmix_bridge_create,
 	.destroy = softmix_bridge_destroy,
 	.join = softmix_bridge_join,

Modified: team/group/bridge_construction/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/include/asterisk/bridging.h?view=diff&rev=388109&r1=388108&r2=388109
==============================================================================
--- team/group/bridge_construction/include/asterisk/bridging.h (original)
+++ team/group/bridge_construction/include/asterisk/bridging.h Wed May  8 22:33:50 2013
@@ -76,15 +76,15 @@
 
 /*! \brief Capabilities for a bridge technology */
 enum ast_bridge_capability {
-	/*! Bridge technology can service calls on hold */
+	/*! Bridge technology can service calls on hold. */
 	AST_BRIDGE_CAPABILITY_HOLDING = (1 << 0),
-	/*! Bridge waits for channel to answer.  Passes early media. */
+	/*! Bridge waits for channel to answer.  Passes early media. (XXX Not supported yet) */
 	AST_BRIDGE_CAPABILITY_EARLY = (1 << 1),
-	/*! Bridge should natively bridge two channels if possible */
+	/*! Bridge is capable of natively bridging two channels. (Smart bridge only) */
 	AST_BRIDGE_CAPABILITY_NATIVE = (1 << 2),
-	/*! Bridge is only capable of mixing 2 channels */
+	/*! Bridge is capable of mixing at most two channels. (Smart bridgeable) */
 	AST_BRIDGE_CAPABILITY_1TO1MIX = (1 << 3),
-	/*! Bridge is capable of mixing 2 or more channels */
+	/*! Bridge is capable of mixing an arbitrary number of channels. (Smart bridgeable) */
 	AST_BRIDGE_CAPABILITY_MULTIMIX = (1 << 4),
 };
 
@@ -404,6 +404,8 @@
 	struct ast_bridge_video_mode video_mode;
 	/*! Bridge flags to tweak behavior */
 	struct ast_flags feature_flags;
+	/*! Allowed bridge technology capabilities when AST_BRIDGE_FLAG_SMART enabled. */
+	uint32_t allowed_capabilities;
 	/*! Number of channels participating in the bridge */
 	unsigned int num_channels;
 	/*! Number of active channels in the bridge. */
@@ -572,25 +574,6 @@
 	} while (0)
 
 /*!
- * \brief See if it is possible to create a bridge
- *
- * \param capabilities The capabilities that the bridge will use
- *
- * \retval 1 if possible
- * \retval 0 if not possible
- *
- * Example usage:
- *
- * \code
- * int possible = ast_bridge_check(AST_BRIDGE_CAPABILITY_1TO1MIX);
- * \endcode
- *
- * This sees if it is possible to create a bridge capable of bridging two channels
- * together.
- */
-int ast_bridge_check(uint32_t capabilities);
-
-/*!
  * \brief Destroy a bridge
  *
  * \param bridge Bridge to destroy

Modified: team/group/bridge_construction/include/asterisk/bridging_technology.h
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/include/asterisk/bridging_technology.h?view=diff&rev=388109&r1=388108&r2=388109
==============================================================================
--- team/group/bridge_construction/include/asterisk/bridging_technology.h (original)
+++ team/group/bridge_construction/include/asterisk/bridging_technology.h Wed May  8 22:33:50 2013
@@ -28,14 +28,17 @@
 extern "C" {
 #endif
 
-/*! \brief Preference for choosing the bridge technology */
+/*!
+ * \brief Base preference values for choosing a bridge technology.
+ *
+ * \note Higher is more preference.
+ */
 enum ast_bridge_preference {
-	/*! Bridge technology should have high precedence over other bridge technologies */
-	AST_BRIDGE_PREFERENCE_HIGH = 0,
-	/*! Bridge technology is decent, not the best but should still be considered over low */
-	AST_BRIDGE_PREFERENCE_MEDIUM,
-	/*! Bridge technology is low, it should not be considered unless it is absolutely needed */
-	AST_BRIDGE_PREFERENCE_LOW,
+	AST_BRIDGE_PREFERENCE_BASE_HOLDING  = 50,
+	AST_BRIDGE_PREFERENCE_BASE_EARLY    = 100,
+	AST_BRIDGE_PREFERENCE_BASE_NATIVE   = 90,
+	AST_BRIDGE_PREFERENCE_BASE_1TO1MIX  = 50,
+	AST_BRIDGE_PREFERENCE_BASE_MULTIMIX = 10,
 };
 
 /*!

Modified: team/group/bridge_construction/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/main/bridging.c?view=diff&rev=388109&r1=388108&r2=388109
==============================================================================
--- team/group/bridge_construction/main/bridging.c (original)
+++ team/group/bridge_construction/main/bridging.c Wed May  8 22:33:50 2013
@@ -1014,8 +1014,8 @@
 	}
 }
 
-/*! \brief Helper function used to find the "best" bridge technology given a specified capabilities */
-static struct ast_bridge_technology *find_best_technology(uint32_t capabilities)
+/*! \brief Helper function used to find the "best" bridge technology given specified capabilities */
+static struct ast_bridge_technology *find_best_technology(uint32_t capabilities, struct ast_bridge *bridge)
 {
 	struct ast_bridge_technology *current;
 	struct ast_bridge_technology *best = NULL;
@@ -1028,13 +1028,18 @@
 			continue;
 		}
 		if (!(current->capabilities & capabilities)) {
-			ast_debug(1, "Bridge technology %s does not have the capabilities we need.\n",
+			ast_debug(1, "Bridge technology %s does not have any capabilities we want.\n",
 				current->name);
 			continue;
 		}
-		if (best && best->preference < current->preference) {
-			ast_debug(1, "Bridge technology %s has preference %d while %s has preference %d. Skipping.\n",
-				current->name, current->preference, best->name, best->preference);
+		if (best && current->preference <= best->preference) {
+			ast_debug(1, "Bridge technology %s has less preference than %s (%d <= %d). Skipping.\n",
+				current->name, best->name, current->preference, best->preference);
+			continue;
+		}
+		if (current->compatible && !current->compatible(bridge)) {
+			ast_debug(1, "Bridge technology %s is not compatible with properties of existing bridge.\n",
+				current->name);
 			continue;
 		}
 		best = current;
@@ -1239,25 +1244,13 @@
 
 	ast_uuid_generate_str(self->uniqueid, sizeof(self->uniqueid));
 	ast_set_flag(&self->feature_flags, flags);
-
-	/* If we need to be a smart bridge see if we can move between 1to1 and multimix bridges */
-	if (flags & AST_BRIDGE_FLAG_SMART) {
-		if (!ast_bridge_check((capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX)
-			? AST_BRIDGE_CAPABILITY_MULTIMIX : AST_BRIDGE_CAPABILITY_1TO1MIX)) {
-			ao2_ref(self, -1);
-			return NULL;
-		}
-	}
-
-	/*
-	 * If capabilities were provided use our helper function to find
-	 * the "best" bridge technology, otherwise we can just look for
-	 * the most basic capability needed, single 1to1 mixing.
-	 */
-	self->technology = capabilities
-		? find_best_technology(capabilities)
-		: find_best_technology(AST_BRIDGE_CAPABILITY_1TO1MIX);
+	self->allowed_capabilities = capabilities;
+
+	/* Use our helper function to find the "best" bridge technology. */
+	self->technology = find_best_technology(capabilities, self);
 	if (!self->technology) {
+		ast_debug(1, "Bridge %s: Could not create.  No technology available to support it.\n",
+			self->uniqueid);
 		ao2_ref(self, -1);
 		return NULL;
 	}
@@ -1399,19 +1392,6 @@
 	return bridge;
 }
 
-int ast_bridge_check(uint32_t capabilities)
-{
-	struct ast_bridge_technology *bridge_technology;
-
-	if (!(bridge_technology = find_best_technology(capabilities))) {
-		return 0;
-	}
-
-	ast_module_unref(bridge_technology->mod);
-
-	return 1;
-}
-
 int ast_bridge_destroy(struct ast_bridge *bridge)
 {
 	ast_debug(1, "Bridge %s: telling all channels to leave the party\n", bridge->uniqueid);
@@ -1504,7 +1484,7 @@
  */
 static int smart_bridge_operation(struct ast_bridge *bridge)
 {
-	uint32_t new_capabilities = 0;
+	uint32_t new_capabilities;
 	struct ast_bridge_technology *new_technology;
 	struct ast_bridge_technology *old_technology = bridge->technology;
 	struct ast_bridge_channel *bridge_channel;
@@ -1520,44 +1500,48 @@
 		return 0;
 	}
 
-/* BUGBUG the bridge tech compatible callback should be asking if the specified bridge is compatible with the tech. */
-	/*
-	 * Based on current capabilities determine whether we want to
-	 * change bridge technologies.
-	 */
-	if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
-		if (bridge->num_channels <= 2) {
-			ast_debug(1, "Bridge %s channel count (%u) is within limits for %s technology, not performing smart bridge operation.\n",
-				bridge->uniqueid, bridge->num_channels, bridge->technology->name);
-			return 0;
-		}
+	/* Determine new bridge technology capabilities needed. */
+	if (2 < bridge->num_channels) {
 		new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
-	} else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
-		if (2 < bridge->num_channels) {
-			ast_debug(1, "Bridge %s channel count (%u) is within limits for %s technology, not performing smart bridge operation.\n",
-				bridge->uniqueid, bridge->num_channels, bridge->technology->name);
-			return 0;
-		}
-		new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX;
-	}
-
-	if (!new_capabilities) {
-		ast_debug(1, "Bridge %s has no new capabilities, not performing smart bridge operation.\n",
-			bridge->uniqueid);
-		return 0;
-	}
-
-	/* Attempt to find a new bridge technology to satisfy the capabilities */
-	new_technology = find_best_technology(new_capabilities);
+		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) {
-		if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
-			ast_debug(1, "Bridge %s could not get a new bridge technology, staying with old technology.\n",
+		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 bridge technology available to support it\n",
+		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;
 	}
 
 	ast_copy_string(dummy_bridge.uniqueid, bridge->uniqueid, sizeof(dummy_bridge.uniqueid));
@@ -3298,7 +3282,8 @@
 	}
 	if (2 + num_kick < merge.dest->num_channels + merge.src->num_channels
 		&& !(merge.dest->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)
-		&& !ast_test_flag(&merge.dest->feature_flags, AST_BRIDGE_FLAG_SMART)) {
+		&& (!ast_test_flag(&merge.dest->feature_flags, AST_BRIDGE_FLAG_SMART)
+			|| !(merge.dest->allowed_capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX))) {
 		ast_debug(1, "Can't merge bridge %s into bridge %s, multimix is needed and it cannot be acquired.\n",
 			merge.src->uniqueid, merge.dest->uniqueid);
 		return -1;
@@ -3731,7 +3716,8 @@
 			merge.src->uniqueid);
 	} else if ((2 + 2) < merge.dest->num_channels + merge.src->num_channels
 		&& !(merge.dest->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)
-		&& !ast_test_flag(&merge.dest->feature_flags, AST_BRIDGE_FLAG_SMART)) {
+		&& (!ast_test_flag(&merge.dest->feature_flags, AST_BRIDGE_FLAG_SMART)
+			|| !(merge.dest->allowed_capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX))) {
 		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));
@@ -5167,29 +5153,10 @@
 	return type;
 }
 
-/*! Bridge technology priority preference to string. */
-static const char *tech_preference2str(enum ast_bridge_preference preference)
-{
-	const char *priority;
-
-	priority = "<Unknown>";
-	switch (preference) {
-	case AST_BRIDGE_PREFERENCE_HIGH:
-		priority = "High";
-		break;
-	case AST_BRIDGE_PREFERENCE_MEDIUM:
-		priority = "Medium";
-		break;
-	case AST_BRIDGE_PREFERENCE_LOW:
-		priority = "Low";
-		break;
-	}
-	return priority;
-}
-
 static char *handle_bridge_technology_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-#define FORMAT "%-20s %-20s %-10s %s\n"
+#define FORMAT_HDR "%-20s %-20s %8s %s\n"
+#define FORMAT_ROW "%-20s %-20s %8d %s\n"
 
 	struct ast_bridge_technology *cur;
 
@@ -5204,19 +5171,16 @@
 		return NULL;
 	}
 
-	ast_cli(a->fd, FORMAT, "Name", "Type", "Priority", "Suspended");
+	ast_cli(a->fd, FORMAT_HDR, "Name", "Type", "Priority", "Suspended");
 	AST_RWLIST_RDLOCK(&bridge_technologies);
 	AST_RWLIST_TRAVERSE(&bridge_technologies, cur, entry) {
 		const char *type;
-		const char *priority;
 
 		/* Decode type for display */
 		type = tech_capability2str(cur->capabilities);
 
-		/* Decode priority preference for display */
-		priority = tech_preference2str(cur->preference);
-
-		ast_cli(a->fd, FORMAT, cur->name, type, priority, AST_CLI_YESNO(cur->suspended));
+		ast_cli(a->fd, FORMAT_ROW, cur->name, type, cur->preference,
+			AST_CLI_YESNO(cur->suspended));
 	}
 	AST_RWLIST_UNLOCK(&bridge_technologies);
 	return CLI_SUCCESS;

Modified: team/group/bridge_construction/main/bridging_basic.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/main/bridging_basic.c?view=diff&rev=388109&r1=388108&r2=388109
==============================================================================
--- team/group/bridge_construction/main/bridging_basic.c (original)
+++ team/group/bridge_construction/main/bridging_basic.c Wed May  8 22:33:50 2013
@@ -141,8 +141,8 @@
 
 	bridge = ast_bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
 	bridge = ast_bridge_base_init(bridge,
-		AST_BRIDGE_CAPABILITY_EARLY | AST_BRIDGE_CAPABILITY_NATIVE
-			| AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_MULTIMIX,
+		AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX
+			| AST_BRIDGE_CAPABILITY_MULTIMIX,
 		AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY
 			| AST_BRIDGE_FLAG_SMART);
 	bridge = ast_bridge_register(bridge);




More information about the asterisk-commits mailing list