]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 166665 via svnmerge from
authorSteve Murphy <murf@digium.com>
Wed, 24 Dec 2008 00:52:12 +0000 (00:52 +0000)
committerSteve Murphy <murf@digium.com>
Wed, 24 Dec 2008 00:52:12 +0000 (00:52 +0000)
https://origsvn.digium.com/svn/asterisk/trunk

Due to non-symmetrical updating, I had some fairly
interesting conflicts to straighten out in this
release. The changes were such that I was compelled
to run thru all the same tests as trunk, which turned
up some problems, which I fixed.

................
  r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines

  Merged revisions 166093 via svnmerge from
  https://origsvn.digium.com/svn/asterisk/branches/1.4

  In order to merge this 1.4 patch into trunk,
  I had to resolve some conflicts and wait for
  Russell to make some changes to res_agi.
  I re-ran all the tests; 39 calls in all, and
  made fairly careful notes and comparisons: I
  don't want this to blow up some aspect of
  asterisk; I completely removed the KEEPALIVE
  from the pbx.h decls. The first 3 scenarios
  involving feature park; feature xfer to 700;
  hookflash park to Park() app call all behave
  the same, don't appear to leave hung channels,
  and no crashes.

  ........
    r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines

    This merges the masqpark branch into 1.4

    These changes eliminate the need for (and use of)
    the KEEPALIVE return code in res_features.c;
    There are other places that use this result code
    for similar purposes at a higher level, these appear
    to be left alone in 1.4, but attacked in trunk.

    The reason these changes are being made in 1.4, is
    that parking ends a channel's life, in some situations,
    and the code in the bridge (and some other places),
    was not checking the result code properly, and dereferencing
    the channel pointer, which could lead to memory corruption
    and crashes.

    Calling the masq_park function eliminates this danger
    in higher levels.

    A series of previous commits have replaced some parking calls
    with masq_park, but this patch puts them ALL to rest,
    (except one, purposely left alone because a masquerade
    is done anyway), and gets rid of the code that tests
    the KEEPALIVE result, and the NOHANGUP_PEER result codes.

    While bug 13820 inspired this work, this patch does
    not solve all the problems mentioned there.

    I have tested this patch (again) to make sure I have
    not introduced regressions.

    Crashes that occurred when a parked party hung up
    while the parking party was listening to the numbers
    of the parking stall being assigned, is eliminated.

    These are the cases where parking code may be activated:

    1. Feature one touch (eg. *3)
    2. Feature blind xfer to parking lot (eg ##700)
    3. Run Park() app from dialplan (eg sip xfer to 700)
       (eg. dahdi hookflash xfer to 700)
    4. Run Park via manager.

    The interesting testing cases for parking are:
    I. A calls B, A parks B
        a. B hangs up while A is getting the numbers announced.
        b. B hangs up after A gets the announcement, but
           before the parking time expires
        c. B waits, time expires, A is redialed,
           A answers, B and A are connected, after
           which, B hangs up.
        d. C picks up B while still in parking lot.

    II. A calls B, B parks A
        a. A hangs up while B is getting the numbers announced.
        b. A hangs up after B gets the announcement, but
           before the parking time expires
        c. A waits, time expires, B is redialed,
           B answers, A and B are connected, after
           which, A hangs up.
        d. C picks up A while still in parking lot.

    Testing this throroughly involves acting all the permutations
    of I and II, in situations 1,2,3, and 4.

    Since I added a few more changes (ALL references to KEEPALIVE in the bridge
    code eliimated (I missed one earlier), I retested
    most of the above cases, and no crashes.

    H-extension weirdness.

    Current h-extension execution is not completely
    correct for several of the cases.

    For the case where A calls B, and A parks B, the
    'h' exten is run on A's channel as soon as the park
    is accomplished. This is expected behavior.

    But when A calls B, and B parks A, this will be
    current behavior:

    After B parks A, B is hung up by the system, and
    the 'h' (hangup) exten gets run, but the channel
    mentioned will be a derivative of A's...

    Thus, if A is DAHDI/1, and B is DAHDI/2,
    the h-extension will be run on channel
    Parked/DAHDI/1-1<ZOMBIE>, and the
    start/answer/end info will be those
    relating to Channel A.

    And, in the case where A is reconnected to
    B after the park time expires, when both parties
    hang up after the joyful reunion, no h-exten
    will be run at all.

    In the case where C picks up A from the
    parking lot, when either A or C hang up,
    the h-exten will be run for the C channel.

    CDR's are a separate issue, and not addressed
    here.

    As to WHY this strange behavior occurs,
    the answer lies in the procedure followed
    to accomplish handing over the channel
    to the parking manager thread. This procedure
    is called masquerading. In the process,
    a duplicate copy of the channel is created,
    and most of the active data is given to the
    new copy. The original channel gets its name
    changed to XXX<ZOMBIE> and keeps the PBX
    information for the sake of the original
    thread (preserving its role as a call
    originator, if it had this role to begin
    with), while the new channel is without
    this info and becomes a call target (a
    "peer").

    In this case, the parking lot manager
    thread is handed the new (masqueraded)
    channel. It will not run an h-exten
    on the channel if it hangs up while
    in the parking lot. The h exten will
    be run on the original channel instead,
    in the original thread, after the bridge
    completes.

    See bug 13820 for our intentions as
    to how to clean up the h exten behavior.

  Review: http://reviewboard.digium.com/r/29/

  ........
................

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

apps/app_dial.c
apps/app_macro.c
apps/app_queue.c
include/asterisk/features.h
include/asterisk/pbx.h
main/features.c
main/pbx.c

index fd815b644bfb6fad1bf59e1c3b950aeea053d142..d676fb5f51e95e6b155c25065ebfb6c2ecb2652e 100644 (file)
@@ -1966,11 +1966,6 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                        res = ast_bridge_call(chan, peer, &config);
                }
 
-               if (ast_test_flag64(&opts, OPT_PEER_H)) {
-                       ast_log(LOG_NOTICE, "PEER context: %s; PEER exten: %s;  PEER priority: %d\n",
-                               peer->context, peer->exten, peer->priority);
-               }
-
                strcpy(peer->context, chan->context);
 
                if (ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
@@ -1991,11 +1986,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                        }
                        ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP);  /* set it back the way it was */
                }
-               if (res != AST_PBX_NO_HANGUP_PEER) {
-                       if (!ast_check_hangup(chan))
-                               chan->hangupcause = peer->hangupcause;
-                       ast_hangup(peer);
-               }
+               if (!ast_check_hangup(chan))
+                       chan->hangupcause = peer->hangupcause;
+               ast_hangup(peer);
        }
 out:
        if (moh) {
@@ -2010,13 +2003,12 @@ out:
        pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
        senddialendevent(chan, pa.status);
        ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
-
-       if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_KEEPALIVE)) {
-               if (calldurationlimit)
-                       chan->whentohangup = 0;
-               res = 0;
-       }
-
+       
+        if (ast_test_flag64(peerflags, OPT_GO_ON) && !ast_check_hangup(chan)) {
+                if (calldurationlimit)
+                        chan->whentohangup = 0;
+                res = 0;
+        }
 done:
        return res;
 }
index 6b41c9f260f319a78936ec838dbf934d78dc6cf8..db24d263ac3257ac171075d3436886df35e15667 100644 (file)
@@ -342,10 +342,6 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
                        case MACRO_EXIT_RESULT:
                                res = 0;
                                goto out;
-                       case AST_PBX_KEEPALIVE:
-                               ast_debug(2, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
-                               ast_verb(2, "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
-                               goto out;
                        default:
                                ast_debug(2, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
                                ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
index a20b3d285d0f0982e6ebb3bb656c9a5fd0c2257b..8870cff1e1c96266f932caeabe3bd17fe4927691 100644 (file)
@@ -3886,8 +3886,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                if (transfer_ds) {
                        ast_channel_datastore_free(transfer_ds);
                }
-               if (bridge != AST_PBX_NO_HANGUP_PEER)
-                       ast_hangup(peer);
+               ast_hangup(peer);
                res = bridge ? bridge : 1;
                ao2_ref(member, -1);
        }
@@ -4865,7 +4864,7 @@ stop:
        }
 
        /* Don't allow return code > 0 */
-       if (res >= 0 && res != AST_PBX_KEEPALIVE) {
+       if (res >= 0) {
                res = 0;        
                if (ringing) {
                        ast_indicate(chan, -1);
index 6e2ae1eaba499f91442790db2874d5cb91f135fb..d49e2575b1f08e8b2cabb2edcc9e9f7c1fa24e37 100644 (file)
@@ -47,7 +47,6 @@ struct ast_call_feature {
 };
 
 
-
 /*!
  * \brief Park a call and read back parked location 
  * \param chan the channel to actually be parked
index 37e6f42e51060acd4f4100135bec4c37fefe8d65..50ba87b2ffe1ec6a9162990621abb53882af4b6d 100644 (file)
@@ -40,8 +40,6 @@ extern "C" {
 #define AST_PBX_HANGUP         -1      /*!< Jump to the 'h' exten */
 #define AST_PBX_OK             0       /*!< No errors */
 #define AST_PBX_ERROR          1       /*!< Jump to the 'e' exten */
-#define AST_PBX_KEEPALIVE      10      /*!< Destroy the thread, but don't hang up the channel */
-#define AST_PBX_NO_HANGUP_PEER 11
 /*! } */
 
 #define PRIORITY_HINT  -1      /*!< Special Priority for a hint */
index 5dbfc9bd8f57d22a0f51bfa9c3c528fdd31fe421..4a1244c8ae907efefc2e981a144ac74b503d6c95 100644 (file)
@@ -495,6 +495,10 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
        con = ast_context_find_or_create(NULL, NULL, parking_con, registrar);
        if (!con)       /* Still no context? Bad */
                ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
+       if (con) {
+               if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
+                       notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
+       }
        /* Tell the peer channel the number of the parking space */
        if (peer && (ast_strlen_zero(orig_chan_name) || !strcasecmp(peer->name, orig_chan_name))) { /* Only say number if it's a number and the channel hasn't been masqueraded away */
                /* If a channel is masqueraded into peer while playing back the parking slot number do not continue playing it back. This is the case if an attended transfer occurs. */
@@ -502,10 +506,6 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
                ast_say_digits(peer, pu->parkingnum, "", peer->language);
                ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
        }
-       if (con) {
-               if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
-                       notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
-       }
        if (pu->notquiteyet) {
                /* Wake up parking thread if we're really done */
                ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
@@ -523,8 +523,7 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
        return park_call_full(chan, peer, timeout, extout, NULL);
 }
 
-/* Park call via masquraded channel */
-int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
+static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement)
 {
        struct ast_channel *chan;
        struct ast_frame *f;
@@ -549,10 +548,11 @@ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int
        if ((f = ast_read(chan)))
                ast_frfree(f);
 
-       orig_chan_name = ast_strdupa(chan->name);
+       if (!play_announcement) {
+               orig_chan_name = ast_strdupa(chan->name);
+       }
 
        park_status = park_call_full(chan, peer, timeout, extout, orig_chan_name);
-
        if (park_status == 1) {
        /* would be nice to play "invalid parking extension" */
                ast_hangup(chan);
@@ -561,6 +561,16 @@ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int
        return 0;
 }
 
+/* Park call via masquraded channel */
+int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
+{
+       return masq_park_call(rchan, peer, timeout, extout, 0);
+}
+
+static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
+{
+       return masq_park_call(rchan, peer, timeout, extout, 1);
+}
 
 #define FEATURE_RETURN_HANGUP          -1
 #define FEATURE_RETURN_SUCCESSBREAK     0
@@ -611,25 +621,24 @@ static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer,
        int res = 0;
 
        set_peers(&parker, &parkee, peer, chan, sense);
-       /* Setup the exten/priority to be s/1 since we don't know
-          where this call should return */
-       strcpy(chan->exten, "s");
-       chan->priority = 1;
+       /* we used to set chan's exten and priority to "s" and 1
+          here, but this generates (in some cases) an invalid
+          extension, and if "s" exists, could errantly
+          cause execution of extensions you don't expect. It
+          makes more sense to let nature take its course
+          when chan finishes, and let the pbx do its thing
+          and hang up when the park is over.
+       */
        if (chan->_state != AST_STATE_UP)
                res = ast_answer(chan);
        if (!res)
                res = ast_safe_sleep(chan, 1000);
-       if (!res)
-               res = ast_park_call(parkee, parker, 0, NULL);
 
-       if (!res) {
-               if (sense == FEATURE_SENSE_CHAN)
-                       res = AST_PBX_NO_HANGUP_PEER;
-               else
-                       res = AST_PBX_KEEPALIVE;
+       if (!res) { /* one direction used to call park_call.... */
+               masq_park_call_announce(parkee, parker, 0, NULL);
+               res = 0; /* PBX should hangup zombie channel */
        }
        return res;
-
 }
 
 /*!
@@ -927,12 +936,12 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
                res = finishup(transferee);
                if (res)
                        res = -1;
-               else if (!ast_park_call(transferee, transferer, 0, NULL)) {     /* success */
+               else if (!masq_park_call_announce(transferee, transferer, 0, NULL)) {   /* success */
                        /* We return non-zero, but tell the PBX not to hang the channel when
                           the thread dies -- We have to be careful now though.  We are responsible for 
                           hanging up the channel, else it will never be hung up! */
 
-                       return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
+                       return 0;
                } else {
                        ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
                }
@@ -1468,7 +1477,6 @@ struct ast_call_feature *ast_find_call_feature(const char *name)
  * \param chan,peer,config,code,sense,data
  *
  * Find a feature, determine which channel activated
- * \retval FEATURE_RETURN_PBX_KEEPALIVE,FEATURE_RETURN_NO_HANGUP_PEER
  * \retval -1 error.
  * \retval -2 when an application cannot be found.
 */
@@ -1523,18 +1531,9 @@ static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer,
 
        ast_autoservice_stop(idle);
 
-       if (res == AST_PBX_KEEPALIVE) {
-               /* do not hangup peer if feature is to be activated on it */
-               if ((ast_test_flag(feature, AST_FEATURE_FLAG_ONPEER) && sense == FEATURE_SENSE_CHAN) || (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF) && sense == FEATURE_SENSE_PEER))
-                       return FEATURE_RETURN_NO_HANGUP_PEER;
-               else
-                       return FEATURE_RETURN_PBX_KEEPALIVE;
-       }
-       else if (res == AST_PBX_NO_HANGUP_PEER)
-               return FEATURE_RETURN_NO_HANGUP_PEER;
-       else if (res)
+       if (res) {
                return FEATURE_RETURN_SUCCESSBREAK;
-       
+       }
        return FEATURE_RETURN_SUCCESS;  /*! \todo XXX should probably return res */
 }
 
@@ -2189,16 +2188,13 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
 
        }
    before_you_go:
-       new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
-       new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
-
-       if (res != AST_PBX_KEEPALIVE && config->end_bridge_callback) {
+       if (config->end_bridge_callback) {
                config->end_bridge_callback(config->end_bridge_callback_data);
        }
 
        autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
        ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
-       if (res != AST_PBX_KEEPALIVE && !ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
+       if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
                struct ast_cdr *swapper = NULL;
                char savelastapp[AST_MAX_EXTENSION];
                char savelastdata[AST_MAX_EXTENSION];
@@ -2248,39 +2244,43 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
        }
        ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
 
-       /* obey the NoCDR() wishes. */
-       if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED))
-               ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
-       if (!new_chan_cdr || (new_chan_cdr && !ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
-               struct ast_channel *chan_ptr = NULL;
-               
-               if (bridge_cdr) {
-                       ast_cdr_end(bridge_cdr);
-                       ast_cdr_detach(bridge_cdr);
-               }
-               /* do a specialized reset on the beginning channel
-                  CDR's, if they still exist, so as not to mess up
-                  issues in future bridges;
-  
-                  Here are the rules of the game:
-                  1. The chan and peer channel pointers will not change
-                     during the life of the bridge.
-                  2. But, in transfers, the channel names will change.
-                     between the time the bridge is started, and the
-                     time the channel ends. 
-                     Usually, when a channel changes names, it will
-                     also change CDR pointers.
-                  3. Usually, only one of the two channels (chan or peer)
-                     will change names.
-                  4. Usually, if a channel changes names during a bridge,
-                     it is because of a transfer. Usually, in these situations,
-                     it is normal to see 2 bridges running simultaneously, and
-                     it is not unusual to see the two channels that change
-                     swapped between bridges.
-                  5. After a bridge occurs, we have 2 or 3 channels' CDRs
-                     to attend to; if the chan or peer changed names,
-                     we have the before and after attached CDR's.
-               */
+       /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
+       new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
+       if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))
+               ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
+
+       /* we can post the bridge CDR at this point */
+       if (bridge_cdr) {
+               ast_cdr_end(bridge_cdr);
+               ast_cdr_detach(bridge_cdr);
+       }
+       
+       /* do a specialized reset on the beginning channel
+          CDR's, if they still exist, so as not to mess up
+          issues in future bridges;
+          
+          Here are the rules of the game:
+          1. The chan and peer channel pointers will not change
+             during the life of the bridge.
+          2. But, in transfers, the channel names will change.
+             between the time the bridge is started, and the
+             time the channel ends. 
+             Usually, when a channel changes names, it will
+             also change CDR pointers.
+          3. Usually, only one of the two channels (chan or peer)
+             will change names.
+          4. Usually, if a channel changes names during a bridge,
+             it is because of a transfer. Usually, in these situations,
+             it is normal to see 2 bridges running simultaneously, and
+             it is not unusual to see the two channels that change
+             swapped between bridges.
+          5. After a bridge occurs, we have 2 or 3 channels' CDRs
+             to attend to; if the chan or peer changed names,
+             we have the before and after attached CDR's.
+       */
+       
+       if (new_chan_cdr) {
+               struct ast_channel *chan_ptr = NULL;
  
                if (strcasecmp(orig_channame, chan->name) != 0) { 
                        /* old channel */
@@ -2303,13 +2303,20 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                } else {
                        ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr  */
                }
-               if (strcasecmp(orig_peername, peer->name) != 0) { 
-                       /* old channel */
-                       chan_ptr = ast_get_channel_by_name_locked(orig_peername);
-                       if (chan_ptr) {
-                               if (!ast_bridged_channel(chan_ptr)) {
-                                       struct ast_cdr *cur;
-                                       for (cur = chan_ptr->cdr; cur; cur = cur->next) {
+       }
+       
+       {
+               struct ast_channel *chan_ptr = NULL;
+               new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
+               if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED))
+                       ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
+               if (strcasecmp(orig_peername, peer->name) != 0) { 
+                       /* old channel */
+                       chan_ptr = ast_get_channel_by_name_locked(orig_peername);
+                       if (chan_ptr) {
+                               if (!ast_bridged_channel(chan_ptr)) {
+                                       struct ast_cdr *cur;
+                                       for (cur = chan_ptr->cdr; cur; cur = cur->next) {
                                                if (cur == peer_cdr) {
                                                        break;
                                                }
@@ -2560,8 +2567,9 @@ static int park_call_exec(struct ast_channel *chan, void *data)
                        ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
                        chan->priority = orig_priority;
                        res = 0;
-               } else if (!res)
-                       res = AST_PBX_KEEPALIVE;
+               } else if (!res) {
+                       res = 1;
+               }
        }
 
        return res;
@@ -2674,8 +2682,7 @@ static int park_exec(struct ast_channel *chan, void *data)
                ast_cdr_setdestchan(chan->cdr, peer->name);
 
                /* Simulate the PBX hanging up */
-               if (res != AST_PBX_NO_HANGUP_PEER)
-                       ast_hangup(peer);
+               ast_hangup(peer);
                return res;
        } else {
                /*! \todo XXX Play a message XXX */
index 62158dfe518052ea41141c8ae7af6ceccb1be8ad..6edd6795d0ebf8cd675de0dde0a08bb97894102d 100644 (file)
@@ -3708,10 +3708,6 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
                                pos = 0;
                                dst_exten[pos++] = digit = res;
                                dst_exten[pos] = '\0';
-                       } else if (res == AST_PBX_KEEPALIVE) {
-                               ast_debug(1, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
-                               ast_verb(2, "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
-                               error = 1;
                        } else {
                                ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
                                ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);