[asterisk-commits] mmichelson: branch mmichelson/atxfer_features r392270 - in /team/mmichelson/a...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jun 19 13:36:41 CDT 2013


Author: mmichelson
Date: Wed Jun 19 13:36:39 2013
New Revision: 392270

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392270
Log:
Create DTMF hooks and a hangup hook for a transferer when pushed into an atxfer bridge.

In order to have the necessary data, I made some changes to how personalities are handled.
Personalities are now allocated when personality changes, but a static v_table is used
now.


Modified:
    team/mmichelson/atxfer_features/include/asterisk/bridging_basic.h
    team/mmichelson/atxfer_features/main/bridging_basic.c

Modified: team/mmichelson/atxfer_features/include/asterisk/bridging_basic.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/atxfer_features/include/asterisk/bridging_basic.h?view=diff&rev=392270&r1=392269&r2=392270
==============================================================================
--- team/mmichelson/atxfer_features/include/asterisk/bridging_basic.h (original)
+++ team/mmichelson/atxfer_features/include/asterisk/bridging_basic.h Wed Jun 19 13:36:39 2013
@@ -98,7 +98,14 @@
 /*! Initialize the basic bridge class for use by the system. */
 void ast_bridging_init_basic(void);
 
-void ast_bridge_basic_change_personality_atxfer(struct ast_bridge *bridge);
+/* XXX Everything below this point can likely be made private to bridging_basic.c
+ * If not, then attended_transfer_properties needs an ast_ prefix and the two
+ * functions need doxygen
+ */
+struct attended_transfer_properties;
+
+void ast_bridge_basic_change_personality_atxfer(struct ast_bridge *bridge,
+		struct attended_transfer_properties *props);
 void ast_bridge_basic_change_personality_normal(struct ast_bridge *bridge);
 
 /* ------------------------------------------------------------------- */

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=392270&r1=392269&r2=392270
==============================================================================
--- team/mmichelson/atxfer_features/main/bridging_basic.c (original)
+++ team/mmichelson/atxfer_features/main/bridging_basic.c Wed Jun 19 13:36:39 2013
@@ -46,7 +46,7 @@
 			| AST_BRIDGE_FLAG_SMART
 
 #define TRANSFER_FLAGS AST_BRIDGE_FLAG_SMART
- 
+#define TRANSFERER_ROLE_NAME "transferer" 
 
 /* ------------------------------------------------------------------- */
 
@@ -121,7 +121,8 @@
 
 struct bridge_basic_personality {
 	const char *name;
-	ast_bridge_push_channel_fn push;
+	struct ast_bridge_methods *v_table;
+	void *pvt;
 };
 
 /*!
@@ -150,53 +151,17 @@
 	return 0;
 }
 
-static int bridge_personality_atxfer_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
-{
-	/* XXX STUB */
-
-	/* This push function will check the role of the bridge channel being added
-	 * to determine if it is a transferer. If it is, then the transferer gets
-	 * a special set of DTMF hooks. Isn't he/she special?!
-	 */
-	return 0;
-}
-
 static int bridge_basic_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
 {
 	struct bridge_basic_personality *personality = self->personality;
 
 	ast_assert(personality != NULL);
 
-	if (personality->push(self, bridge_channel, swap)) {
+	if (personality->v_table->push(self, bridge_channel, swap)) {
 		return -1;
 	}
 
 	return ast_bridge_base_v_table.push(self, bridge_channel, swap);
-}
-
-struct ast_bridge_methods ast_bridge_basic_v_table;
-
-static struct bridge_basic_personality bridge_normal_personality = {
-	.name = "normal",
-	.push = bridge_personality_normal_push,
-};
-
-static struct bridge_basic_personality bridge_atxfer_personality = {
-	.name = "atxfer",
-	.push = bridge_personality_atxfer_push,
-};
-
-struct ast_bridge *ast_bridge_basic_new(void)
-{
-	struct ast_bridge *bridge;
-
-	bridge = ast_bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
-	bridge = ast_bridge_base_init(bridge,
-		AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX
-			| AST_BRIDGE_CAPABILITY_MULTIMIX, NORMAL_FLAGS);
-	bridge->personality = &bridge_normal_personality;
-	bridge = ast_bridge_register(bridge);
-	return bridge;
 }
 
 static void remove_hooks_on_personality_change(struct ast_bridge *bridge)
@@ -206,34 +171,6 @@
 	AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
 		SCOPED_LOCK(lock, iter, ast_bridge_channel_lock, ast_bridge_channel_unlock);
 		ast_bridge_features_remove(iter->features, AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE);
-	}
-}
-
-void ast_bridge_basic_change_personality_atxfer(struct ast_bridge *bridge)
-{
-	SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
-
-	ast_assert(bridge->v_table == &ast_bridge_base_v_table);
-
-	if (bridge->personality != &bridge_atxfer_personality) {
-		bridge->personality = &bridge_atxfer_personality;
-		ast_clear_flag(&bridge->feature_flags, AST_FLAGS_ALL);
-		ast_set_flag(&bridge->feature_flags, TRANSFER_FLAGS);
-		remove_hooks_on_personality_change(bridge);
-	}
-}
-
-void ast_bridge_basic_change_personality_normal(struct ast_bridge *bridge)
-{
-	SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
-
-	ast_assert(bridge->v_table == &ast_bridge_base_v_table);
-
-	if (bridge->personality != &bridge_normal_personality) {
-		bridge->personality = &bridge_normal_personality;
-		ast_clear_flag(&bridge->feature_flags, AST_FLAGS_ALL);
-		ast_set_flag(&bridge->feature_flags, NORMAL_FLAGS);
-		remove_hooks_on_personality_change(bridge);
 	}
 }
 
@@ -827,7 +764,7 @@
 	},
 };
 
-static __attribute__((unused)) void stimulate_attended_transfer(struct attended_transfer_properties *props,
+static void stimulate_attended_transfer(struct attended_transfer_properties *props,
 		enum attended_transfer_stimulus stimulus)
 {
 	struct stimulus_list *list;
@@ -843,6 +780,91 @@
 	AST_LIST_INSERT_TAIL(&props->stimulus_queue, list, next);
 	ast_cond_signal(&props->cond);
 	ast_mutex_unlock(&props->lock);
+}
+
+static int atxfer_abort(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
+{
+	struct attended_transfer_properties *props = hook_pvt;
+
+	stimulate_attended_transfer(props, STIMULUS_DTMF_ATXFER_ABORT);
+	return 0;
+}
+
+static int atxfer_complete(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
+{
+	struct attended_transfer_properties *props = hook_pvt;
+
+	stimulate_attended_transfer(props, STIMULUS_DTMF_ATXFER_COMPLETE);
+	return 0;
+}
+
+static int atxfer_threeway(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
+{
+	struct attended_transfer_properties *props = hook_pvt;
+
+	stimulate_attended_transfer(props, STIMULUS_DTMF_ATXFER_THREEWAY);
+	return 0;
+}
+
+static int atxfer_swap(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
+{
+	struct attended_transfer_properties *props = hook_pvt;
+
+	stimulate_attended_transfer(props, STIMULUS_DTMF_ATXFER_SWAP);
+	return 0;
+}
+
+static int atxfer_transferer_hangup(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
+{
+	struct attended_transfer_properties *props = hook_pvt;
+
+	stimulate_attended_transfer(props, STIMULUS_TRANSFERER_HANGUP);
+	return 0;
+}
+
+static int bridge_personality_atxfer_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
+{
+	const char *abort_dtmf;
+	const char *complete_dtmf;
+	const char *threeway_dtmf;
+	const char *swap_dtmf;
+	struct bridge_basic_personality *personality = self->personality;
+
+	if (!ast_channel_has_role(bridge_channel->chan, TRANSFERER_ROLE_NAME)) {
+		return 0;
+	}
+
+	abort_dtmf = ast_channel_get_role_option(bridge_channel->chan, TRANSFERER_ROLE_NAME, "abort");
+	complete_dtmf = ast_channel_get_role_option(bridge_channel->chan, TRANSFERER_ROLE_NAME, "complete");
+	threeway_dtmf = ast_channel_get_role_option(bridge_channel->chan, TRANSFERER_ROLE_NAME, "threeway");
+	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, 
+				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, 
+				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, 
+				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, 
+				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,
+			AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
+		return -1;
+	}
+
+	return 0;
 }
 
 static enum attended_transfer_stimulus wait_for_stimulus(struct attended_transfer_properties *props)
@@ -1338,6 +1360,92 @@
 	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);
+}
+
+static struct bridge_basic_personality *normal_personality_alloc(void)
+{
+	struct bridge_basic_personality *normal;
+
+	normal = ao2_alloc(sizeof(*normal), basic_personality_destructor);
+	if (!normal) {
+		return NULL;
+	}
+	normal->name = personality_normal_v_table.name;
+	normal->v_table = &personality_normal_v_table;
+
+	return normal;
+}
+
+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) {
+		return NULL;
+	}
+	atxfer->name = personality_atxfer_v_table.name;
+	atxfer->v_table = &personality_atxfer_v_table;
+	ao2_ref(props, +1);
+	atxfer->pvt = props;
+
+	return atxfer;
+}
+
+void ast_bridge_basic_change_personality_normal(struct ast_bridge *bridge)
+{
+	struct bridge_basic_personality *personality;
+	SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
+
+	ast_assert(bridge->v_table == &ast_bridge_base_v_table);
+
+	personality = normal_personality_alloc();
+	ao2_cleanup(bridge->personality);
+	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);
+}
+
+void ast_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);
+
+	ast_assert(bridge->v_table == &ast_bridge_base_v_table);
+
+	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);
+}
+
+struct ast_bridge *ast_bridge_basic_new(void)
+{
+	struct ast_bridge *bridge;
+
+	bridge = ast_bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
+	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 = ast_bridge_register(bridge);
+	return bridge;
+}
+
 void ast_bridging_init_basic(void)
 {
 	/* Setup bridge basic subclass v_table. */
@@ -1345,6 +1453,14 @@
 	ast_bridge_basic_v_table.name = "basic";
 	ast_bridge_basic_v_table.push = bridge_basic_push;
 
+	personality_normal_v_table = ast_bridge_base_v_table;
+	personality_normal_v_table.name = "normal";
+	personality_normal_v_table.push = bridge_personality_normal_push;
+	
+	personality_atxfer_v_table = ast_bridge_base_v_table;
+	personality_atxfer_v_table.name = "attended transfer";
+	personality_atxfer_v_table.push = bridge_personality_atxfer_push;
+
 	ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, feature_attended_transfer, NULL);
 }
 




More information about the asterisk-commits mailing list