Do not send a BYE when a provisional response arrives during a re-INVITE
authorMatthew Jordan <mjordan@digium.com>
Thu, 5 Jul 2012 17:03:43 +0000 (17:03 +0000)
committerMatthew Jordan <mjordan@digium.com>
Thu, 5 Jul 2012 17:03:43 +0000 (17:03 +0000)
Commits r369557 and r369579 were done to improve handling of re-INVITEs
when the UA that was supposed to receive the re-INVITE fails to respond.
A limitation of those patches occurred when a UA sent a provisional
response to the re-INVITE.  This triggered a sending of a BYE in
check_pending.  This patch tweaks the handling of the re-INVITE such that
a BYE is not sent in response to those messages.

(issue ASTERISK-19992)
Reported by: Steve Davies
Tested by: Steve Davies
patches:
  (reinvite_tweak.diff license #5012 by Steve Davies)
........

Merged revisions 369626 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 369627 from http://svn.asterisk.org/svn/asterisk/branches/10

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

channels/chan_sip.c

index 04af933..9b5f96f 100644 (file)
@@ -3912,7 +3912,7 @@ static int __sip_autodestruct(const void *data)
                        ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
                        append_history(p, "ReliableXmit", "timeout");
                        if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) {
-                               if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
+                               if (p->ongoing_reinvite || method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
                                        pvt_set_needdestroy(p, "autodestruct");
                                }
                        }
@@ -6378,8 +6378,8 @@ static int reinvite_timeout(const void *data)
 {
        struct sip_pvt *dialog = (struct sip_pvt *) data;
        struct ast_channel *owner = sip_pvt_lock_full(dialog);
-       check_pendings(dialog);
        dialog->reinviteid = -1;
+       check_pendings(dialog);
        if (owner) {
                ast_channel_unlock(owner);
                ast_channel_unref(owner);
@@ -21048,8 +21048,11 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char
 static void check_pendings(struct sip_pvt *p)
 {
        if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
-               /* if we can't BYE, then this is really a pending CANCEL */
-               if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) {
+               if (p->reinviteid > -1) {
+                       /* Outstanding p->reinviteid timeout, so wait... */
+                       return;
+               } else if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) {
+                       /* if we can't BYE, then this is really a pending CANCEL */
                        p->invitestate = INV_CANCELLED;
                        transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE);
                        /* If the cancel occurred on an initial invite, cancel the pending BYE */