Merged revisions 194484 via svnmerge from
[asterisk/asterisk.git] / channels / chan_sip.c
index 7e58f7f..4e3591e 100644 (file)
@@ -19371,7 +19371,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
        p->reqsipoptions = required_profile;
 
        /* Check if this is a loop */
-       if (ast_test_flag(&p->flags[0], SIP_OUTGOING) && p->owner && (p->owner->_state != AST_STATE_UP)) {
+       if (ast_test_flag(&p->flags[0], SIP_OUTGOING) && p->owner && (p->invitestate != INV_TERMINATED && p->invitestate != INV_CONFIRMED)) {
                /* This is a call to ourself.  Send ourselves an error code and stop
                processing immediately, as SIP really has no good mechanism for
                being able to call yourself */
@@ -19971,9 +19971,21 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                        p->invitestate = INV_PROCEEDING;
                        break;
                case AST_STATE_RINGING:
-                       transmit_response(p, "180 Ringing", req);
-                       p->invitestate = INV_PROCEEDING;
-                       break;
+                       if (reinvite && (p->invitestate == INV_TERMINATED || p->invitestate == INV_CONFIRMED)) {
+                       /* If these conditions are true, and the channel is still in the 'ringing'
+                        * state, then this likely means that we have a situation where the initial
+                        * INVITE transaction has completed *but* the channel's state has not yet been
+                        * changed to UP. The reason this could happen is if the reinvite is received
+                        * on the SIP socket prior to an application calling ast_read on this channel
+                        * to read the answer frame we earlier queued on it. In this case, the reinvite
+                        * is completely legitimate so we need to handle this the same as if the channel 
+                        * were already UP. Thus we are purposely falling through to the AST_STATE_UP case.
+                        */
+                       } else {
+                               transmit_response(p, "180 Ringing", req);
+                               p->invitestate = INV_PROCEEDING;
+                               break;
+                       }
                case AST_STATE_UP:
                        ast_debug(2, "%s: This call is UP.... \n", c->name);