]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
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 788a1141cbc091d55def24ff8d46c813c2b48c1d..8770147363d65d0826b36e5ea5f773f9079e935e 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 535782a8616ea2433c2c8c4d46cdf8b6ea4f0238..37160c4364c5ed4726611a0c960e30366dc5de53 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 df9b72aafba8c83207209a80553260cfe16ff113..b48a226c79ca19eb66414c1a8c4c94c588af8823 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 1fb22b1859a8f1a2cd4f911c86a6f1acec268035..1355361e277e445d18eb72b308091cb4351d72e8 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 fe6b00ab0f749e82490aae164d4da57e3b9a5c10..0b53ea6191c513d95136f2f3ea9a495d12924aa7 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 d5d32c92185bd229e82be35758f98f4b389c35e4..08f4effe6084a5c3bb9daefe6a9cf71707946ce7 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 d5fc1699a712334c1acd208ee61258b03ce01e8f..45b42380a969fe7e439ff09f213ff81b296b9418 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 cb8c2f992b0fc242c77c5e8d68b9edc861ace8e4..0d95d83d27a47053b5ecffff39eee97448722226 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 a3005af8b75532503ee635a2999fbda062930f15..4be13511c1285a92ada1fe16018c731114277429 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 e9e37c0fda6c59bf91656327224a9c0a2722067c..4ce4e916f4809aede94bed1ff958d9cf58212890 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 a1ae897b9f1066d458e63d3a36f61377ca8412a0..b3dc5281c61a7ee7d4384efcbd7ac44350142e57 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 afee5eeca653f95aad316b8045bb768b2a8591c0..04249fd71dbf60361e3cd61adeae1045e676f61f 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 389a4c0f50dec680d8909b8139ab06e6b78169a0..48fd119f542342eb00d9cee6c74451611097eeb8 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 8f563f7cf77114a754e2954ff820174d07e70d12..61cb85f008d45baab6d243ea3f1542abed83134b 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);