summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2014-12-22 15:40:06 +0000
committerMatthew Jordan <mjordan@digium.com>2014-12-22 15:40:06 +0000
commit9735a13429ea8a03c99e963fd5d4044b909d1dde (patch)
tree44a09b4e8064db497ce656f8fb5fca01dc3ebb19
parentfc79cf6428213191023eaed6ab25e89dbfde5564 (diff)
chan_sip: Send CANCEL via original INVITE destination even after UPDATE request
Given the following scenario: * Three SIP phones (A, B, C), all communicating via a proxy with Asterisk * A call is established between A and B. B performs a SIP attended transfer of A to C. B sets the call on hold (A is hearing MOH) and dials the extension of C. While phone C is ringing, B transfers the call (that is, what we typically call a 'blond transfer'). * When the transfer completes, A hears the ringing of phone C, while B is idle. In the SIP messaging for the above scenario, a REFER request is sent to transfer the call. When "sendrpid=yes" is set in sip.conf, Asterisk may send an UPDATE request to phone C to update party information. This update is sent directly to phone C, not through the intervening proxy. This has the unfortunate side effect of providing route information, which is then set on the sip_pvt structure for C. If someone (e.g. B) is trying to get the call back (through a directed pickup), Asterisk will send a CANCEL request to C. However, since we have now updated the route set, the CANCEL request will be sent directly to C and not through the proxy. The phone ignores this CANCEL according to RFC3261 (Section 9.1). This patch updates reqprep such that the route is not updated if an UPDATE request is being sent while the INVITE state is INV_PROCEEDING or INV_EARLY_MEDIA. This ensures that a subsequent CANCEL request is still sent to the correct location. Review: https://reviewboard.asterisk.org/r/4279 ASTERISK-24628 #close Reported by: Karsten Wemheuer patches: issue.patch uploaded by Karsten Wemheuer (License 5930) ........ Merged revisions 429982 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@429983 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_sip.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 8cd4eb54e..af115d40f 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -11976,13 +11976,15 @@ 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 on an ACK for a non-2xx
+ * Use the learned route set unless this is a CANCEL or 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.
+ * Send UPDATE to the same destination as CANCEL, if call is not in final state.
*/
if (!sip_route_empty(&p->route) &&
!(sipmethod == SIP_CANCEL ||
- (sipmethod == SIP_ACK && (p->invitestate == INV_COMPLETED || p->invitestate == INV_CANCELLED)))) {
+ (sipmethod == SIP_ACK && (p->invitestate == INV_COMPLETED || p->invitestate == INV_CANCELLED)) ||
+ (sipmethod == SIP_UPDATE && (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA)))) {
if (p->socket.type != AST_TRANSPORT_UDP && p->socket.tcptls_session) {
/* For TCP/TLS sockets that are connected we won't need
* to do any hostname/IP lookups */