]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 315596 via svnmerge from
authorTerry Wilson <twilson@digium.com>
Tue, 26 Apr 2011 21:27:44 +0000 (21:27 +0000)
committerTerry Wilson <twilson@digium.com>
Tue, 26 Apr 2011 21:27:44 +0000 (21:27 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
  r315596 | twilson | 2011-04-26 14:16:10 -0700 (Tue, 26 Apr 2011) | 18 lines

  Allow transfer loops without allowing forwarding loops

  We try to avoid the situation where two phones may be forwarded to each other
  causing an infinite loop by storing each dialed interface in a channel
  datastore and checking the list before dialing out. This works, but currently
  breaks situations like A calls B, A transfers B to C, B transfers C to A, and A
  transfers C to B. Since human interaction is happening here and not an
  automated forwarding loop, it should be allowed.

  This patch removes the dialed_interfaces datastore when a call is bridged (a
  suggestion from the brilliant mmichelson). If a call is being bridged, it
  should be safe to assume that we aren't stuck in a loop.

  Since we are now handling this is the bridge code, the previous attempts at
  handling it in app_dial and app_queue are removed.

  Review: https://reviewboard.asterisk.org/r/1195/
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.2@315643 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_dial.c
apps/app_queue.c
main/features.c

index 4ab419011f0d08ca0e8ea6dfab07831cca55ee34..0db0b79e526847b6f4587e9e30bf1e2cd9c07018 100644 (file)
@@ -1912,14 +1912,6 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
 
        peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result);
 
-       /* The ast_channel_datastore_remove() function could fail here if the
-        * datastore was moved to another channel during a masquerade. If this is
-        * the case, don't free the datastore here because later, when the channel
-        * to which the datastore was moved hangs up, it will attempt to free this
-        * datastore again, causing a crash
-        */
-       if (!ast_channel_datastore_remove(chan, datastore))
-               ast_datastore_free(datastore);
        if (!peer) {
                if (result) {
                        res = result;
index a7f55ac734b824b902d02e23c2e743e4609a9f77..14ba09e564c7844d67fdf1afe4e03f425af89411 100644 (file)
@@ -3843,17 +3843,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
        if (need_weight)
                ao2_unlock(queues);
        lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
-       /* The ast_channel_datastore_remove() function could fail here if the
-        * datastore was moved to another channel during a masquerade. If this is
-        * the case, don't free the datastore here because later, when the channel
-        * to which the datastore was moved hangs up, it will attempt to free this
-        * datastore again, causing a crash
-        */
-       ast_channel_lock(qe->chan);
-       if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) {
-               ast_datastore_free(datastore);
-       }
-       ast_channel_unlock(qe->chan);
        ao2_lock(qe->parent);
        if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
                store_next_rr(qe, outgoing);
index ce24cfdcac94d824cf915b410c06b394348feef4..d6ee9b1a2e5b230abaa11b6708fe310b4ec2c818 100644 (file)
@@ -2832,6 +2832,22 @@ static void add_features_datastores(struct ast_channel *caller, struct ast_chann
        return;
 }
 
+static void clear_dialed_interfaces(struct ast_channel *chan)
+{
+       struct ast_datastore *di_datastore;
+
+       ast_channel_lock(chan);
+       if ((di_datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL))) {
+               if (option_debug) {
+                       ast_log(LOG_DEBUG, "Removing dialed interfaces datastore on %s since we're bridging\n", chan->name);
+               }
+               if (!ast_channel_datastore_remove(chan, di_datastore)) {
+                       ast_datastore_free(di_datastore);
+               }
+       }
+       ast_channel_unlock(chan);
+}
+
 /*!
  * \brief bridge the call and set CDR
  * \param chan,peer,config
@@ -3001,6 +3017,13 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                 * present. */
                ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED);
        }
+
+       /* If we are bridging a call, stop worrying about forwarding loops. We presume that if
+        * a call is being bridged, that the humans in charge know what they're doing. If they
+        * don't, well, what can we do about that? */
+       clear_dialed_interfaces(chan);
+       clear_dialed_interfaces(peer);
+
        for (;;) {
                struct ast_channel *other;      /* used later */