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);
 }


--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to