[asterisk-commits] mmichelson: branch mmichelson/atxfer_features r392971 - /team/mmichelson/atxf...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jun 26 14:02:41 CDT 2013
Author: mmichelson
Date: Wed Jun 26 14:02:39 2013
New Revision: 392971
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392971
Log:
Add pull method for atxfer bridges.
This way, we can detect if the transfer target or the transferee
has hung up. With this in place, I tested the following scenarios:
1) Transfer target hangs up while ringing
2) Transfer target hangs up during consultation
3) Transferee hangs up during target ringing
I have not tested what happens when a transferee hangs up during
consultation because I'm not 100% sure how I'm going to handle it.
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=392971&r1=392970&r2=392971
==============================================================================
--- team/mmichelson/atxfer_features/main/bridging_basic.c (original)
+++ team/mmichelson/atxfer_features/main/bridging_basic.c Wed Jun 26 14:02:39 2013
@@ -164,6 +164,19 @@
}
return ast_bridge_base_v_table.push(self, bridge_channel, swap);
+}
+
+static void bridge_basic_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
+{
+ struct bridge_basic_personality *personality = self->personality;
+
+ ast_assert(personality != NULL);
+
+ if (personality->v_table->pull) {
+ personality->v_table->pull(self, bridge_channel);
+ }
+
+ ast_bridge_base_v_table.pull(self, bridge_channel);
}
static void bridge_basic_destroy(struct ast_bridge *self)
@@ -638,6 +651,10 @@
case STIMULUS_TRANSFERER_ANSWER:
ast_assert(0);
case STIMULUS_TRANSFEREE_HANGUP:
+ /* We soft hangup the transferer to prevent him from sitting in
+ * a bridge by himself after the transfer fails
+ */
+ ast_softhangup(props->transferer, AST_SOFTHANGUP_EXPLICIT);
return TRANSFER_FAIL;
case STIMULUS_DTMF_ATXFER_COMPLETE:
case STIMULUS_TRANSFERER_HANGUP:
@@ -669,8 +686,7 @@
static int resume_enter(struct attended_transfer_properties *props)
{
- ast_bridge_basic_change_personality_normal(props->transferee_bridge);
- return ast_bridge_destroy(props->target_bridge);
+ return 0;
}
static int threeway_enter(struct attended_transfer_properties *props)
@@ -762,6 +778,10 @@
case STIMULUS_TRANSFERER_ANSWER:
ast_assert(0);
case STIMULUS_TRANSFEREE_HANGUP:
+ /* We soft hangup the transferer to prevent him from sitting in
+ * a bridge by himself after the transfer fails
+ */
+ ast_softhangup(props->transferer, AST_SOFTHANGUP_EXPLICIT);
return TRANSFER_FAIL;
case STIMULUS_TRANSFERER_HANGUP:
case STIMULUS_DTMF_ATXFER_COMPLETE:
@@ -1069,6 +1089,44 @@
return 0;
}
+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;
+
+ if (self->num_channels > 1) {
+ return;
+ }
+
+ if (self->num_channels == 1) {
+ RAII_VAR(struct ast_bridge_channel *, transferer_bridge_channel, NULL, ao2_cleanup);
+
+ ast_channel_lock(props->transferer);
+ transferer_bridge_channel = ast_channel_get_bridge_channel(props->transferer);
+ ast_channel_unlock(props->transferer);
+
+ if (!transferer_bridge_channel) {
+ return;
+ }
+
+ if (AST_LIST_FIRST(&self->channels) != transferer_bridge_channel) {
+ return;
+ }
+ }
+
+ /* Reaching this point means that either
+ * 1) The bridge has no channels in it
+ * 2) The bridge has one channel, and it's the transferer
+ * In either case, it indicates that the non-transferer parties
+ * are no longer in the bridge.
+ */
+ if (self == props->transferee_bridge) {
+ stimulate_attended_transfer(props, STIMULUS_TRANSFEREE_HANGUP);
+ } else {
+ stimulate_attended_transfer(props, STIMULUS_TARGET_HANGUP);
+ }
+}
+
static enum attended_transfer_stimulus wait_for_stimulus(struct attended_transfer_properties *props)
{
RAII_VAR(struct stimulus_list *, list, NULL, ast_free_ptr);
@@ -1338,6 +1396,7 @@
void ast_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);
@@ -1350,6 +1409,11 @@
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);
+ };
}
void ast_bridge_basic_change_personality_atxfer(struct ast_bridge *bridge,
@@ -1388,6 +1452,7 @@
ast_bridge_basic_v_table = ast_bridge_base_v_table;
ast_bridge_basic_v_table.name = "basic";
ast_bridge_basic_v_table.push = bridge_basic_push;
+ ast_bridge_basic_v_table.pull = bridge_basic_pull;
ast_bridge_basic_v_table.destroy = bridge_basic_destroy;
personality_normal_v_table = ast_bridge_base_v_table;
@@ -1397,6 +1462,7 @@
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;
+ personality_atxfer_v_table.pull = bridge_personality_atxfer_pull;
ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, feature_attended_transfer, NULL);
}
More information about the asterisk-commits
mailing list