summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2014-12-22 15:40:27 +0000
committerMatthew Jordan <mjordan@digium.com>2014-12-22 15:40:27 +0000
commit264a50c52a5aa53d68839e5753bc5dd4d513793e (patch)
treec6e6a191fa147ddaa96017db6ae56c5235d34eff /channels
parent0c38276d6e08c47bba50649e888b980df1a11f1c (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 ........ Merged revisions 429983 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@429984 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-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 4789c553f..dd3f2723f 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -11985,13 +11985,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 */