summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2012-02-23 15:49:13 +0000
committerMark Michelson <mmichelson@digium.com>2012-02-23 15:49:13 +0000
commitc078a1819cff61e8358deb4def8f9f488b592517 (patch)
tree932f374fbbf854f02b303c239ce02fc9e91fe8c7
parent9a49bd6dc03da8f4fac534209fcf04fc14de7991 (diff)
Fix ACK routing for non-2xx responses.
When we send an ACK for a 2xx response to an INVITE, we are supposed to use the learned route set. However, when we receive a non-2xx final response to an INVITE, we are supposed to send the ACK to the same place we initially sent the INVITE. We had been doing this up until the changes went in that would build a route set from provisional responses. That introduced a regression where we would use the learned route set under all circumstances. With this change, we now will set the destination of our ACK based on the invitestate. If it is INV_COMPLETED then that means that we have received a non-2xx final response (INV_TERMINATED indicates a 2xx response was received). If it is INV_CANCELLED, then that means the call is being canceled, which means that we should be ACKing a 487 response. The other change introduced here is setting the invitestate to INV_CONFIRMED when we send an ACK *after* the reqprep instead of before. This way, we can tell in reqprep more easily what the invitestate is prior to sending the ACK. (closes issue ASTERISK-19389) reported by Karsten Wemheuer patches: ASTERISK-19389v2.patch uploaded by Mark Michelson (license #5049) (with some slight modifications prior to commit) ........ Merged revisions 356475 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 356476 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@356477 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_sip.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 92f3cbfc5..2a4f8b31d 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -10666,10 +10666,14 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, ui
add_header(req, "Via", p->via);
/*
- * Use the learned route set unless this is a CANCEL. For a CANCEL
- * we have to send to the same destination as the original INVITE.
+ * Use the learned route set unless this is a CANCEL on an ACK for a non-2xx
+ * final response. For a CANCEL or ACK, we have to send to the same destination
+ * as the original INVITE.
*/
- if (p->route && sipmethod != SIP_CANCEL) {
+ if (sipmethod == SIP_CANCEL ||
+ (sipmethod == SIP_ACK && (p->invitestate == INV_COMPLETED || p->invitestate == INV_CANCELLED))) {
+ set_destination(p, ast_strdupa(p->uri));
+ } else if (p->route) {
set_destination(p, p->route->hop);
add_route(req, is_strict ? p->route->next : p->route);
}
@@ -14055,15 +14059,15 @@ static int transmit_request(struct sip_pvt *p, int sipmethod, uint32_t seqno, en
{
struct sip_request resp;
- if (sipmethod == SIP_ACK) {
- p->invitestate = INV_CONFIRMED;
- }
-
reqprep(&resp, p, sipmethod, seqno, newbranch);
if (sipmethod == SIP_CANCEL && p->answered_elsewhere) {
add_header(&resp, "Reason", "SIP;cause=200;text=\"Call completed elsewhere\"");
}
+ if (sipmethod == SIP_ACK) {
+ p->invitestate = INV_CONFIRMED;
+ }
+
return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
}