Merged revisions 281874 via svnmerge from
authorMatthew Nicholson <mnicholson@digium.com>
Wed, 11 Aug 2010 21:12:25 +0000 (21:12 +0000)
committerMatthew Nicholson <mnicholson@digium.com>
Wed, 11 Aug 2010 21:12:25 +0000 (21:12 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r281874 | mnicholson | 2010-08-11 16:11:54 -0500 (Wed, 11 Aug 2010) | 10 lines

  handle all possible responses to REFER requests

  (closes issue #17486)
  Reported by: davidw
  Patches:
        Issue17486-counterbid.diff.txt uploaded by davidw (license 780)
  Tested by: davidw

  Review: https://reviewboard.asterisk.org/r/837/
........

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

channels/chan_sip.c

index 2a656ba..07d4143 100644 (file)
@@ -19239,6 +19239,23 @@ static void handle_response_refer(struct sip_pvt *p, int resp, const char *rest,
                        ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
                }
                break;
+       default:
+               /* We should treat unrecognized 9xx as 900.  400 is actually
+                  specified as a possible response, but any 4-6xx is 
+                  theoretically possible. */
+
+               if (resp < 299) { /* 1xx cases don't get here */
+                       ast_log(LOG_WARNING, "SIP transfer to %s had unxpected 2xx response (%d), confusion is possible. \n", p->refer->refer_to, resp);
+               } else {
+                       ast_log(LOG_WARNING, "SIP transfer to %s with response (%d). \n", p->refer->refer_to, resp);
+               }
+
+               p->refer->status = REFER_FAILED;
+               pvt_set_needdestroy(p, "received failure response");
+               if (p->owner) {
+                       ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
+               }
+               break;
        }
 }
 
@@ -19555,6 +19572,8 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                   need to hang around for something more "definitive" */
                if (resp != 100)
                        handle_response_peerpoke(p, resp, req);
+       } else if (sipmethod == SIP_REFER && resp >= 200) {
+               handle_response_refer(p, resp, rest, req, seqno);
        } else if (sipmethod == SIP_PUBLISH) {
                /* SIP PUBLISH transcends this morass of doodoo and instead
                 * we just always call the response handler. Good gravy!
@@ -19591,18 +19610,12 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                                ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                        }
                        break;
-               case 202:   /* Transfer accepted */
-                       if (sipmethod == SIP_REFER)
-                               handle_response_refer(p, resp, rest, req, seqno);
-                       break;
                case 401: /* Not www-authorized on SIP method */
                case 407: /* Proxy auth required */
                        if (sipmethod == SIP_INVITE)
                                handle_response_invite(p, resp, rest, req, seqno);
                        else if (sipmethod == SIP_NOTIFY)
                                handle_response_notify(p, resp, rest, req, seqno);
-                       else if (sipmethod == SIP_REFER)
-                               handle_response_refer(p, resp, rest, req, seqno);
                        else if (sipmethod == SIP_SUBSCRIBE)
                                handle_response_subscribe(p, resp, rest, req, seqno);
                        else if (p->registry && sipmethod == SIP_REGISTER)
@@ -19675,8 +19688,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                case 481: /* Call leg does not exist */
                        if (sipmethod == SIP_INVITE) {
                                handle_response_invite(p, resp, rest, req, seqno);
-                       } else if (sipmethod == SIP_REFER) {
-                               handle_response_refer(p, resp, rest, req, seqno);
                        } else if (sipmethod == SIP_SUBSCRIBE) {
                                handle_response_subscribe(p, resp, rest, req, seqno);
                        } else if (sipmethod == SIP_BYE) {
@@ -19718,16 +19729,9 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                        }
                        if (sipmethod == SIP_INVITE)
                                handle_response_invite(p, resp, rest, req, seqno);
-                       else if (sipmethod == SIP_REFER)
-                               handle_response_refer(p, resp, rest, req, seqno);
                        else
                                ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_sockaddr_stringify(&p->sa), msg);
                        break;
-               case 603:       /* Declined transfer */
-                       if (sipmethod == SIP_REFER) {
-                               handle_response_refer(p, resp, rest, req, seqno);
-                               break;
-                       }
                        /* Fallthrough */
                default:
                        if ((resp >= 300) && (resp < 700)) {
@@ -19770,10 +19774,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                                case 410: /* Gone */
                                case 400: /* Bad Request */
                                case 500: /* Server error */
-                                       if (sipmethod == SIP_REFER) {
-                                               handle_response_refer(p, resp, rest, req, seqno);
-                                               break;
-                                       } else if (sipmethod == SIP_SUBSCRIBE) {
+                                       if (sipmethod == SIP_SUBSCRIBE) {
                                                handle_response_subscribe(p, resp, rest, req, seqno);
                                                break;
                                        }
@@ -19871,15 +19872,9 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                                ;
                        }
                        break;
-               case 202:   /* Transfer accepted */
-                       if (sipmethod == SIP_REFER)
-                               handle_response_refer(p, resp, rest, req, seqno);
-                       break;
                case 401:       /* www-auth */
                case 407:
-                       if (sipmethod == SIP_REFER)
-                               handle_response_refer(p, resp, rest, req, seqno);
-                       else if (sipmethod == SIP_INVITE)
+                       if (sipmethod == SIP_INVITE)
                                handle_response_invite(p, resp, rest, req, seqno);
                        else if (sipmethod == SIP_BYE) {
                                if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) {
@@ -19901,15 +19896,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                case 501: /* Not Implemented */
                        if (sipmethod == SIP_INVITE)
                                handle_response_invite(p, resp, rest, req, seqno);
-                       else if (sipmethod == SIP_REFER)
-                               handle_response_refer(p, resp, rest, req, seqno);
                        break;
-               case 603:       /* Declined transfer */
-                       if (sipmethod == SIP_REFER) {
-                               handle_response_refer(p, resp, rest, req, seqno);
-                               break;
-                       }
-                       /* Fallthrough */
                default:        /* Errors without handlers */
                        if ((resp >= 100) && (resp < 200)) {
                                if (sipmethod == SIP_INVITE) {  /* re-invite */