Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c (revision 219719)
+++ channels/chan_sip.c (working copy)
@@ -967,6 +967,10 @@
ast_group_t pickupgroup; /*!< Pickup group */
int lastinvite; /*!< Last Cseq of invite */
struct ast_flags flags[2]; /*!< SIP_ flags */
+
+ /* boolean or small integers that don't belong in flags */
+ char answered_elsewhere; /*!< This call is cancelled due to answer on another channel */
+
int timer_t1; /*!< SIP timer T1, ms rtt */
unsigned int sipoptions; /*!< Supported SIP options on the other end */
struct ast_codec_pref prefs; /*!< codec prefs */
@@ -3658,6 +3662,13 @@
if (p->owner)
p->hangupcause = p->owner->hangupcause;
+ if (ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) {
+ if(option_debug)
+ ast_log(LOG_DEBUG, "This call was answered elsewhere\n");
+ append_history(p, "Cancel", "Call answered elsewhere");
+ p->answered_elsewhere = TRUE;
+ }
+
if (ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
if (option_debug && sipdebug)
@@ -8257,6 +8268,10 @@
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\"");
+
add_header_contentLength(&resp, 0);
return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
}
Index: apps/app_dial.c
===================================================================
--- apps/app_dial.c (revision 219719)
+++ apps/app_dial.c (working copy)
@@ -322,14 +322,17 @@
};
-static void hanguptree(struct dial_localuser *outgoing, struct ast_channel *exception)
+static void hanguptree(struct dial_localuser *outgoing, struct ast_channel *exception, int answered_elsewhere)
{
/* Hang up a tree of stuff */
struct dial_localuser *oo;
while (outgoing) {
/* Hangup any existing lines we have open */
- if (outgoing->chan && (outgoing->chan != exception))
+ if (outgoing->chan && (outgoing->chan != exception)) {
+ if (answered_elsewhere)
+ ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE);
ast_hangup(outgoing->chan);
+ }
oo = outgoing;
outgoing=outgoing->next;
free(oo);
@@ -1441,7 +1444,7 @@
/* Ah ha! Someone answered within the desired timeframe. Of course after this
we will always return with -1 so that it is hung up properly after the
conversation. */
- hanguptree(outgoing, peer);
+ hanguptree(outgoing, peer, 1);
outgoing = NULL;
/* If appropriate, log that we have a destination channel */
if (chan->cdr)
@@ -1644,7 +1647,7 @@
ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
peer->priority = chan->priority + 2;
ast_pbx_start(peer);
- hanguptree(outgoing, NULL);
+ hanguptree(outgoing, NULL, 0);
if (continue_exec)
*continue_exec = 1;
res = 0;
@@ -1818,7 +1821,7 @@
ast_indicate(chan, -1);
}
ast_rtp_early_bridge(chan, NULL);
- hanguptree(outgoing, NULL);
+ hanguptree(outgoing, NULL, 0);
pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
if (option_debug)
ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
Index: include/asterisk/channel.h
===================================================================
--- include/asterisk/channel.h (revision 219719)
+++ include/asterisk/channel.h (working copy)
@@ -517,6 +517,11 @@
AST_FLAG_BRIDGE_HANGUP_DONT = (1 << 17),
/*! This flag indicates whether the channel is in the channel list or not. */
AST_FLAG_IN_CHANNEL_LIST = (1 << 19),
+
+ AST_FLAG_ANSWERED_ELSEWHERE = (1 << 20),
+ /*! Flag to show channels that this call is hangup due to the fact that the call
+ * was indeed anwered, but in another channel */
+
};
/*! \brief ast_bridge_config flags */