[svn-commits] mmichelson: branch mmichelson/atxfer_features r394091 - /team/mmichelson/atxf...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Jul 11 11:17:28 CDT 2013


Author: mmichelson
Date: Thu Jul 11 11:17:27 2013
New Revision: 394091

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=394091
Log:
Change the method by which personalities are allocated/changed.

Now personalities are pre-allocated on bridge creation. When changing
personalities, it's a simple matter of changing an index into an array
and setting user data appropriately.

This approach requires much fewer allocations than previously and is
therefore safer.

Basic bridge allocation also was altered to be safer as well.


Modified:
    team/mmichelson/atxfer_features/main/bridging_basic.c

Modified: team/mmichelson/atxfer_features/main/bridging_basic.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/atxfer_features/main/bridging_basic.c?view=diff&rev=394091&r1=394090&r2=394091
==============================================================================
--- team/mmichelson/atxfer_features/main/bridging_basic.c (original)
+++ team/mmichelson/atxfer_features/main/bridging_basic.c Thu Jul 11 11:17:27 2013
@@ -53,9 +53,27 @@
 
 struct attended_transfer_properties;
 
-static void bridge_basic_change_personality_atxfer(struct ast_bridge *bridge,
-		struct attended_transfer_properties *props);
-static void bridge_basic_change_personality_normal(struct ast_bridge *bridge);
+enum bridge_basic_personality_type {
+	/*! Index for "normal" basic bridge personality */
+	BRIDGE_BASIC_PERSONALITY_NORMAL,
+	/*! Index for attended transfer basic bridge personality */
+	BRIDGE_BASIC_PERSONALITY_ATXFER,
+	/*! Indicates end of enum. Must always remain the last element */
+	BRIDGE_BASIC_PERSONALITY_END,
+};
+
+/*!
+ * \brief Change basic bridge personality
+ *
+ * Changing personalities allows for the bridge to remain in use but have
+ * properties such as its v_table and its flags change.
+ *
+ * \param bridge The bridge
+ * \param type The personality to change the bridge to
+ * \user_data Private data to attach to the personality.
+ */
+static void bridge_basic_change_personality(struct ast_bridge *bridge,
+		enum bridge_basic_personality_type type, void *user_data);
 
 /* ------------------------------------------------------------------- */
 
@@ -129,13 +147,25 @@
 }
 
 /*!
- * \brief The basis for basic bridge personalities
- */
-struct bridge_basic_personality {
+ * \brief Details for specific basic bridge personalities
+ */
+struct personality_details {
 	/*! The v_table to use for this personality */
 	struct ast_bridge_methods *v_table;
-	/*! User data for this personality */
+	/*! Flags to set on this type of bridge */
+	unsigned int bridge_flags;
+	/*! User data for this personality. If used, must be an ao2 object */
 	void *pvt;
+};
+
+/*!
+ * \brief structure that organizes different personalities for basic bridges.
+ */
+struct bridge_basic_personality {
+	/*! The current bridge personality in use */
+	enum bridge_basic_personality_type current;
+	/*! Array of details for the types of bridge personalities supported */
+	struct personality_details details[BRIDGE_BASIC_PERSONALITY_END];
 };
 
 /*!
@@ -170,7 +200,7 @@
 
 	ast_assert(personality != NULL);
 
-	if (personality->v_table->push(self, bridge_channel, swap)) {
+	if (personality->details[personality->current].v_table->push(self, bridge_channel, swap)) {
 		return -1;
 	}
 
@@ -183,8 +213,8 @@
 
 	ast_assert(personality != NULL);
 
-	if (personality->v_table->pull) {
-		personality->v_table->pull(self, bridge_channel);
+	if (personality->details[personality->current].v_table->pull) {
+		personality->details[personality->current].v_table->pull(self, bridge_channel);
 	}
 
 	ast_bridge_base_v_table.pull(self, bridge_channel);
@@ -980,7 +1010,8 @@
 
 	if (props->transferee_bridge) {
 		ast_bridge_merge_inhibit(props->transferee_bridge, -1);
-		bridge_basic_change_personality_normal(props->transferee_bridge);
+		bridge_basic_change_personality(props->transferee_bridge,
+				BRIDGE_BASIC_PERSONALITY_NORMAL, NULL);
 	}
 
 	if (props->target_bridge) {
@@ -1535,7 +1566,7 @@
 		 * will change the personality of the transfer target bridge back to normal, and play
 		 * a sound to the transferer to indicate the transferee is gone.
 		 */
-		bridge_basic_change_personality_normal(props->target_bridge);
+		bridge_basic_change_personality(props->target_bridge, BRIDGE_BASIC_PERSONALITY_NORMAL, NULL);
 		play_sound(props->transferer, props->failsound);
 		/* These next two lines are here to ensure that our reference to the target bridge
 		 * is cleaned up properly and that the target bridge is not destroyed when the
@@ -2075,26 +2106,27 @@
 	swap_dtmf = ast_channel_get_role_option(bridge_channel->chan, TRANSFERER_ROLE_NAME, "swap");
 
 	if (!ast_strlen_zero(abort_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
-				abort_dtmf, atxfer_abort, personality->pvt, NULL,
+				abort_dtmf, atxfer_abort, personality->details[personality->current].pvt, NULL,
 				AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
 		return -1;
 	}
 	if (!ast_strlen_zero(complete_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
-				complete_dtmf, atxfer_complete, personality->pvt, NULL,
+				complete_dtmf, atxfer_complete, personality->details[personality->current].pvt, NULL,
 				AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
 		return -1;
 	}
 	if (!ast_strlen_zero(threeway_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
-				threeway_dtmf, atxfer_threeway, personality->pvt, NULL,
+				threeway_dtmf, atxfer_threeway, personality->details[personality->current].pvt, NULL,
 				AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
 		return -1;
 	}
 	if (!ast_strlen_zero(swap_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
-				swap_dtmf, atxfer_swap, personality->pvt, NULL,
+				swap_dtmf, atxfer_swap, personality->details[personality->current].pvt, NULL,
 				AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
 		return -1;
 	}
-	if (ast_bridge_hangup_hook(bridge_channel->features, atxfer_transferer_hangup, personality->pvt, NULL,
+	if (ast_bridge_hangup_hook(bridge_channel->features, atxfer_transferer_hangup,
+				personality->details[personality->current].pvt, NULL,
 			AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
 		return -1;
 	}
@@ -2181,7 +2213,7 @@
 static void bridge_personality_atxfer_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
 {
 	struct bridge_basic_personality *personality = self->personality;
-	struct attended_transfer_properties *props = personality->pvt;
+	struct attended_transfer_properties *props = personality->details[personality->current].pvt;
 
 	switch (props->superstate) {
 	case SUPERSTATE_TRANSFER:
@@ -2509,8 +2541,10 @@
 		return 0;
 	}
 
-	bridge_basic_change_personality_atxfer(props->target_bridge, props);
-	bridge_basic_change_personality_atxfer(bridge, props);
+	bridge_basic_change_personality(props->target_bridge,
+			BRIDGE_BASIC_PERSONALITY_ATXFER, props);
+	bridge_basic_change_personality(bridge,
+			BRIDGE_BASIC_PERSONALITY_ATXFER, props);
 
 	if (ast_call(props->transfer_target, destination, 0)) {
 		ast_log(LOG_ERROR, "Unable to place outbound call to transfer target\n");
@@ -2598,109 +2632,77 @@
 	return 0;
 }
 
-
 struct ast_bridge_methods ast_bridge_basic_v_table;
 struct ast_bridge_methods personality_normal_v_table;
 struct ast_bridge_methods personality_atxfer_v_table;
 
-static void basic_personality_destructor(void *obj)
-{
-	struct bridge_basic_personality *atxfer = obj;
-	ao2_cleanup(atxfer->pvt);
-}
-
-/*!
- * \brief Allocate a normal personlity for a basic bridge
- *
- * The normal personality is the default personality for basic bridges.
- */
-static struct bridge_basic_personality *normal_personality_alloc(void)
-{
-	struct bridge_basic_personality *normal;
-
-	normal = ao2_alloc(sizeof(*normal), basic_personality_destructor);
-	if (!normal) {
+static void bridge_basic_change_personality(struct ast_bridge *bridge,
+		enum bridge_basic_personality_type type, void *user_data)
+{
+	struct bridge_basic_personality *personality = bridge->personality;
+	SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
+
+	ao2_cleanup(personality->details[personality->current].pvt);
+	ast_clear_flag(&bridge->feature_flags, AST_FLAGS_ALL);
+
+	personality->current = type;
+	if (user_data) {
+		ao2_ref(user_data, +1);
+		personality->details[personality->current].pvt = user_data;
+	}
+	ast_set_flag(&bridge->feature_flags, personality->details[personality->current].bridge_flags);
+	remove_hooks_on_personality_change(bridge);
+}
+
+static void personality_destructor(void *obj)
+{
+	struct bridge_basic_personality *personality = obj;
+	int i;
+
+	for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
+		ao2_cleanup(personality->details[i].pvt);
+	}
+}
+
+static void init_details(struct personality_details *details,
+		enum bridge_basic_personality_type type)
+{
+	switch (type) {
+	case BRIDGE_BASIC_PERSONALITY_NORMAL:
+		details->v_table = &personality_normal_v_table;
+		details->bridge_flags = NORMAL_FLAGS;
+		break;
+	case BRIDGE_BASIC_PERSONALITY_ATXFER:
+		details->v_table = &personality_atxfer_v_table;
+		details->bridge_flags = TRANSFER_FLAGS;
+		break;
+	default:
+		ast_log(LOG_WARNING, "Asked to initialize unexpected basic bridge personality type.\n");
+		break;
+	}
+}
+
+static struct ast_bridge *bridge_basic_personality_alloc(struct ast_bridge *bridge)
+{
+	struct bridge_basic_personality *personality;
+	int i;
+
+	if (!bridge) {
 		return NULL;
 	}
-	normal->v_table = &personality_normal_v_table;
-
-	return normal;
-}
-
-/*!
- * \brief Allocate an atxfer personality for a basic bridge
- *
- * The atxfer personality is used when an attended transfer is being performed. The
- * bridge where the transfer was initiated and the bridge where the transfer target is
- * contacted have this personality.
- *
- * The personality stores the properties of the attended transfer locally so that they
- * can be referenced from the v_table methods.
- */
-static struct bridge_basic_personality *atxfer_personality_alloc(struct attended_transfer_properties *props)
-{
-	struct bridge_basic_personality *atxfer;
-
-	atxfer = ao2_alloc(sizeof(*atxfer), basic_personality_destructor);
-	if (!atxfer) {
+
+	personality = ao2_alloc(sizeof(*personality), personality_destructor);
+	if (!personality) {
+		ao2_ref(bridge, -1);
 		return NULL;
 	}
-	atxfer->v_table = &personality_atxfer_v_table;
-	ao2_ref(props, +1);
-	atxfer->pvt = props;
-
-	return atxfer;
-}
-
-/*!
- * \brief Change a basic bridge's personality to normal
- *
- * Changing to normal means that a transfer operation has completed and the
- * bridge can change back to its normal self. This operation will clean up
- * the previous personality the bridge had and add back any hooks or features
- * that should be present on the bridge channels.
- */
-static void bridge_basic_change_personality_normal(struct ast_bridge *bridge)
-{
-	struct ast_bridge_channel *bridge_channel;
-	struct bridge_basic_personality *personality;
-	SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
-
-	personality = normal_personality_alloc();
-	ao2_cleanup(bridge->personality);
+	for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
+		init_details(&personality->details[i], i);
+	}
+	personality->current = BRIDGE_BASIC_PERSONALITY_NORMAL;
 	bridge->personality = personality;
 
-	ast_clear_flag(&bridge->feature_flags, AST_FLAGS_ALL);
-	ast_set_flag(&bridge->feature_flags, NORMAL_FLAGS);
-	remove_hooks_on_personality_change(bridge);
-
-	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
-		ast_bridge_hangup_hook(bridge_channel->features, basic_hangup_hook, NULL, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL);
-		ast_bridge_channel_setup_features(bridge_channel);
-	};
-}
-
-/*!
- * \brief Change a basic bridge's personality to atxfer
- *
- * Changing to atxfer means that a transfer is in progress on the bridge.
- * When changing to the atxfer bridge, the properties of the attended transfer
- * are needed so that v_table methods for the atxfer personality can access
- * the data they need.
- */
-static void bridge_basic_change_personality_atxfer(struct ast_bridge *bridge,
-		struct attended_transfer_properties *props)
-{
-	struct bridge_basic_personality *personality;
-	SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
-
-	personality = atxfer_personality_alloc(props);
-	ao2_cleanup(bridge->personality);
-	bridge->personality = personality;
-
-	ast_clear_flag(&bridge->feature_flags, AST_FLAGS_ALL);
-	ast_set_flag(&bridge->feature_flags, TRANSFER_FLAGS);
-	remove_hooks_on_personality_change(bridge);
+	return bridge;
 }
 
 struct ast_bridge *ast_bridge_basic_new(void)
@@ -2711,7 +2713,7 @@
 	bridge = ast_bridge_base_init(bridge,
 		AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX
 			| AST_BRIDGE_CAPABILITY_MULTIMIX, NORMAL_FLAGS);
-	bridge->personality = normal_personality_alloc();
+	bridge = bridge_basic_personality_alloc(bridge);
 	bridge = ast_bridge_register(bridge);
 	return bridge;
 }




More information about the svn-commits mailing list