]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix pedantic mode of chan_sip to only check the
authorMark Michelson <mmichelson@digium.com>
Mon, 8 Sep 2008 21:10:10 +0000 (21:10 +0000)
committerMark Michelson <mmichelson@digium.com>
Mon, 8 Sep 2008 21:10:10 +0000 (21:10 +0000)
remote tag of an endpoint once a dialog has
been confirmed. Up until that point, it is possible
and legal for the far-end to send provisional
responses with a different To: tag each time. With
this patch applied, these provisional messages
will not cause a matching problem.

(closes issue #11536)
Reported by: ibc
Patches:
      11536v2.patch uploaded by putnopvut (license 60)

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

channels/chan_sip.c

index 0dbef7744323e99c74f9a05991f37eb659d84046..9b185a0715a5b0376531506669e10b309edc5d95 100644 (file)
@@ -796,6 +796,7 @@ struct sip_auth {
 #define SIP_PAGE2_BUGGY_MWI            (1 << 26)       /*!< 26: Buggy CISCO MWI fix */
 #define SIP_PAGE2_OUTGOING_CALL         (1 << 27)       /*!< 27: Is this an outgoing call? */
 #define SIP_PAGE2_UDPTL_DESTINATION     (1 << 28)       /*!< 28: Use source IP of RTP as destination if NAT is enabled */
+#define SIP_PAGE2_DIALOG_ESTABLISHED    (1 << 29)       /*!< 29: Has a dialog been established? */
 
 #define SIP_PAGE2_FLAGS_TO_COPY \
        (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | \
@@ -3700,8 +3701,10 @@ static int sip_answer(struct ast_channel *ast)
                        if (option_debug > 1)
                                ast_log(LOG_DEBUG,"T38State change to %d on channel %s\n", p->t38.state, ast->name);
                        res = transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
+                       ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                } else {
                        res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
+                       ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                }
        }
        ast_mutex_unlock(&p->lock);
@@ -4626,9 +4629,12 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
                        continue;
                if (req->method == SIP_REGISTER)
                        found = (!strcmp(p->callid, callid));
-               else 
-                       found = (!strcmp(p->callid, callid) && 
-                       (!pedanticsipchecking || ast_strlen_zero(tag) || ast_strlen_zero(p->theirtag) || !strcmp(p->theirtag, tag))) ;
+               else {
+                       found = !strcmp(p->callid, callid);
+                       if (pedanticsipchecking && found) {
+                               found = ast_strlen_zero(tag) || ast_strlen_zero(p->theirtag) || !ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED) || !strcmp(p->theirtag, tag);
+                       }
+               }
 
                if (option_debug > 4)
                        ast_log(LOG_DEBUG, "= %s Their Call ID: %s Their Tag %s Our tag: %s\n", found ? "Found" : "No match", p->callid, p->theirtag, p->tag);
@@ -12349,6 +12355,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
                }
                /* If I understand this right, the branch is different for a non-200 ACK only */
                p->invitestate = INV_TERMINATED;
+               ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE);
                check_pendings(p);
                break;
@@ -12841,8 +12848,11 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
                                }
                        } else if (sipmethod == SIP_REGISTER) 
                                res = handle_response_register(p, resp, rest, req, ignore, seqno);
-                       else if (sipmethod == SIP_BYE)          /* Ok, we're ready to go */
-                               ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 
+                       else if (sipmethod == SIP_BYE) {                /* Ok, we're ready to go */
+                               ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+                               ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+                       } else if (sipmethod == SIP_SUBSCRIBE)
+                               ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                        break;
                case 202:   /* Transfer accepted */
                        if (sipmethod == SIP_REFER) 
@@ -14531,6 +14541,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                                        }
                                                } else {
                                                        /* The other side is already setup for T.38 most likely so we need to acknowledge this too */
+                                                       ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                                                        transmit_response_with_t38_sdp(p, "200 OK", req, XMIT_CRITICAL);
                                                        p->t38.state = T38_ENABLED;
                                                        if (option_debug)
@@ -14551,6 +14562,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                        }
                                } else {
                                        /* we are not bridged in a call */
+                                       ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                                        transmit_response_with_t38_sdp(p, "200 OK", req, XMIT_CRITICAL);
                                        p->t38.state = T38_ENABLED;
                                        if (option_debug)
@@ -14580,9 +14592,11 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                        }
                                } 
                                /* Respond to normal re-invite */
-                               if (sendok)
+                               if (sendok) {
                                        /* If this is not a re-invite or something to ignore - it's critical */
+                                       ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                                        transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_CRITICAL)));
+                               }
                        }
                        p->invitestate = INV_TERMINATED;
                        break;
@@ -15225,6 +15239,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
                if (option_debug > 2)
                        ast_log(LOG_DEBUG, "Received bye, no owner, selfdestruct soon.\n");
        }
+       ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
        transmit_response(p, "200 OK", req);
 
        return 1;
@@ -15483,6 +15498,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
                        sip_scheddestroy(p, (p->expiry + 10) * 1000);   /* Set timer for destruction of call at expiration */
 
                if (p->subscribed == MWI_NOTIFICATION) {
+                       ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                        transmit_response(p, "200 OK", req);
                        if (p->relatedpeer) {   /* Send first notification */
                                ASTOBJ_WRLOCK(p->relatedpeer);
@@ -15499,7 +15515,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
                                ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);    
                                return 0;
                        }
-
+                       ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                        transmit_response(p, "200 OK", req);
                        transmit_state_notify(p, firststate, 1, FALSE); /* Send first notification */
                        append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate));