summaryrefslogtreecommitdiff
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
authorTerry Wilson <twilson@digium.com>2012-01-16 21:50:10 +0000
committerTerry Wilson <twilson@digium.com>2012-01-16 21:50:10 +0000
commitaacc158072bbbc609363404cc4689284a1b6ce8f (patch)
tree93f45b1c934ba300c37ce009dd4a2a45d27c291c /channels/chan_sip.c
parentfb5924ebe8104a9a5d95d6d1f2f6df41874ab93b (diff)
Ensure ACK retransmit & hangup on non-200 response to INVITE
When handling a non-2xx final response on an INVITE transaction, we have to keep the transaction around after we send an ACK in case we receive a retransmission of the response so we can re-transmit the ACK, but also tear down the ast_channel as soon as we transmit the ACK. Before this patch, we could fail at both of these things. Calling sip_alreadygone/needdestroy prevented us from keeping the transaction up and retransmitting the ACK, and queueing CONGESTION was not sufficient to cause the channel to be torn down when originating calls via the CLI, for example. This patch queues a hangup with CONGESTION instead of just queueing CONGESTION for these responses and removes the sip_alreadygone and sip_needdestroy calls from handle_response_invite on non-2xx responses. It relies on the hangup calling sip_scheddestroy. For more information, see section 17.1.1.1 of RFC 3261. (closes issue ASTERISK-17717) Review: https://reviewboard.asterisk.org/r/1672/ ........ Merged revisions 351130 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 351131 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@351143 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c34
1 files changed, 11 insertions, 23 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index f26d7d5e0..548199fe0 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -20400,7 +20400,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
*/
if (!reinvite) {
set_pvt_allowed_methods(p, req);
- }
+ }
switch (resp) {
case 100: /* Trying */
@@ -20708,19 +20708,16 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", sip_get_header(&p->initreq, "From"));
if (!req->ignore && p->owner) {
ast_set_hangupsource(p->owner, ast_channel_name(p->owner), 0);
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION);
}
- pvt_set_needdestroy(p, "received 403 response");
- sip_alreadygone(p);
break;
case 404: /* Not found */
xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
if (p->owner && !req->ignore) {
ast_set_hangupsource(p->owner, ast_channel_name(p->owner), 0);
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION);
}
- sip_alreadygone(p);
break;
case 408: /* Request timeout */
@@ -20729,9 +20726,8 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid);
xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
if (p->owner) {
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION);
}
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
break;
case 422: /* Session-Timers: Session interval too small */
@@ -20744,13 +20740,11 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
append_history(p, "Identity", "SIP identity is required. Not supported by Asterisk.");
ast_log(LOG_WARNING, "SIP identity required by proxy. SIP dialog '%s'. Giving up.\n", p->callid);
- if (p->owner) {
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ if (p->owner && !req->ignore) {
+ ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION);
}
break;
-
-
case 487: /* Cancelled transaction */
/* We have sent CANCEL on an outbound INVITE
This transaction is already scheduled to be killed by sip_hangup().
@@ -20762,9 +20756,8 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
} else if (!req->ignore) {
update_call_counter(p, DEC_CALL_LIMIT);
append_history(p, "Hangup", "Got 487 on CANCEL request from us on call without owner. Killing this dialog.");
- pvt_set_needdestroy(p, "received 487 response");
- sip_alreadygone(p);
}
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
break;
case 415: /* Unsupported media type */
case 488: /* Not acceptable here */
@@ -20781,12 +20774,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
} else {
/* We can't set up this call, so give up */
if (p->owner && !req->ignore) {
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
- }
- pvt_set_needdestroy(p, "received 488 response");
- /* If there's no dialog to end, then mark p as already gone */
- if (!reinvite) {
- sip_alreadygone(p);
+ ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION);
}
}
break;
@@ -20794,8 +20782,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
if (p->owner && !req->ignore) {
if (p->owner->_state != AST_STATE_UP) {
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
- pvt_set_needdestroy(p, "received 491 response");
+ ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION);
} else {
/* This is a re-invite that failed. */
/* Reset the flag after a while
@@ -20819,7 +20806,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
case 501: /* Not implemented */
xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
if (p->owner) {
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION);
}
break;
}
@@ -21608,6 +21595,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
}
break;
+ case 428:
case 422: /* Session-Timers: Session Interval Too Small */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, seqno);