Index: asterisk-1.4.17~dfsg/include/asterisk/channel.h
===================================================================
--- asterisk-1.4.17~dfsg.orig/include/asterisk/channel.h 2008-04-11 19:26:31.000000000 +0200
+++ asterisk-1.4.17~dfsg/include/asterisk/channel.h 2008-04-11 19:28:13.000000000 +0200
@@ -493,6 +493,9 @@
/*! This flag indicates that on a masquerade, an active stream should not
* be carried over */
AST_FLAG_MASQ_NOSTREAM = (1 << 15),
+ /*! Flag to show channels that this call is hangup due to the fact that the call
+ * was indeed answerd, but in another channel */
+ AST_FLAG_ANSWERED_ELSEWHERE = (1<< 16),
};
/*! \brief ast_bridge_config flags */
Index: asterisk-1.4.17~dfsg/apps/app_dial.c
===================================================================
--- asterisk-1.4.17~dfsg.orig/apps/app_dial.c 2008-04-11 19:28:47.000000000 +0200
+++ asterisk-1.4.17~dfsg/apps/app_dial.c 2008-04-11 19:39:10.000000000 +0200
@@ -101,6 +101,8 @@
" Options:\n"
" A(x) - Play an announcement to the called party, using 'x' as the file.\n"
" C - Reset the CDR for this call.\n"
+" c - If DIAL cancels this call, always set the flag to tell the channel\n"
+" driver that the call is answered elsewhere.\n"
" d - Allow the calling user to dial a 1 digit extension while waiting for\n"
" a call to be answered. Exit to that extension if it exists in the\n"
" current context, or the context defined in the EXITCONTEXT variable,\n"
@@ -243,6 +245,7 @@
OPT_CALLEE_PARK = (1 << 25),
OPT_CALLER_PARK = (1 << 26),
OPT_IGNORE_FORWARDING = (1 << 27),
+ OPT_CANCEL_ELSEWHERE = (1 << 28),
} dial_exec_option_flags;
#define DIAL_STILLGOING (1 << 30)
@@ -265,6 +268,7 @@
AST_APP_OPTIONS(dial_exec_options, {
AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
AST_APP_OPTION('C', OPT_RESETCDR),
+ AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE),
AST_APP_OPTION('d', OPT_DTMF_EXIT),
AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
AST_APP_OPTION('f', OPT_FORCECLID),
@@ -308,14 +312,19 @@
};
-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);
@@ -1114,6 +1123,7 @@
goto out;
if (opts.flags) {
ast_copy_flags(tmp, &opts,
+ OPT_CANCEL_ELSEWHERE |
OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
@@ -1347,7 +1357,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)
@@ -1550,7 +1560,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, ast_test_flag(&opts, OPT_CANCEL_ELSEWHERE)?1:0);
if (continue_exec)
*continue_exec = 1;
res = 0;
@@ -1730,7 +1740,7 @@
ast_indicate(chan, -1);
}
ast_rtp_early_bridge(chan, NULL);
- hanguptree(outgoing, NULL);
+ hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */
pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
if (option_debug)
ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
Index: asterisk-1.4.17~dfsg/channels/chan_sip.c
===================================================================
--- asterisk-1.4.17~dfsg.orig/channels/chan_sip.c 2008-04-11 19:39:26.000000000 +0200
+++ asterisk-1.4.17~dfsg/channels/chan_sip.c 2008-04-11 19:46:50.000000000 +0200
@@ -709,6 +709,13 @@
struct sip_auth *next; /*!< Next auth structure in list */
};
+/* New set flags for DIALOG ONLY, not for peers/users etc
+ \todo - move dialog only flags here to release bits for peer/user to dialog copying
+ This gues into flags[2] in the dialog - page 3
+*/
+
+#define SIP_DIALOG_ANSWEREDELSEWHERE (1<<0)
+
/*--- Various flags for the flags field in the pvt structure */
#define SIP_ALREADYGONE (1 << 0) /*!< Whether or not we've already been destroyed by our peer */
#define SIP_NEEDDESTROY (1 << 1) /*!< if we need to be destroyed by the monitor thread */
@@ -948,7 +955,7 @@
ast_group_t pickupgroup; /*!< Pickup group */
int lastinvite; /*!< Last Cseq of invite */
int lastnoninvite; /*!< Last Cseq of non-invite */
- struct ast_flags flags[2]; /*!< SIP_ flags */
+ struct ast_flags flags[3]; /*!< SIP_ flags */
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 */
@@ -3460,6 +3467,13 @@
return 0;
}
+ if (ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "This call was answered elsewhere");
+ append_history(p, "Cancel", "Call answered elsewhere");
+ ast_set_flag(&p->flags[2], SIP_DIALOG_ANSWEREDELSEWHERE);
+ }
+
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)
@@ -7763,6 +7777,8 @@
p->invitestate = INV_CONFIRMED;
reqprep(&resp, p, sipmethod, seqno, newbranch);
+ if (sipmethod == SIP_CANCEL && ast_test_flag(&p->flags[0], SIP_DIALOG_ANSWEREDELSEWHERE))
+ 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);
}