[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