]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Improve call forwarding reporting, especially with regards to ARI.
authorMatthew Jordan <mjordan@digium.com>
Mon, 18 Aug 2014 00:57:01 +0000 (00:57 +0000)
committerMatthew Jordan <mjordan@digium.com>
Mon, 18 Aug 2014 00:57:01 +0000 (00:57 +0000)
This patch addresses a few issues:

1) The order of Dial events have been changed when performing a call forward.
   The order has now been altered to
    1) Dial begins dialing channel A.
    2) When A forwards the call to B, we issue the dial end event to channel
       A, indicating the dial is being canceled due to a forward to B.
    3) When the call to channel B occurs, we then issue a new dial begin to
       channel B.

2) Call forwards are now reported on the calling channel, not the peer channel.

3) AMI DialEnd events have been altered to display the extension the call is
   being forwarded to when relevant.

4) You can now get the values of channel variables for channels that are not
   currently in the Stasis application. This brings the retrieval of channel
   variables more in line with the rest of channel read operations since they
   may be performed on channels not in Stasis.

ASTERISK-24134 #close
Reported by Matt Jordan

ASTERISK-24138 #close
Reported by Matt Jordan

Patches:
forward-shenanigans.diff uploaded by Matt Jordan (License #6283)

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

Merged revisions 420794 from http://svn.asterisk.org/svn/asterisk/branches/13

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

CHANGES
apps/app_dial.c
include/asterisk/stasis_app.h
main/manager_channels.c
main/stasis_channels.c
res/ari/resource_channels.c
res/res_pjsip_pubsub.c
res/stasis/app.c
res/stasis/control.c

diff --git a/CHANGES b/CHANGES
index f584db63f52f9c5301019469d9ca4cbacdf6c785..456b5ccef588e303a3120907957745f5ec7c02d4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -280,6 +280,10 @@ AMI
  * The AMI action PJSIPShowEndpoint now includes ContactStatusDetail sections
    that give information on Asterisk's attempts to qualify the endpoint.
 
+ * The DialEnd event will now contain a Forward header if the dial is ending
+   due to the call being forwarded. The contents of the Forward header is the
+   extension in the number to which the call is being forwarded.
+
 CEL
 ------------------
  * The "bridge_technology" extra field key has been added to BRIDGE_ENTER
index 2faff8478981516af40c47e4106bc7f7df260e8b..174ff776ea47d67347011ecab1377a891c0b8eb2 100644 (file)
@@ -895,6 +895,7 @@ static void do_forward(struct chanlist *o, struct cause_args *num,
                                tech, stuff, cause);
        }
        if (!c) {
+               ast_channel_publish_dial(in, original, stuff, "BUSY");
                ast_clear_flag64(o, DIAL_STILLGOING);
                handle_cause(cause, num);
                ast_hangup(original);
@@ -995,16 +996,18 @@ static void do_forward(struct chanlist *o, struct cause_args *num,
                if (ast_call(c, stuff, 0)) {
                        ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
                                tech, stuff);
+                       ast_channel_publish_dial(in, original, stuff, "CONGESTION");
                        ast_clear_flag64(o, DIAL_STILLGOING);
                        ast_hangup(original);
                        ast_hangup(c);
                        c = o->chan = NULL;
                        num->nochan++;
                } else {
-                       ast_channel_publish_dial(in, c, stuff, NULL);
                        ast_channel_publish_dial_forward(in, original, c, NULL, "CANCEL",
                                ast_channel_call_forward(original));
 
+                       ast_channel_publish_dial(in, c, stuff, NULL);
+
                        /* Hangup the original channel now, in case we needed it */
                        ast_hangup(original);
                }
index 5a7593d67781af506a0e77773f6b704639486028..2e5901cb63556e5261348b0486f8ec3503db74a2 100644 (file)
@@ -553,15 +553,6 @@ int stasis_app_control_unmute(struct stasis_app_control *control, unsigned int d
  */
 int stasis_app_control_answer(struct stasis_app_control *control);
 
-/*!
- * \brief Get the value of a variable on the channel associated with this control.
- * \param control Control for \c res_stasis.
- * \param variable The name of the variable.
- *
- * \return The value of the variable.  The returned variable must be freed.
- */
-char *stasis_app_control_get_channel_var(struct stasis_app_control *control, const char *variable);
-
 /*!
  * \brief Set a variable on the channel associated with this control to value.
  * \param control Control for \c res_stasis.
index 9a15353f2fb32ad5e33315b62895a093cf9e0265..127084161fc0b82476a25037ad543b831cbfc982 100644 (file)
@@ -185,6 +185,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                                                </enum>
                                        </enumlist>
                                </parameter>
+                               <parameter name="Forward" required="false">
+                                       <para>If the call was forwarded, where the call was
+                                       forwarded to.</para>
+                               </parameter>
                        </syntax>
                        <see-also>
                                <ref type="application">Dial</ref>
@@ -986,6 +990,7 @@ static void channel_dial_cb(void *data, struct stasis_subscription *sub,
        struct ast_multi_channel_blob *obj = stasis_message_data(message);
        const char *dialstatus;
        const char *dialstring;
+       const char *forward;
        struct ast_channel_snapshot *caller;
        struct ast_channel_snapshot *peer;
        RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
@@ -1007,6 +1012,7 @@ static void channel_dial_cb(void *data, struct stasis_subscription *sub,
 
        dialstatus = ast_json_string_get(ast_json_object_get(ast_multi_channel_blob_get_json(obj), "dialstatus"));
        dialstring = ast_json_string_get(ast_json_object_get(ast_multi_channel_blob_get_json(obj), "dialstring"));
+       forward = ast_json_string_get(ast_json_object_get(ast_multi_channel_blob_get_json(obj), "forward"));
        if (ast_strlen_zero(dialstatus)) {
                manager_event(EVENT_FLAG_CALL, "DialBegin",
                                "%s"
@@ -1016,12 +1022,16 @@ static void channel_dial_cb(void *data, struct stasis_subscription *sub,
                                ast_str_buffer(peer_event_string),
                                S_OR(dialstring, "unknown"));
        } else {
+               int forwarded = !ast_strlen_zero(forward);
+
                manager_event(EVENT_FLAG_CALL, "DialEnd",
                                "%s"
                                "%s"
+                               "%s%s%s"
                                "DialStatus: %s\r\n",
                                caller_event_string ? ast_str_buffer(caller_event_string) : "",
                                ast_str_buffer(peer_event_string),
+                               forwarded ? "Forward: " : "", S_OR(forward, ""), forwarded ? "\r\n" : "",
                                S_OR(dialstatus, "unknown"));
        }
 
index d7fbc98ab94f7adf3fcc2a5c1b19b2b8d4210d0d..d40b5701cb64d35c5825d4c1de3e64e08c161f21 100644 (file)
@@ -288,11 +288,6 @@ static void channel_blob_dtor(void *obj)
        ast_json_unref(event->blob);
 }
 
-/*! \brief Dummy callback for receiving events */
-static void dummy_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
-{
-}
-
 void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer,
        struct ast_channel *forwarded, const char *dialstring, const char *dialstatus,
        const char *forward)
@@ -362,14 +357,7 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_cha
                return;
        }
 
-       if (forwarded) {
-               struct stasis_subscription *subscription = stasis_subscribe(ast_channel_topic(peer), dummy_event_cb, NULL);
-
-               stasis_publish(ast_channel_topic(peer), msg);
-               stasis_unsubscribe_and_join(subscription);
-       } else {
-               publish_message_for_channel_topics(msg, caller);
-       }
+       publish_message_for_channel_topics(msg, caller);
 }
 
 void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer,
index 23f7fa0f6e5b76bbb568e0c4a75ea5a139862f4b..0ac53dd73005ea6484097a20b573356bcdfd7a7b 100644 (file)
@@ -928,7 +928,8 @@ void ast_ari_channels_get_channel_var(struct ast_variable *headers,
 {
        RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
        RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
-       RAII_VAR(char *, value, NULL, ast_free);
+       RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
+       RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
 
        ast_assert(response != NULL);
 
@@ -939,15 +940,41 @@ void ast_ari_channels_get_channel_var(struct ast_variable *headers,
                return;
        }
 
-       control = find_control(response, args->channel_id);
-       if (control == NULL) {
-               /* response filled in by find_control */
+       if (ast_strlen_zero(args->channel_id)) {
+               ast_ari_response_error(
+                       response, 400, "Bad Request",
+                       "Channel ID is required");
+               return;
+       }
+
+       channel = ast_channel_get_by_name(args->channel_id);
+       if (!channel) {
+               ast_ari_response_error(
+                       response, 404, "Channel Not Found",
+                       "Provided channel was not found");
                return;
        }
 
-       value = stasis_app_control_get_channel_var(control, args->variable);
+       /* You may be tempted to lock the channel you're about to read from. You
+        * would be wrong. Some dialplan functions put the channel into
+        * autoservice, which deadlocks if the channel is already locked.
+        * ast_str_retrieve_variable() does its own locking, and the dialplan
+        * functions need to as well. We should be fine without the lock.
+        */
+
+       if (args->variable[strlen(args->variable) - 1] == ')') {
+               if (ast_func_read2(channel, args->variable, &value, 0)) {
+                       ast_ari_response_alloc_failed(response);
+                       return;
+               }
+       } else {
+               if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
+                       ast_ari_response_alloc_failed(response);
+                       return;
+               }
+       }
 
-       if (!(json = ast_json_pack("{s: s}", "value", S_OR(value, "")))) {
+       if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
                ast_ari_response_alloc_failed(response);
                return;
        }
index f9b64f85fe67d29f57799d50844fd093ab493da1..90be60d4e3f7ec95826fcfdcdd6d235a36c2da0b 100644 (file)
@@ -2032,10 +2032,13 @@ int ast_sip_subscription_notify(struct ast_sip_subscription *sub, void *notify_d
        if (sub->tree->notification_batch_interval) {
                return schedule_notification(sub->tree);
        } else {
+               int res;
                /* See the note in pubsub_on_rx_refresh() for why sub->tree is refbumped here */
                ao2_ref(sub->tree, +1);
-               return send_notify(sub->tree, 0);
+               res = send_notify(sub->tree, 0);
                ao2_ref(sub->tree, -1);
+               
+               return res;
        }
 }
 
index 7459696152934b5f54cd893bfc2f632d9f31da62..245936734bc598ec41a0925e90302929bfb8a66a 100644 (file)
@@ -1073,9 +1073,7 @@ static int unsubscribe(struct stasis_app *app, const char *kind, const char *id,
 
        forwards = ao2_find(app->forwards, id, OBJ_SEARCH_KEY | OBJ_NOLOCK);
        if (!forwards) {
-               ast_log(LOG_WARNING,
-                       "App '%s' not subscribed to %s '%s'\n",
-                       app->name, kind, id);
+               ast_debug(3, "App '%s' not subscribed to %s '%s'\n", app->name, kind, id);
                return -1;
        }
        forwards->interested--;
index 0a9669d3bc82cd77caad9b21f7011e38dba1c8e9..e53d93c06a2186aaaaa9f77ecfe510653ee7e689 100644 (file)
@@ -565,34 +565,6 @@ int stasis_app_control_unmute(struct stasis_app_control *control, unsigned int d
        return 0;
 }
 
-char *stasis_app_control_get_channel_var(struct stasis_app_control *control, const char *variable)
-{
-       RAII_VAR(struct ast_str *, tmp, ast_str_create(32), ast_free);
-
-       /* You may be tempted to lock the channel you're about to read from. You
-        * would be wrong. Some dialplan functions put the channel into
-        * autoservice, which deadlocks if the channel is already locked.
-        * ast_str_retrieve_variable() does its own locking, and the dialplan
-        * functions need to as well. We should be fine without the lock.
-        */
-
-       if (!tmp) {
-               return NULL;
-       }
-
-       if (variable[strlen(variable) - 1] == ')') {
-               if (ast_func_read2(control->channel, variable, &tmp, 0)) {
-                       return NULL;
-               }
-       } else {
-               if (!ast_str_retrieve_variable(&tmp, 0, control->channel, NULL, variable)) {
-                       return NULL;
-               }
-       }
-
-       return ast_strdup(ast_str_buffer(tmp));
-}
-
 int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
 {
        return pbx_builtin_setvar_helper(control->channel, variable, value);