mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-29 07:24:55 +00:00
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/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@352014 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -3860,6 +3860,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);
|
||||||
@@ -20262,15 +20263,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", p->owner->name);
|
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", p->owner->name);
|
||||||
|
/*
|
||||||
|
* 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)) {
|
||||||
@@ -20295,6 +20303,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20889,6 +20900,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 */
|
||||||
@@ -20904,8 +20918,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) {
|
||||||
@@ -20920,8 +20932,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)
|
||||||
@@ -20997,8 +21007,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 */
|
||||||
@@ -21155,24 +21163,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");
|
||||||
}
|
}
|
||||||
@@ -21194,8 +21184,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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user