]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 369558 via svnmerge from
authorAutomerge script <automerge@asterisk.org>
Tue, 3 Jul 2012 15:25:48 +0000 (15:25 +0000)
committerAutomerge script <automerge@asterisk.org>
Tue, 3 Jul 2012 15:25:48 +0000 (15:25 +0000)
file:///srv/subversion/repos/asterisk/branches/10

................
  r369558 | twilson | 2012-07-03 09:34:22 -0500 (Tue, 03 Jul 2012) | 14 lines

  Better handle re-INVITEs with provisional but no final repsonses

  A previous attempt at fixing this issue had negative side effects related
  to attended transfers which this patch should resolve. Many thanks to
  Steve Davies for all of the good suggestions and testing.

  (closes issue ASTERISK-19992)
  Reported by: Steve Davies
  Tested by: Steve Davies, Terry Wilson
  Review: https://reviewboard.asterisk.org/r/2009/
  ........

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

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10-digiumphones@369578 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
channels/sip/include/sip.h

index bab75e6289334a1178f8733dbc5f87d461a75a45..fbe22a13091711711a75120548b4112c2ff33fa3 100644 (file)
@@ -6295,6 +6295,21 @@ const char *hangup_cause2sip(int cause)
        return 0;
 }
 
+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;
+       if (owner) {
+               ast_channel_unlock(owner);
+               ast_channel_unref(owner);
+       }
+       ao2_unlock(dialog);
+       dialog_unref(dialog, "unref for reinvite timeout");
+       return 0;
+}
+
 /*! \brief  sip_hangup: Hangup SIP call
  * Part of PBX interface, called from ast_hangup */
 static int sip_hangup(struct ast_channel *ast)
@@ -6421,7 +6436,7 @@ static int sip_hangup(struct ast_channel *ast)
                                stop_session_timer(p);
                        }
 
-                       if (!p->pendinginvite || p->ongoing_reinvite) {
+                       if (!p->pendinginvite) {
                                struct ast_channel *bridge = ast_bridged_channel(oldowner);
                                char quality_buf[AST_MAX_USER_FIELD], *quality;
 
@@ -6483,8 +6498,16 @@ static int sip_hangup(struct ast_channel *ast)
                                ast_set_flag(&p->flags[0], SIP_PENDINGBYE);     
                                ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 
                                AST_SCHED_DEL_UNREF(sched, p->waitid, dialog_unref(p, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
-                               if (sip_cancel_destroy(p))
+                               if (sip_cancel_destroy(p)) {
                                        ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
+                               }
+                               /* If we have an ongoing reinvite, there is a chance that we have gotten a provisional
+                                * response, but something weird has happened and we will never receive a final response.
+                                * So, just in case, check for pending actions after a bit of time to trigger the pending
+                                * bye that we are setting above */
+                               if (p->ongoing_reinvite && p->reinviteid < 0) {
+                                       p->reinviteid = ast_sched_add(sched, 32 * p->timer_t1, reinvite_timeout, dialog_ref(p, "ref for reinvite_timeout"));
+                               }
                        }
                }
        }
@@ -7867,6 +7890,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
        p->method = intended_method;
        p->initid = -1;
        p->waitid = -1;
+       p->reinviteid = -1;
        p->autokillid = -1;
        p->request_queue_sched_id = -1;
        p->provisional_keepalive_sched_id = -1;
@@ -20591,8 +20615,9 @@ static void check_pendings(struct sip_pvt *p)
                           INVITE, but do set an autodestruct just in case we never get it. */
                } else {
                        /* We have a pending outbound invite, don't send something
-                               new in-transaction */
-                       if (p->pendinginvite)
+                        * new in-transaction, unless it is a pending reinvite, then
+                        * by the time we are called here, we should probably just hang up. */
+                       if (p->pendinginvite && !p->ongoing_reinvite)
                                return;
 
                        if (p->owner) {
@@ -20837,12 +20862,19 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
        if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA ))
                p->invitestate = INV_COMPLETED;
        
+       if ((resp >= 200 && reinvite)) {
+               p->ongoing_reinvite = 0;
+               if (p->reinviteid > -1) {
+                       AST_SCHED_DEL_UNREF(sched, p->reinviteid, dialog_unref(p, "unref dialog for reinvite timeout because of a final response"));
+                       /* Since we got a final response to the reinvite, but were relying on the reinvite_timeout
+                        * function to clean up after the reinvite, we need to make sure and call check_pendings */
+                       check_pendings(p);
+               }
+       }
+
        /* Final response, clear out pending invite */
        if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) {
                p->pendinginvite = 0;
-               if (reinvite) {
-                       p->ongoing_reinvite = 0;
-               }
        }
 
        /* If this is a response to our initial INVITE, we need to set what we can use
index 6a0f6cdb292f1404260233991f6e63255892c413..271fd997b178770ddaaea15b2945a3dca164c4e2 100644 (file)
@@ -1114,6 +1114,7 @@ struct sip_pvt {
 
        int initid;                         /*!< Auto-congest ID if appropriate (scheduler) */
        int waitid;                         /*!< Wait ID for scheduler after 491 or other delays */
+       int reinviteid;                     /*!< Reinvite in case of provisional, but no final response */
        int autokillid;                     /*!< Auto-kill ID (scheduler) */
        int t38id;                          /*!< T.38 Response ID */
        struct sip_refer *refer;            /*!< REFER: SIP transfer data structure */