]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Allow transfer loops without allowing forwarding loops
authorTerry Wilson <twilson@digium.com>
Tue, 26 Apr 2011 21:16:10 +0000 (21:16 +0000)
committerTerry Wilson <twilson@digium.com>
Tue, 26 Apr 2011 21:16:10 +0000 (21:16 +0000)
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.4@315596 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_dial.c
apps/app_queue.c
res/res_features.c

index 3f0c67082a39acb1c9f0205226a5950ceeda36f8..fec1c9b72934f7ad27c423c37359e45c367e9946 100644 (file)
@@ -1453,14 +1453,6 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
        time(&start_time);
        peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &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_channel_datastore_free(datastore);
        if (!peer) {
                if (result) {
                        res = result;
index 7f34d1fc30f1e59a0e94a0ac13ba374349c81025..a2447d43eb2edcf2a24520bf8067b9fc6ca58e54 100644 (file)
@@ -3047,17 +3047,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
        if (need_weight)
                AST_LIST_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_channel_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(qe, outgoing);
index 63aafa57128cffdd3afce36d9663bb96fe3695ab..66106e851df3ab1dbf6e70b7354f698da38678d9 100644 (file)
@@ -2092,6 +2092,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_channel_datastore_free(di_datastore);
+               }
+       }
+       ast_channel_unlock(chan);
+}
+
 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
 {
        /* Copy voice back and forth between the two channels.  Give the peer
@@ -2249,6 +2265,12 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                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 */