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
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;
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);
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
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 */