]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Expand the scope of Dial Events 91/2791/6
authorMark Michelson <mmichelson@digium.com>
Mon, 9 May 2016 20:00:56 +0000 (15:00 -0500)
committerMark Michelson <mmichelson@digium.com>
Tue, 31 May 2016 16:43:24 +0000 (11:43 -0500)
Dial events up to this point have come in two flavors
* A Dial event with no status to indicate that dialing has begun
* A Dial event with a status to indicate that dialing has ended

With this change, Dial events have been expanded to also give
intermediate events, such as "RINGING", "PROCEEDING", and "PROGRESS".
This is especially useful for ARI dialing, as it gives the application
writer the opportunity to place a channel into an early bridge when
early media is detected.

AMI handles these in-progress dial events by sending a new event called
"DialState" that simply indicates that dial state has changed but has
not ended. ARI never distinguished between DialBegin and DialEnd, so no
change was made to the event itself.

Another change here relates to dial forwards. A forward-related event
was previously only sent when a channel was successfully able to forward
a call to a new channel. With this set of changes, if forwarding is
blocked, we send a Dial event with a forwarding destination but no
forwarding channel, since we were prevented from creating one. This is
again useful for ARI since application writers can now handle call
forward attempts from within their own application.

ASTERISK-25925 #close
Reported by Mark Michelson

Change-Id: I42cbec7730d84640a434d143a0d172a740995543

CHANGES
UPGRADE.txt
apps/app_dial.c
apps/app_followme.c
apps/app_queue.c
main/bridge_channel.c
main/cdr.c
main/dial.c
main/manager_channels.c
main/stasis_channels.c

diff --git a/CHANGES b/CHANGES
index 255ccd24accd325db874f235da7c3c5b9976e445..fe3a25396411a577adf405b316a0bec8af18c0df 100644 (file)
--- a/CHANGES
+++ b/CHANGES
 --- Functionality changes from Asterisk 13 to Asterisk 14 --------------------
 ------------------------------------------------------------------------------
 
+AMI
+-----------------
+ * A new event, "DialState" has been added. This is similar to "DialBegin" and
+ "DialEnd" in that it tracks the state of a dialed call. The difference is that
+ this indicates some intermediate state change in the dial attempt, such as
+ "RINGING", "PROGRESS", or "PROCEEDING".
+
 ARI
 -----------------
  * A new ARI method has been added to the channels resource. "create" allows for
@@ -23,6 +30,10 @@ ARI
  * To complement the "create" method, a "dial" method has been added to the channels
  resource in order to place a call to a created channel.
 
+ * "Dial" events have been modified to not only be sent when dialing begins and ends.
+ They now are also sent for intermediate states, such as "RINGING", "PROGRESS", and
+ "PROCEEDING".
+
 Applications
 ------------------
 
index 131ce6caab238b1ac45f8e38f58f780ba928a796..f8fa7906b42df3177db8eb8c7076d8a375ba7c73 100644 (file)
 === UPGRADE-13.txt  -- Upgrade info for 12 to 13
 ===========================================================
 
+ARI:
+ - The policy for when to send "Dial" events has changed. Previously, "Dial"
+   events were sent on the calling channel's topic. However, starting in Asterisk
+   14, if there is no calling channel on which to send the event, the event is
+   instead sent on the called channel's topic. Note that for the ARI channels
+   resource's dial operation, this means that the "Dial" events will always be
+   sent on the called channel's topic.
+
 Channel Drivers:
 
 chan_dahdi:
index 11591bdfbe78a2ce043cbb8d42e7d773aa47b174..5e034d3ebe2e9037f738ee6697db3a82d2980aa7 100644 (file)
@@ -872,6 +872,8 @@ static void do_forward(struct chanlist *o, struct cause_args *num,
        /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
        if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
                ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", ast_channel_name(in), tech, stuff);
+               ast_channel_publish_dial_forward(in, original, NULL, NULL, "CANCEL",
+                       ast_channel_call_forward(original));
                c = o->chan = NULL;
                cause = AST_CAUSE_BUSY;
        } else {
@@ -1385,6 +1387,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                                        pa->sentringing++;
                                                }
                                        }
+                                       ast_channel_publish_dial(in, c, NULL, "RINGING");
                                        break;
                                case AST_CONTROL_PROGRESS:
                                        ast_verb(3, "%s is making progress passing it to %s\n", ast_channel_name(c), ast_channel_name(in));
@@ -1404,6 +1407,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                                        dtmf_progress);
                                                ast_dtmf_stream(c, in, dtmf_progress, 250, 0);
                                        }
+                                       ast_channel_publish_dial(in, c, NULL, "PROGRESS");
                                        break;
                                case AST_CONTROL_VIDUPDATE:
                                case AST_CONTROL_SRCUPDATE:
@@ -1476,6 +1480,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                        }
                                        if (!ast_test_flag64(outgoing, OPT_RINGBACK))
                                                ast_indicate(in, AST_CONTROL_PROCEEDING);
+                                       ast_channel_publish_dial(in, c, NULL, "PROCEEDING");
                                        break;
                                case AST_CONTROL_HOLD:
                                        /* XXX this should be saved like AST_CONTROL_CONNECTED_LINE for !single || caller_entertained */
index d2000fd13535a7fa119c2fc83dae71639bee01d2..6687534171be044d909866b6d4f5b1eebf2111f4 100644 (file)
@@ -822,9 +822,11 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                                                break;
                                        case AST_CONTROL_RINGING:
                                                ast_verb(3, "%s is ringing\n", ast_channel_name(winner));
+                                               ast_channel_publish_dial(caller, winner, NULL, "RINGING");
                                                break;
                                        case AST_CONTROL_PROGRESS:
                                                ast_verb(3, "%s is making progress\n", ast_channel_name(winner));
+                                               ast_channel_publish_dial(caller, winner, NULL, "PROGRESS");
                                                break;
                                        case AST_CONTROL_VIDUPDATE:
                                                ast_verb(3, "%s requested a video update\n", ast_channel_name(winner));
@@ -834,6 +836,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                                                break;
                                        case AST_CONTROL_PROCEEDING:
                                                ast_verb(3, "%s is proceeding\n", ast_channel_name(winner));
+                                               ast_channel_publish_dial(caller, winner, NULL, "PROCEEDING");
                                                break;
                                        case AST_CONTROL_HOLD:
                                                ast_verb(3, "%s placed call on hold\n", ast_channel_name(winner));
index 8171d11cb47a844fa2086f0ef61f6d4dbd1f76cd..165924e0c889c9fc9e247fde10f90eeabf797a00 100644 (file)
@@ -4846,6 +4846,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                                /* Before processing channel, go ahead and check for forwarding */
                                if (!ast_strlen_zero(ast_channel_call_forward(o->chan)) && !forwardsallowed) {
                                        ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, ast_channel_call_forward(o->chan));
+                                       ast_channel_publish_dial_forward(qe->chan, o->chan, NULL, NULL,
+                                               "CANCEL", ast_channel_call_forward(o->chan));
                                        numnochan++;
                                        do_hang(o);
                                        winner = NULL;
@@ -5052,6 +5054,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                                                case AST_CONTROL_RINGING:
                                                        ast_verb(3, "%s is ringing\n", ochan_name);
 
+                                                       ast_channel_publish_dial(qe->chan, o->chan, on, "RINGING");
+
                                                        /* Start ring indication when the channel is ringing, if specified */
                                                        if (qe->ring_when_ringing) {
                                                                ast_moh_stop(qe->chan);
index db4ecfe57cd10cf497892425a34f5212a9e76e92..6766dff8ec1d84f453ed4905c5100410a6b66ba1 100644 (file)
@@ -2393,6 +2393,14 @@ static struct ast_frame *bridge_handle_dtmf(struct ast_bridge_channel *bridge_ch
        return frame;
 }
 
+static const char *controls[] = {
+       [AST_CONTROL_RINGING] = "RINGING",
+       [AST_CONTROL_PROCEEDING] = "PROCEEDING",
+       [AST_CONTROL_PROGRESS] = "PROGRESS",
+       [AST_CONTROL_BUSY] = "BUSY",
+       [AST_CONTROL_CONGESTION] = "CONGESTION",
+       [AST_CONTROL_ANSWER] = "ANSWER",
+};
 
 /*!
  * \internal
@@ -2404,6 +2412,17 @@ static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel)
 {
        struct ast_frame *frame;
 
+       if (!ast_strlen_zero(ast_channel_call_forward(bridge_channel->chan))) {
+               /* TODO If early bridging is ever used by anything other than ARI,
+                * it's important that we actually attempt to handle the call forward
+                * attempt, as well as expand features on a bridge channel to allow/disallow
+                * call forwarding. For now, all we do is raise an event, showing that
+                * a call forward is being attempted.
+                */
+               ast_channel_publish_dial_forward(NULL, bridge_channel->chan, NULL, NULL, "CANCEL",
+                       ast_channel_call_forward(bridge_channel->chan));
+       }
+
        if (bridge_channel->features->mute) {
                frame = ast_read_noaudio(bridge_channel->chan);
        } else {
@@ -2417,10 +2436,20 @@ static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel)
        switch (frame->frametype) {
        case AST_FRAME_CONTROL:
                switch (frame->subclass.integer) {
+               case AST_CONTROL_CONGESTION:
+               case AST_CONTROL_BUSY:
+                       ast_channel_publish_dial(NULL, bridge_channel->chan, NULL, controls[frame->subclass.integer]);
+                       break;
                case AST_CONTROL_HANGUP:
                        ast_bridge_channel_kick(bridge_channel, 0);
                        bridge_frame_free(frame);
                        return;
+               case AST_CONTROL_RINGING:
+               case AST_CONTROL_PROGRESS:
+               case AST_CONTROL_PROCEEDING:
+               case AST_CONTROL_ANSWER:
+                       ast_channel_publish_dial(NULL, bridge_channel->chan, NULL, controls[frame->subclass.integer]);
+                       break;
                default:
                        break;
                }
index b6a0b428c98257dec6c7e29fd4328a7e2ca61f00..b43e3610c074bbce93324ce74cfd681b73def230 100644 (file)
@@ -1902,6 +1902,13 @@ static int filter_channel_cache_message(struct ast_channel_snapshot *old_snapsho
        return ret;
 }
 
+static int dial_status_end(const char *dialstatus)
+{
+       return (strcmp(dialstatus, "RINGING") &&
+                       strcmp(dialstatus, "PROCEEDING") &&
+                       strcmp(dialstatus, "PROGRESS"));
+}
+
 /* TOPIC ROUTER CALLBACKS */
 
 /*!
@@ -1970,7 +1977,7 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
                        res &= it_cdr->fn_table->process_dial_begin(it_cdr,
                                        caller,
                                        peer);
-               } else {
+               } else if (dial_status_end(dial_status)) {
                        if (!it_cdr->fn_table->process_dial_end) {
                                continue;
                        }
index fc66af5a7665ad01bd3a2f11a1b125586de9185c..bac191e0657b9fafee30fb1620216cc2e47e1385 100644 (file)
@@ -627,11 +627,13 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
                        break;
                case AST_CONTROL_RINGING:
                        ast_verb(3, "%s is ringing\n", ast_channel_name(channel->owner));
+                       ast_channel_publish_dial(chan, channel->owner, channel->device, "RINGING");
                        if (chan && !dial->options[AST_DIAL_OPTION_MUSIC])
                                ast_indicate(chan, AST_CONTROL_RINGING);
                        set_state(dial, AST_DIAL_RESULT_RINGING);
                        break;
                case AST_CONTROL_PROGRESS:
+                       ast_channel_publish_dial(chan, channel->owner, channel->device, "PROGRESS");
                        if (chan) {
                                ast_verb(3, "%s is making progress, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
                                ast_indicate(chan, AST_CONTROL_PROGRESS);
@@ -675,6 +677,7 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
                        }
                        break;
                case AST_CONTROL_PROCEEDING:
+                       ast_channel_publish_dial(chan, channel->owner, channel->device, "PROCEEDING");
                        if (chan) {
                                ast_verb(3, "%s is proceeding, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
                                ast_indicate(chan, AST_CONTROL_PROCEEDING);
index c395708cc9a35de30a71f4cda6372bc14099032f..ec1f807dcf2f00d216d650f925c040aeb0bec3c4 100644 (file)
@@ -142,6 +142,33 @@ ASTERISK_REGISTER_FILE()
                        </see-also>
                </managerEventInstance>
        </managerEvent>
+       <managerEvent language="en_US" name="DialState">
+               <managerEventInstance class="EVENT_FLAG_CALL">
+                       <synopsis>Raised when dial status has changed.</synopsis>
+                       <syntax>
+                               <channel_snapshot/>
+                               <channel_snapshot prefix="Dest"/>
+                               <parameter name="DialStatus">
+                                       <para> The new state of the outbound dial attempt.</para>
+                                       <enumlist>
+                                               <enum name="RINGING">
+                                                       <para>The outbound channel is ringing.</para>
+                                               </enum>
+                                               <enum name="PROCEEDING">
+                                                       <para>The call to the outbound channel is proceeding.</para>
+                                               </enum>
+                                               <enum name="PROGRESS">
+                                                       <para>Progress has been received on the outbound channel.</para>
+                                               </enum>
+                                       </enumlist>
+                               </parameter>
+                               <parameter name="Forward" required="false">
+                                       <para>If the call was forwarded, where the call was
+                                       forwarded to.</para>
+                               </parameter>
+                       </syntax>
+               </managerEventInstance>
+       </managerEvent>
        <managerEvent language="en_US" name="DialEnd">
                <managerEventInstance class="EVENT_FLAG_CALL">
                        <synopsis>Raised when a dial action has completed.</synopsis>
@@ -1034,6 +1061,13 @@ static void channel_monitor_stop_cb(void *data, struct stasis_subscription *sub,
        publish_basic_channel_event("MonitorStop", EVENT_FLAG_CALL, payload->snapshot);
 }
 
+static int dial_status_end(const char *dialstatus)
+{
+       return (strcmp(dialstatus, "RINGING") &&
+                       strcmp(dialstatus, "PROCEEDING") &&
+                       strcmp(dialstatus, "PROGRESS"));
+}
+
 /*!
  * \brief Callback processing messages for channel dialing
  */
@@ -1077,7 +1111,7 @@ static void channel_dial_cb(void *data, struct stasis_subscription *sub,
        } else {
                int forwarded = !ast_strlen_zero(forward);
 
-               manager_event(EVENT_FLAG_CALL, "DialEnd",
+               manager_event(EVENT_FLAG_CALL, dial_status_end(dialstatus) ? "DialEnd" : "DialState",
                                "%s"
                                "%s"
                                "%s%s%s"
index e56d1b928b216fd1ad3e44f37733df4ddf1ae7de..e1c50c6d05f9ee07c231f62fb1d176c5178d0c53 100644 (file)
@@ -362,7 +362,7 @@ static void ast_channel_publish_dial_internal(struct ast_channel *caller,
                return;
        }
 
-       publish_message_for_channel_topics(msg, caller);
+       publish_message_for_channel_topics(msg, caller ?: peer);
 }
 
 static void remove_dial_masquerade(struct ast_channel *peer);