Skip to content
Snippets Groups Projects
Commit ab8ba431 authored by Mark Michelson's avatar Mark Michelson
Browse files

Fix RTP reference leak.

If a blind transfer were initiated using a REFER without a prior
reINVITE to place the call on hold, AND if Asterisk were sending
RTCP reports, then there was a reference for the RTP instance
of the transferer.

This fixes the issue by merging two similar but slightly conflicting
sections of code into a single area. It also adds a stop_media_flows()
call in the case that the transferer's UA never sends a BYE to us
like it is supposed to.

(issue ASTERISK-19192)

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

Merged revisions 352014 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 352015 from http://svn.asterisk.org/svn/asterisk/branches/10


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@352018 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent d0c76549
Branches
Tags
No related merge requests found
...@@ -3885,6 +3885,7 @@ static int __sip_autodestruct(const void *data) ...@@ -3885,6 +3885,7 @@ static int __sip_autodestruct(const void *data)
ast_channel_unref(owner); ast_channel_unref(owner);
} else if (p->refer && !p->alreadygone) { } else if (p->refer && !p->alreadygone) {
ast_debug(3, "Finally hanging up channel after transfer: %s\n", p->callid); ast_debug(3, "Finally hanging up channel after transfer: %s\n", p->callid);
stop_media_flows(p);
transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
append_history(p, "ReferBYE", "Sending BYE on transferer call leg %s", p->callid); append_history(p, "ReferBYE", "Sending BYE on transferer call leg %s", p->callid);
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
...@@ -20866,15 +20867,22 @@ static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest ...@@ -20866,15 +20867,22 @@ static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest
case 200: /* Notify accepted */ case 200: /* Notify accepted */
/* They got the notify, this is the end */ /* They got the notify, this is the end */
if (p->owner) { if (p->owner) {
if (!p->refer) { if (p->refer) {
ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", ast_channel_name(p->owner)); ast_log(LOG_NOTICE, "Got OK on REFER Notify message\n");
ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_UNSPECIFIED);
} else { } else {
ast_debug(4, "Got OK on REFER Notify message\n"); ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", ast_channel_name(p->owner));
/*
* XXX There is discrepancy on whether a hangup should be queued
* or not. This code used to be duplicated in two places, and the more
* frequently hit area had this disabled, making it the de facto
* "correct" way to go.
*
* ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_UNSPECIFIED);
*/
} }
} else { } else {
if (p->subscribed == NONE) { if (p->subscribed == NONE && !p->refer) {
ast_debug(4, "Got 200 accepted on NOTIFY\n"); ast_debug(4, "Got 200 accepted on NOTIFY %s\n", p->callid);
pvt_set_needdestroy(p, "received 200 response"); pvt_set_needdestroy(p, "received 200 response");
} }
if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
...@@ -20899,6 +20907,9 @@ static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest ...@@ -20899,6 +20907,9 @@ static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest
pvt_set_needdestroy(p, "failed to authenticate NOTIFY"); pvt_set_needdestroy(p, "failed to authenticate NOTIFY");
} }
break; break;
case 481: /* Call leg does not exist */
pvt_set_needdestroy(p, "Received 481 response for NOTIFY");
break;
} }
} }
   
...@@ -21541,6 +21552,9 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc ...@@ -21541,6 +21552,9 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
} else if (sipmethod == SIP_MESSAGE) { } else if (sipmethod == SIP_MESSAGE) {
/* More good gravy! */ /* More good gravy! */
handle_response_message(p, resp, rest, req, seqno); handle_response_message(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_NOTIFY) {
/* The gravy train continues to roll */
handle_response_notify(p, resp, rest, req, seqno);
} else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { } else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
switch(resp) { switch(resp) {
case 100: /* 100 Trying */ case 100: /* 100 Trying */
...@@ -21556,8 +21570,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc ...@@ -21556,8 +21570,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
p->authtries = 0; /* Reset authentication counter */ p->authtries = 0; /* Reset authentication counter */
if (sipmethod == SIP_INVITE) { if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, seqno); 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_REGISTER) { } else if (sipmethod == SIP_REGISTER) {
handle_response_register(p, resp, rest, req, seqno); handle_response_register(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_SUBSCRIBE) { } else if (sipmethod == SIP_SUBSCRIBE) {
...@@ -21572,8 +21584,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc ...@@ -21572,8 +21584,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
case 407: /* Proxy auth required */ case 407: /* Proxy auth required */
if (sipmethod == SIP_INVITE) if (sipmethod == SIP_INVITE)
handle_response_invite(p, resp, rest, req, seqno); 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_SUBSCRIBE) else if (sipmethod == SIP_SUBSCRIBE)
handle_response_subscribe(p, resp, rest, req, seqno); handle_response_subscribe(p, resp, rest, req, seqno);
else if (p->registry && sipmethod == SIP_REGISTER) else if (p->registry && sipmethod == SIP_REGISTER)
...@@ -21649,8 +21659,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc ...@@ -21649,8 +21659,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
handle_response_invite(p, resp, rest, req, seqno); handle_response_invite(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_SUBSCRIBE) { } else if (sipmethod == SIP_SUBSCRIBE) {
handle_response_subscribe(p, resp, rest, req, seqno); handle_response_subscribe(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_NOTIFY) {
pvt_set_needdestroy(p, "received 481 response");
} else if (sipmethod == SIP_BYE) { } else if (sipmethod == SIP_BYE) {
/* The other side has no transaction to bye, /* The other side has no transaction to bye,
just assume it's all right then */ just assume it's all right then */
...@@ -21811,24 +21819,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc ...@@ -21811,24 +21819,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
ast_debug(1, "Got 200 OK on CANCEL\n"); ast_debug(1, "Got 200 OK on CANCEL\n");
   
/* Wait for 487, then destroy */ /* Wait for 487, then destroy */
} else if (sipmethod == SIP_NOTIFY) {
/* They got the notify, this is the end */
if (p->owner) {
if (p->refer) {
ast_debug(1, "Got 200 OK on NOTIFY for transfer\n");
} else
ast_log(LOG_WARNING, "Notify answer on an owned channel?\n");
/* ast_queue_hangup(p->owner); Disabled */
} else {
if (!p->subscribed && !p->refer) {
pvt_set_needdestroy(p, "transaction completed");
}
if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
/* Ready to send the next state we have on queue */
ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
}
}
} else if (sipmethod == SIP_BYE) { } else if (sipmethod == SIP_BYE) {
pvt_set_needdestroy(p, "transaction completed"); pvt_set_needdestroy(p, "transaction completed");
} }
...@@ -21850,8 +21840,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc ...@@ -21850,8 +21840,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
handle_response_invite(p, resp, rest, req, seqno); handle_response_invite(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_BYE) { } else if (sipmethod == SIP_BYE) {
pvt_set_needdestroy(p, "received 481 response"); pvt_set_needdestroy(p, "received 481 response");
} else if (sipmethod == SIP_NOTIFY) {
pvt_set_needdestroy(p, "received 481 response");
} else if (sipdebug) { } else if (sipdebug) {
ast_debug(1, "Remote host can't match request %s to call '%s'. Giving up\n", sip_methods[sipmethod].text, p->callid); ast_debug(1, "Remote host can't match request %s to call '%s'. Giving up\n", sip_methods[sipmethod].text, p->callid);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment