accountcode: Slightly change accountcode propagation.
authorRichard Mudgett <rmudgett@digium.com>
Thu, 24 Jul 2014 22:48:38 +0000 (22:48 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Thu, 24 Jul 2014 22:48:38 +0000 (22:48 +0000)
The previous behavior was to simply set the accountcode of an outgoing
channel to the accountcode of the channel initiating the call.  It was
done this way a long time ago to allow the accountcode set on the SIP/100
channel to be propagated to a local channel so the dialplan execution on
the Local;2 channel would have the SIP/100 accountcode available.

SIP/100 -> Local;1/Local;2 -> SIP/200

Propagating the SIP/100 accountcode to the local channels is very useful.
Without any dialplan manipulation, all channels in this call would have
the same accountcode.

Using dialplan, you can set a different accountcode on the SIP/200 channel
either by setting the accountcode on the Local;2 channel or by the Dial
application's b(pre-dial), M(macro) or U(gosub) options, or by the
FollowMe application's b(pre-dial) option, or by the Queue application's
macro or gosub options.  Before Asterisk v12, the altered accountcode on
SIP/200 will remain until the local channels optimize out and the
accountcode would change to the SIP/100 accountcode.

Asterisk v1.8 attempted to add peeraccount support but ultimately had to
punt on the support.  The peeraccount support was rendered useless because
of how the CDR code needed to unconditionally force the caller's
accountcode onto the peer channel's accountcode.  The CEL events were thus
intentionally made to always use the channel's accountcode as the
peeraccount value.

With the arrival of Asterisk v12, the situation has improved somewhat so
peeraccount support can be made to work.  Using the indicated example, the
the accountcode values become as follows when the peeraccount is set on
SIP/100 before calling SIP/200:

SIP/100 ---> Local;1 ---- Local;2 ---> SIP/200
acct: 100 \/ acct: 200 \/ acct: 100 \/ acct: 200
peer: 200 /\ peer: 100 /\ peer: 200 /\ peer: 100

If a channel already has an accountcode it can only change by the
following explicit user actions:

1) A channel originate method that can specify an accountcode to use.

2) The calling channel propagating its non-empty peeraccount or its
non-empty accountcode if the peeraccount was empty to the outgoing
channel's accountcode before initiating the dial.  e.g., Dial and
FollowMe.  The exception to this propagation method is Queue.  Queue will
only propagate peeraccounts this way only if the outgoing channel does not
have an accountcode.

3) Dialplan using CHANNEL(accountcode).

4) Dialplan using CHANNEL(peeraccount) on the other end of a local
channel pair.

If a channel does not have an accountcode it can get one from the
following places:

1) The channel driver's configuration at channel creation.

2) Explicit user action as already indicated.

3) Entering a basic or stasis-mixing bridge from a peer channel's
peeraccount value.

You can specify the accountcode for an outgoing channel by setting the
CHANNEL(peeraccount) before using the Dial, FollowMe, and Queue
applications.  Queue adds the wrinkle that it will not overwrite an
existing accountcode on the outgoing channel with the calling channels
values.

Accountcode and peeraccount values propagate to an outgoing channel before
dialing.  Accountcodes also propagate when channels enter or leave a basic
or stasis-mixing bridge.  The peeraccount value only makes sense for
mixing bridges with two channels; it is meaningless otherwise.

* Made peeraccount functional by changing accountcode propagation as
described above.

* Fixed CEL extracting the wrong ie value for the peeraccount.  This was
done intentionally in Asterisk v1.8 when that version had to punt on
peeraccount.

* Fixed a few places dealing with accountcodes that were reading from
channels without the lock held.

AFS-65 #close

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

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

14 files changed:
CHANGES
UPGRADE.txt
apps/app_dial.c
apps/app_followme.c
apps/app_queue.c
include/asterisk/channel.h
main/bridge.c
main/bridge_basic.c
main/cel.c
main/channel.c
main/core_unreal.c
main/dial.c
main/pbx.c
res/parking/parking_bridge_features.c

diff --git a/CHANGES b/CHANGES
index 788a114..8770147 100644 (file)
--- a/CHANGES
+++ b/CHANGES
 --- Functionality changes from Asterisk 12 to Asterisk 13 --------------------
 ------------------------------------------------------------------------------
 
+accountcode
+------------------
+ - Added functional peeraccount support.  Except for Queue, the
+   accountcode propagation is now consistently propagated to outgoing
+   channels before dialing.  The channel accountcode can change from its
+   original non-empty value on channel creation for the following specific
+   reasons.  One, dialplan sets it using CHANNEL(accountcode).  Two, an
+   originate method that can specify an accountcode value.  Three, the
+   calling channel propagates its peeraccount or accountcode to the
+   outgoing channel's accountcode before dialing.  The change has two
+   visible effects.  One, local channels now cross accountcode and
+   peeraccount across the special bridge between the ;1 and ;2 channels
+   just like channels between normal bridges.  Two, the
+   CHANNEL(peeraccount) value can now be set before Dial and FollowMe to
+   set the accountcode on the outgoing channel(s).
+
+   For Queue, an outgoing channel's non-empty accountcode will not change
+   unless explicitly set by CHANNEL(accountcode).  The change has three
+   visible effects.  One, local channels now cross accountcode and
+   peeraccount across the special bridge between the ;1 and ;2 channels
+   just like channels between normal bridges.  Two, the queue member will
+   get an accountcode if it doesn't have one and one is available from the
+   calling channel's peeraccount.  Three, accountcode propagation includes
+   local channel members where the accountcodes are propagated early
+   enough to be available on the ;2 channel.
+
 app_dahdibarge
 ------------------
  * This module was deprecated and has been removed. Users of app_dahdibarge
index 535782a..37160c4 100644 (file)
@@ -57,6 +57,13 @@ From 12 to 13:
    update their dialplans to use ',' instead of '|' as a delimiter, and should
    use the Set dialplan application instead of the MSet dialplan application.
 
+accountcode:
+ - Accountcode behavior changed somewhat to add functional peeraccount
+   support.  The main change is that local channels now cross accountcode
+   and peeraccount across the special bridge between the ;1 and ;2 channels
+   just like channels between normal bridges.  See the CHANGES file for
+   more information.
+
 ARI:
  - The ARI version has been changed from 1.0.0 to 1.1.0. This is to reflect
    the backwards compatible changes listed below.
index df9b72a..b48a226 100644 (file)
@@ -956,7 +956,7 @@ static void do_forward(struct chanlist *o, struct cause_args *num,
                        ast_connected_line_copy_from_caller(ast_channel_connected(c), ast_channel_caller(in));
                }
 
-               ast_channel_accountcode_set(c, ast_channel_accountcode(in));
+               ast_channel_req_accountcodes(c, in, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
 
                ast_channel_appl_set(c, "AppDial");
                ast_channel_data_set(c, "(Outgoing Line)");
@@ -2524,9 +2524,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
 
                ast_channel_dialed(tc)->transit_network_select = ast_channel_dialed(chan)->transit_network_select;
 
-               if (!ast_strlen_zero(ast_channel_accountcode(chan))) {
-                       ast_channel_accountcode_set(tc, ast_channel_accountcode(chan));
-               }
+               ast_channel_req_accountcodes(tc, chan, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
                if (ast_strlen_zero(ast_channel_musicclass(tc))) {
                        ast_channel_musicclass_set(tc, ast_channel_musicclass(chan));
                }
index 1fb22b1..1355361 100644 (file)
@@ -1070,7 +1070,7 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel
                        ast_channel_inherit_variables(caller, outbound);
                        ast_channel_datastore_inherit(caller, outbound);
                        ast_channel_language_set(outbound, ast_channel_language(caller));
-                       ast_channel_accountcode_set(outbound, ast_channel_accountcode(caller));
+                       ast_channel_req_accountcodes(outbound, caller, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
                        ast_channel_musicclass_set(outbound, ast_channel_musicclass(caller));
                        ast_channel_unlock(outbound);
                        ast_channel_unlock(caller);
index fe6b00a..0b53ea6 100644 (file)
@@ -4125,6 +4125,8 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
 
        ast_channel_lock_both(tmp->chan, qe->chan);
 
+       ast_channel_req_accountcodes_precious(tmp->chan, qe->chan,
+               AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
        if (qe->cancel_answered_elsewhere) {
                ast_channel_hangupcause_set(tmp->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
        }
@@ -4663,7 +4665,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                                                        ast_party_connected_line_copy(&o->connected, ast_channel_connected(in));
                                                }
 
-                                               ast_channel_accountcode_set(o->chan, ast_channel_accountcode(in));
+                                               ast_channel_req_accountcodes(o->chan, in, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
 
                                                if (!ast_channel_redirecting(o->chan)->from.number.valid
                                                        || ast_strlen_zero(ast_channel_redirecting(o->chan)->from.number.str)) {
index d5d32c9..08f4eff 100644 (file)
@@ -1387,6 +1387,45 @@ struct ast_channel *ast_channel_release(struct ast_channel *chan);
  */
 struct ast_channel *ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause);
 
+enum ast_channel_requestor_relationship {
+       /*! The requestor is the future bridge peer of the channel. */
+       AST_CHANNEL_REQUESTOR_BRIDGE_PEER,
+       /*! The requestor is to be replaced by the channel. */
+       AST_CHANNEL_REQUESTOR_REPLACEMENT,
+};
+
+/*!
+ * \brief Setup new channel accountcodes from the requestor channel after ast_request().
+ * \since 13.0.0
+ *
+ * \param chan New channel to get accountcodes setup.
+ * \param requestor Requesting channel to get accountcodes from.
+ * \param relationship What the new channel was created for.
+ *
+ * \pre The chan and requestor channels are already locked.
+ *
+ * \note Pre-existing accountcodes on chan will be overwritten.
+ *
+ * \return Nothing
+ */
+void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship);
+
+/*!
+ * \brief Setup new channel accountcodes from the requestor channel after ast_request().
+ * \since 13.0.0
+ *
+ * \param chan New channel to get accountcodes setup.
+ * \param requestor Requesting channel to get accountcodes from.
+ * \param relationship What the new channel was created for.
+ *
+ * \pre The chan and requestor channels are already locked.
+ *
+ * \note Pre-existing accountcodes on chan will not be overwritten.
+ *
+ * \return Nothing
+ */
+void ast_channel_req_accountcodes_precious(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship);
+
 /*!
  * \brief Request a channel of a given type, with data as optional information used
  *        by the low level module and attempt to place a call on it
index d5fc169..45b4238 100644 (file)
@@ -3793,7 +3793,11 @@ static enum ast_transfer_result blind_transfer_bridge(struct ast_channel *transf
                return AST_BRIDGE_TRANSFER_FAIL;
        }
 
+       ast_channel_lock_both(local, transferer);
+       ast_channel_req_accountcodes(local, transferer, AST_CHANNEL_REQUESTOR_REPLACEMENT);
        pbx_builtin_setvar_helper(local, BLINDTRANSFER, ast_channel_name(transferer));
+       ast_channel_unlock(local);
+       ast_channel_unlock(transferer);
 
        if (new_channel_cb) {
                new_channel_cb(local, user_data_wrapper, AST_BRIDGE_TRANSFER_MULTI_PARTY);
@@ -3952,12 +3956,15 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha
 
        local_chan = ast_request("Local", ast_channel_nativeformats(chan1), NULL, chan1,
                        dest, &cause);
-
        if (!local_chan) {
                return AST_BRIDGE_TRANSFER_FAIL;
        }
 
+       ast_channel_lock_both(local_chan, chan1);
+       ast_channel_req_accountcodes(local_chan, chan1, AST_CHANNEL_REQUESTOR_REPLACEMENT);
        pbx_builtin_setvar_helper(local_chan, ATTENDEDTRANSFER, ast_channel_name(chan1));
+       ast_channel_unlock(local_chan);
+       ast_channel_unlock(chan1);
 
        if (bridge2) {
                res = ast_local_setup_bridge(local_chan, bridge2, chan2, NULL);
index cb8c2f9..0d95d83 100644 (file)
@@ -2982,11 +2982,18 @@ static struct ast_channel *dial_transfer(struct ast_channel *caller, const char
                return NULL;
        }
 
+       ast_channel_lock_both(chan, caller);
+
+       ast_channel_req_accountcodes(chan, caller, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
+
        /* Who is transferring the call. */
        pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", ast_channel_name(caller));
 
        ast_bridge_set_transfer_variables(chan, ast_channel_name(caller), 1);
 
+       ast_channel_unlock(chan);
+       ast_channel_unlock(caller);
+
        /* Before we actually dial out let's inherit appropriate information. */
        copy_caller_data(chan, caller);
 
index a3005af..4be1351 100644 (file)
@@ -946,7 +946,7 @@ int ast_cel_fill_record(const struct ast_event *e, struct ast_cel_event_record *
        r->application_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPNAME), "");
        r->application_data = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPDATA), "");
        r->account_code     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
-       r->peer_account     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
+       r->peer_account     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_PEERACCT), "");
        r->unique_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_UNIQUEID), "");
        r->linked_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_LINKEDID), "");
        r->amaflag          = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_AMAFLAGS);
index e9e37c0..4ce4e91 100644 (file)
@@ -5549,9 +5549,12 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
                if (oh->parent_channel) {
                        call_forward_inherit(new_chan, oh->parent_channel, orig);
                }
-               if (oh->account) {
+               if (!ast_strlen_zero(oh->account)) {
                        ast_channel_lock(new_chan);
+                       ast_channel_stage_snapshot(new_chan);
                        ast_channel_accountcode_set(new_chan, oh->account);
+                       ast_channel_peeraccount_set(new_chan, oh->account);
+                       ast_channel_stage_snapshot_done(new_chan);
                        ast_channel_unlock(new_chan);
                }
        } else if (caller) { /* no outgoing helper so use caller if available */
@@ -5560,9 +5563,9 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
        ast_set_flag(ast_channel_flags(new_chan), AST_FLAG_ORIGINATED);
 
        ast_channel_lock_both(orig, new_chan);
-       ast_channel_accountcode_set(new_chan, ast_channel_accountcode(orig));
        ast_party_connected_line_copy(ast_channel_connected(new_chan), ast_channel_connected(orig));
        ast_party_redirecting_copy(ast_channel_redirecting(new_chan), ast_channel_redirecting(orig));
+       ast_channel_req_accountcodes(new_chan, orig, AST_CHANNEL_REQUESTOR_REPLACEMENT);
        ast_channel_unlock(new_chan);
        ast_channel_unlock(orig);
 
@@ -5625,9 +5628,12 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
                        ast_channel_unlock(oh->parent_channel);
                        ast_channel_unlock(chan);
                }
-               if (oh->account) {
+               if (!ast_strlen_zero(oh->account)) {
                        ast_channel_lock(chan);
+                       ast_channel_stage_snapshot(chan);
                        ast_channel_accountcode_set(chan, oh->account);
+                       ast_channel_peeraccount_set(chan, oh->account);
+                       ast_channel_stage_snapshot_done(chan);
                        ast_channel_unlock(chan);
                }
        }
@@ -5655,6 +5661,12 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
                connected.id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
        }
        ast_channel_set_connected_line(chan, &connected, NULL);
+       if (requestor) {
+               ast_channel_lock_both(chan, (struct ast_channel *) requestor);
+               ast_channel_req_accountcodes(chan, requestor, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
+               ast_channel_unlock(chan);
+               ast_channel_unlock((struct ast_channel *) requestor);
+       }
 
        if (ast_call(chan, addr, 0)) {  /* ast_call failed... */
                ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, addr);
@@ -5880,15 +5892,20 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
                        return NULL;
                }
 
-               /* Set newly created channel callid to same as the requestor */
                if (requestor) {
-                       struct ast_callid *callid = ast_channel_callid(requestor);
+                       struct ast_callid *callid;
+
+                       ast_channel_lock_both(c, (struct ast_channel *) requestor);
+
+                       /* Set the newly created channel's callid to the same as the requestor. */
+                       callid = ast_channel_callid(requestor);
                        if (callid) {
-                               ast_channel_lock(c);
                                ast_channel_callid_set(c, callid);
-                               ast_channel_unlock(c);
                                callid = ast_callid_unref(callid);
                        }
+
+                       ast_channel_unlock(c);
+                       ast_channel_unlock((struct ast_channel *) requestor);
                }
 
                ao2_ref(joint_cap, -1);
@@ -5911,6 +5928,88 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
        return NULL;
 }
 
+/*!
+ * \internal
+ * \brief Setup new channel accountcodes from the requestor channel after ast_request().
+ * \since 13.0.0
+ *
+ * \param chan New channel to get accountcodes setup.
+ * \param requestor Requesting channel to get accountcodes from.
+ * \param relationship What the new channel was created for.
+ * \param precious TRUE if pre-existing accountcodes on chan will not be overwritten.
+ *
+ * \pre The chan and requestor channels are already locked.
+ *
+ * \return Nothing
+ */
+static void channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship, int precious)
+{
+       /*
+        * The primary reason for the existence of this function is
+        * so local channels can propagate accountcodes to the ;2
+        * channel before ast_call().
+        *
+        * The secondary reason is to propagate the CHANNEL(peeraccount)
+        * value set before Dial, FollowMe, and Queue while maintaining
+        * the historic straight across accountcode propagation as a
+        * fallback.
+        */
+       switch (relationship) {
+       case AST_CHANNEL_REQUESTOR_BRIDGE_PEER:
+               /* Crossover the requestor's accountcode and peeraccount */
+               if (!precious || ast_strlen_zero(ast_channel_accountcode(chan))) {
+                       /*
+                        * The newly created channel does not have an accountcode
+                        * or we don't care.
+                        */
+                       if (!ast_strlen_zero(ast_channel_peeraccount(requestor))) {
+                               /*
+                                * Set it to the requestor's peeraccount.  This allows the
+                                * dialplan to indicate the accountcode to use when dialing
+                                * by setting CHANNEL(peeraccount).
+                                */
+                               ast_channel_accountcode_set(chan, ast_channel_peeraccount(requestor));
+                       } else if (!precious
+                               && !ast_strlen_zero(ast_channel_accountcode(requestor))) {
+                               /*
+                                * Fallback to the historic propagation and set it to the
+                                * requestor's accountcode.
+                                */
+                               ast_channel_accountcode_set(chan, ast_channel_accountcode(requestor));
+                       }
+               }
+               if (!ast_strlen_zero(ast_channel_accountcode(requestor))) {
+                       ast_channel_peeraccount_set(chan, ast_channel_accountcode(requestor));
+               }
+               break;
+       case AST_CHANNEL_REQUESTOR_REPLACEMENT:
+               /* Pass the requestor's accountcode and peeraccount straight. */
+               if (!precious || ast_strlen_zero(ast_channel_accountcode(chan))) {
+                       /*
+                        * The newly created channel does not have an accountcode
+                        * or we don't care.
+                        */
+                       if (!ast_strlen_zero(ast_channel_accountcode(requestor))) {
+                               ast_channel_accountcode_set(chan, ast_channel_accountcode(requestor));
+                       }
+               }
+               if (!ast_strlen_zero(ast_channel_peeraccount(requestor))) {
+                       ast_channel_peeraccount_set(chan, ast_channel_peeraccount(requestor));
+               }
+               break;
+       }
+}
+
+void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
+{
+       channel_req_accountcodes(chan, requestor, relationship, 0);
+}
+
+void ast_channel_req_accountcodes_precious(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
+{
+       channel_req_accountcodes(chan, requestor, relationship, 1);
+}
+
 int ast_pre_call(struct ast_channel *chan, const char *sub_args)
 {
        int (*pre_call)(struct ast_channel *chan, const char *sub_args);
index a1ae897..b3dc528 100644 (file)
@@ -36,6 +36,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/causes.h"
 #include "asterisk/channel.h"
+#include "asterisk/stasis_channels.h"
 #include "asterisk/pbx.h"
 #include "asterisk/musiconhold.h"
 #include "asterisk/astobj2.h"
@@ -100,6 +101,7 @@ int ast_unreal_setoption(struct ast_channel *ast, int option, void *data, int da
        struct ast_unreal_pvt *p;
        struct ast_channel *otherchan = NULL;
        ast_chan_write_info_t *write_info;
+       char *info_data;
 
        if (option != AST_OPTION_CHANNEL_WRITE) {
                return -1;
@@ -112,10 +114,19 @@ int ast_unreal_setoption(struct ast_channel *ast, int option, void *data, int da
                return -1;
        }
 
-       if (!strcmp(write_info->function, "CHANNEL")
-               && !strncasecmp(write_info->data, "hangup_handler_", 15)) {
-               /* Block CHANNEL(hangup_handler_xxx) writes to the other unreal channel. */
-               return 0;
+       info_data = write_info->data;
+       if (!strcmp(write_info->function, "CHANNEL")) {
+               if (!strncasecmp(info_data, "hangup_handler_", 15)) {
+                       /* Block CHANNEL(hangup_handler_xxx) writes to the other unreal channel. */
+                       return 0;
+               }
+
+               /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
+               if (!strcasecmp(info_data, "accountcode")) {
+                       info_data = "peeraccount";
+               } else if (!strcasecmp(info_data, "peeraccount")) {
+                       info_data = "accountcode";
+               }
        }
 
        /* get the tech pvt */
@@ -140,7 +151,7 @@ int ast_unreal_setoption(struct ast_channel *ast, int option, void *data, int da
        ao2_unlock(p);
 
        ast_channel_lock(otherchan);
-       res = write_info->write_fn(otherchan, write_info->function, write_info->data, write_info->value);
+       res = write_info->write_fn(otherchan, write_info->function, info_data, write_info->value);
        ast_channel_unlock(otherchan);
 
 setoption_cleanup:
@@ -642,6 +653,8 @@ void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
        struct ast_var_t *varptr;
        struct ast_var_t *clone_var;
 
+       ast_channel_stage_snapshot(semi2);
+
        /*
         * Note that cid_num and cid_name aren't passed in the
         * ast_channel_alloc calls in ast_unreal_new_channels().  It's
@@ -651,11 +664,16 @@ void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
 
        ast_party_dialed_copy(ast_channel_dialed(semi2), ast_channel_dialed(semi1));
 
+       /* Crossover the CallerID and conected-line to cross the unreal bridge. */
        ast_connected_line_copy_to_caller(ast_channel_caller(semi2), ast_channel_connected(semi1));
        ast_connected_line_copy_from_caller(ast_channel_connected(semi2), ast_channel_caller(semi1));
 
        ast_channel_language_set(semi2, ast_channel_language(semi1));
-       ast_channel_accountcode_set(semi2, ast_channel_accountcode(semi1));
+
+       /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
+       ast_channel_accountcode_set(semi2, ast_channel_peeraccount(semi1));
+       ast_channel_peeraccount_set(semi2, ast_channel_accountcode(semi1));
+
        ast_channel_musicclass_set(semi2, ast_channel_musicclass(semi1));
 
        ast_channel_cc_params_init(semi2, ast_channel_get_cc_config_params(semi1));
@@ -682,6 +700,8 @@ void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
                }
        }
        ast_channel_datastore_inherit(semi1, semi2);
+
+       ast_channel_stage_snapshot_done(semi2);
 }
 
 int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags)
index afee5ee..04249fd 100644 (file)
@@ -318,7 +318,12 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
        cap_request = NULL;
        ao2_cleanup(cap_all_audio);
 
-       ast_channel_lock(channel->owner);
+       if (chan) {
+               ast_channel_lock_both(chan, channel->owner);
+       } else {
+               ast_channel_lock(channel->owner);
+       }
+
        ast_channel_stage_snapshot(channel->owner);
 
        ast_channel_appl_set(channel->owner, "AppDial2");
@@ -339,12 +344,13 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
                ast_connected_line_copy_from_caller(ast_channel_connected(channel->owner), ast_channel_caller(chan));
 
                ast_channel_language_set(channel->owner, ast_channel_language(chan));
-               ast_channel_accountcode_set(channel->owner, ast_channel_accountcode(chan));
+               ast_channel_req_accountcodes(channel->owner, chan, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
                if (ast_strlen_zero(ast_channel_musicclass(channel->owner)))
                        ast_channel_musicclass_set(channel->owner, ast_channel_musicclass(chan));
 
                ast_channel_adsicpe_set(channel->owner, ast_channel_adsicpe(chan));
                ast_channel_transfercapability_set(channel->owner, ast_channel_transfercapability(chan));
+               ast_channel_unlock(chan);
        }
 
        ast_channel_stage_snapshot_done(channel->owner);
index 389a4c0..48fd119 100644 (file)
@@ -10347,8 +10347,11 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap,
        if (vars) {
                ast_set_variables(dialed, vars);
        }
-       if (account) {
+       if (!ast_strlen_zero(account)) {
+               ast_channel_stage_snapshot(dialed);
                ast_channel_accountcode_set(dialed, account);
+               ast_channel_peeraccount_set(dialed, account);
+               ast_channel_stage_snapshot_done(dialed);
        }
        ast_set_flag(ast_channel_flags(dialed), AST_FLAG_ORIGINATED);
        ast_channel_unlock(dialed);
index 8f563f7..61cb85f 100644 (file)
@@ -235,6 +235,7 @@ static struct ast_channel *park_local_transfer(struct ast_channel *parker, const
 
        /* Before we actually dial out let's inherit appropriate information. */
        ast_channel_lock_both(parker, parkee);
+       ast_channel_req_accountcodes(parkee, parker, AST_CHANNEL_REQUESTOR_REPLACEMENT);
        ast_connected_line_copy_from_caller(ast_channel_connected(parkee), ast_channel_caller(parker));
        ast_channel_inherit_variables(parker, parkee);
        ast_channel_datastore_inherit(parker, parkee);