res_pjsip_refer.c: Delay sending the initial SIP Notify with frag 100
authorKevin Harwell <kharwell@digium.com>
Wed, 2 Mar 2016 00:08:52 +0000 (18:08 -0600)
committerKevin Harwell <kharwell@digium.com>
Thu, 3 Mar 2016 18:09:11 +0000 (12:09 -0600)
During the transfer process, some phones (okay it was the Jitsi softphone,
but maybe others are out there) send a "bye" immediately after receiving a
SIP Notify. When a "bye" is received early for some types of transfers the
transferer channel may no longer be available during late stage transfer
processing.

For instance, during an attended transfer involving stasis bridging at one
point the created local channel looks for an associated swap channel in
order to retrieve the stasis application name. If the transferer has hung
up then the local channel will fail to find it. The local channel then has
no way to know which stasis app to enter, so it fails and hangs up as well.
Thus the transfer does not complete as expected.

This patch delays the sending of the initial notify in order to give the
transfer process enough time to gather the necessary data for a successful
transfer.

ASTERISK-25771

Change-Id: I09cfc9a5d6ed4c007bc70625e0972b470393bf16

res/res_pjsip_refer.c

index f89f901..fbc3eb3 100644 (file)
@@ -59,6 +59,8 @@ struct refer_progress {
        struct transfer_channel_data *transfer_data;
        /*! \brief Uniqueid of transferee channel */
        char *transferee;
+       /*! \brief Non-zero if the 100 notify has been sent */
+       int sent_100;
 };
 
 /*! \brief REFER Progress notification structure */
@@ -133,6 +135,18 @@ static int refer_progress_notify(void *data)
                notification->progress->sub = NULL;
        }
 
+       /* Send a deferred initial 100 Trying SIP frag NOTIFY if we haven't already. */
+       if (!notification->progress->sent_100) {
+               notification->progress->sent_100 = 1;
+               if (notification->response != 100) {
+                       ast_debug(3, "Sending initial 100 Trying NOTIFY for progress monitor '%p'\n",
+                               notification->progress);
+                       if (pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_ACTIVE, 100, NULL, &tdata) == PJ_SUCCESS) {
+                               pjsip_xfer_send_request(sub, tdata);
+                       }
+               }
+       }
+
        ast_debug(3, "Sending NOTIFY with response '%d' and state '%u' on subscription '%p' and progress monitor '%p'\n",
                notification->response, notification->state, sub, notification->progress);
 
@@ -340,7 +354,6 @@ static int refer_progress_alloc(struct ast_sip_session *session, pjsip_rx_data *
        const pj_str_t str_refer_sub = { "Refer-Sub", 9 };
        pjsip_generic_string_hdr *refer_sub = NULL;
        const pj_str_t str_true = { "true", 4 };
-       pjsip_tx_data *tdata;
        pjsip_hdr hdr_list;
        char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
 
@@ -392,12 +405,6 @@ static int refer_progress_alloc(struct ast_sip_session *session, pjsip_rx_data *
        ast_debug(3, "Accepting REFER request for progress monitor '%p'\n", *progress);
        pjsip_xfer_accept((*progress)->sub, rdata, 202, &hdr_list);
 
-       /* Send initial NOTIFY Request */
-       ast_debug(3, "Sending initial 100 Trying NOTIFY for progress monitor '%p'\n", *progress);
-       if (pjsip_xfer_notify((*progress)->sub, PJSIP_EVSUB_STATE_ACTIVE, 100, NULL, &tdata) == PJ_SUCCESS) {
-               pjsip_xfer_send_request((*progress)->sub, tdata);
-       }
-
        return 0;
 
 error: