]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix reference leaks involving SIP Replaces transfers
authorKinsey Moore <kmoore@digium.com>
Thu, 26 Apr 2012 13:24:11 +0000 (13:24 +0000)
committerKinsey Moore <kmoore@digium.com>
Thu, 26 Apr 2012 13:24:11 +0000 (13:24 +0000)
The reference held for SIP blind transfers using the Replaces header in an
INVITE was never freed on success and also failed to be freed in some error
conditions.  This caused a file descriptor leak since the RTP structures in use
at the time of the transfer were never freed.  This reference leak and another
relating to subscriptions in the same code path have now been corrected.

(closes issue ASTERISK-19579)

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

channels/chan_sip.c

index 77dae746d76c88328cf6c21597968422065a2cc3..cfd58ade12e27ccf20bb3e7a476164636a5311ec 100644 (file)
@@ -5808,8 +5808,12 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
        }
        if (p->udptl)
                ast_udptl_destroy(p->udptl);
-       if (p->refer)
+       if (p->refer) {
+               if (p->refer->refer_call) {
+                       p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call");
+               }
                ast_free(p->refer);
+       }
        if (p->route) {
                free_old_route(p->route);
                p->route = NULL;
@@ -22426,6 +22430,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                if (subscription->owner) {
                                        ast_channel_unlock(subscription->owner);
                                }
+                               subscription = dialog_unref(subscription, "unref dialog subscription");
                        }
                }
 
@@ -22444,7 +22449,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
 
                if (p->refer->refer_call == p) {
                        ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid);
-                       p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call");
                        transmit_response_reliable(p, "400 Bad request", req);  /* The best way to not not accept the transfer */
                        error = 1;
                }
@@ -22472,6 +22476,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                if (p->refer->refer_call->owner) {
                                        ast_channel_unlock(p->refer->refer_call->owner);
                                }
+                               p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call");
                        }
                        refer_locked = 0;
                        p->invitestate = INV_COMPLETED;