app_queue.c: Force COLP update if outgoing channel name changed.
authorRichard Mudgett <rmudgett@digium.com>
Thu, 24 Sep 2015 19:56:24 +0000 (14:56 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 25 Sep 2015 17:40:31 +0000 (12:40 -0500)
* When a call is answered and the outgoing channel name has changed then
force a connected line update because the channel is no longer the same.
The channel was masqueraded into by another channel.  This is usually
because of a call pickup.

Note: Forwarded calls are handled in a controlled manner so the original
channel name is replaced with the forwarded channel.

ASTERISK-25423 #close
Reported by: John Hardin

Change-Id: Ie275ea9e99c092ad369db23e0feb08c44498c172

apps/app_queue.c

index 0d5f743..e043e18 100644 (file)
@@ -1487,6 +1487,8 @@ struct callattempt {
        /*! TRUE if the call is still active */
        unsigned int stillgoing:1;
        struct ast_aoc_decoded *aoc_s_rate_list;
+       /*! Original channel name.  Must be freed.  Could be NULL if allocation failed. */
+       char *orig_chan_name;
 };
 
 
@@ -3969,6 +3971,7 @@ static void callattempt_free(struct callattempt *doomed)
                ao2_ref(doomed->member, -1);
        }
        ast_party_connected_line_free(&doomed->connected);
+       ast_free(doomed->orig_chan_name);
        ast_free(doomed);
 }
 
@@ -4300,6 +4303,9 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
                ast_channel_exten_set(tmp->chan, ast_channel_exten(qe->chan));
        }
 
+       /* Save the original channel name to detect call pickup masquerading in. */
+       tmp->orig_chan_name = ast_strdup(ast_channel_name(tmp->chan));
+
        ast_channel_unlock(tmp->chan);
        ast_channel_unlock(qe->chan);
 
@@ -4721,7 +4727,14 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                        if (o->stillgoing && (o->chan) &&  (ast_channel_state(o->chan) == AST_STATE_UP)) {
                                if (!peer) {
                                        ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
-                                       if (!o->block_connected_update) {
+                                       if (o->orig_chan_name
+                                               && strcmp(o->orig_chan_name, ochan_name)) {
+                                               /*
+                                                * The channel name changed so we must generate COLP update.
+                                                * Likely because a call pickup channel masqueraded in.
+                                                */
+                                               update_connected_line_from_peer(in, o->chan, 1);
+                                       } else if (!o->block_connected_update) {
                                                if (o->pending_connected_update) {
                                                        if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
                                                                ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
@@ -4809,6 +4822,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                                                        ast_party_connected_line_copy(&o->connected, ast_channel_connected(in));
                                                }
 
+                                               ast_free(o->orig_chan_name);
+                                               o->orig_chan_name = ast_strdup(ast_channel_name(o->chan));
+
                                                ast_channel_req_accountcodes(o->chan, in, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
 
                                                if (!ast_channel_redirecting(o->chan)->from.number.valid
@@ -4884,7 +4900,14 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                                                                ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
                                                                ast_channel_publish_dial(qe->chan, o->chan, on, "ANSWER");
                                                                publish_dial_end_event(qe->chan, outgoing, o->chan, "CANCEL");
-                                                               if (!o->block_connected_update) {
+                                                               if (o->orig_chan_name
+                                                                       && strcmp(o->orig_chan_name, ochan_name)) {
+                                                                       /*
+                                                                        * The channel name changed so we must generate COLP update.
+                                                                        * Likely because a call pickup channel masqueraded in.
+                                                                        */
+                                                                       update_connected_line_from_peer(in, o->chan, 1);
+                                                               } else if (!o->block_connected_update) {
                                                                        if (o->pending_connected_update) {
                                                                                if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
                                                                                        ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {