]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 203116 via svnmerge from
authorRussell Bryant <russell@russellbryant.com>
Thu, 25 Jun 2009 16:07:10 +0000 (16:07 +0000)
committerRussell Bryant <russell@russellbryant.com>
Thu, 25 Jun 2009 16:07:10 +0000 (16:07 +0000)
https://origsvn.digium.com/svn/asterisk/trunk

................
  r203116 | russell | 2009-06-25 11:04:10 -0500 (Thu, 25 Jun 2009) | 18 lines

  Merged revisions 203115 via svnmerge from
  https://origsvn.digium.com/svn/asterisk/branches/1.4

  ........
    r203115 | russell | 2009-06-25 11:02:16 -0500 (Thu, 25 Jun 2009) | 11 lines

    Resolve a crash related to a T.38 reinvite race condition.

    This change resolves a crash observed locally during some T.38 testing.
    A call was set up using a call file, and when the T.38 reinvite came in,
    the channel state was still AST_STATE_DOWN.  The reason is explained by
    a comment in the code that previously lived in the handling of
    AST_STATE_RINGING.  This change modifies the logic to handle the same
    race condition for any channel state that is not UP.

    (closes ABE-1895)
  ........
................

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

channels/chan_sip.c

index b89db1818b5209210d41ae39be49583a30adb2f6..601f2ebdf0dcb6690a1b8833fa0e136c1aae5bd2 100644 (file)
@@ -18635,7 +18635,23 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
 
 
        if (c) {        /* We have a call  -either a new call or an old one (RE-INVITE) */
-               switch(c->_state) {
+               enum ast_channel_state c_state = c->_state;
+
+               if (c_state != AST_STATE_UP && 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.
+                        */
+                       c_state = AST_STATE_UP;
+               }
+
+               switch(c_state) {
                case AST_STATE_DOWN:
                        ast_debug(2, "%s: New call is still down.... Trying... \n", c->name);
                        transmit_response(p, "100 Trying", req);
@@ -18697,21 +18713,9 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                        p->invitestate = INV_PROCEEDING;
                        break;
                case AST_STATE_RINGING:
-                       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;
-                       }
+                       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);