[svn-commits] kaii: branch kaii/1.8-multicall r323324 - in /team/kaii/1.8-multicall: apps/ ...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Jun 14 05:02:16 CDT 2011


Author: kaii
Date: Tue Jun 14 05:02:13 2011
New Revision: 323324

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=323324
Log:
* added option "B" to app_dial to enable multicall behaviours
 

Modified:
    team/kaii/1.8-multicall/apps/app_dial.c
    team/kaii/1.8-multicall/channels/chan_local.c
    team/kaii/1.8-multicall/include/asterisk/channel.h
    team/kaii/1.8-multicall/main/channel.c

Modified: team/kaii/1.8-multicall/apps/app_dial.c
URL: http://svnview.digium.com/svn/asterisk/team/kaii/1.8-multicall/apps/app_dial.c?view=diff&rev=323324&r1=323323&r2=323324
==============================================================================
--- team/kaii/1.8-multicall/apps/app_dial.c (original)
+++ team/kaii/1.8-multicall/apps/app_dial.c Tue Jun 14 05:02:13 2011
@@ -105,6 +105,11 @@
 					announcement) are completed.  This option can be used to answer the calling
 					channel before doing anything on the called channel. You will rarely need to use
 					this option, the default behavior is adequate in most cases.</para>
+				</option>
+				<option name="B">
+					<para>Enable "converged" behaviour for dialed interfaces. When one of the called interfaces
+ 					returns busy, immediately return busy to the caller and stop ringing all other interfaces.
+ 					When one of the called interfaces forwards the call, stop ringing all other interfaces.</para>
 				</option>
 				<option name="C">
 					<para>Reset the call detail record (CDR) for this call.</para>
@@ -563,6 +568,7 @@
 #define OPT_CANCEL_TIMEOUT   ((uint64_t)1 << 37)
 #define OPT_FORCE_CID_TAG    ((uint64_t)1 << 38)
 #define OPT_FORCE_CID_PRES   ((uint64_t)1 << 39)
+#define OPT_CONVERGED        ((uint64_t)1 << 40)
 
 enum {
 	OPT_ARG_ANNOUNCE = 0,
@@ -589,6 +595,7 @@
 AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
 	AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
 	AST_APP_OPTION('a', OPT_CALLER_ANSWER),
+	AST_APP_OPTION('B', OPT_CONVERGED),
 	AST_APP_OPTION('C', OPT_RESETCDR),
 	AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE),
 	AST_APP_OPTION('d', OPT_DTMF_EXIT),
@@ -798,7 +805,8 @@
  */
 static void do_forward(struct chanlist *o,
 	struct cause_args *num, struct ast_flags64 *peerflags, int single, int *to,
-	struct ast_party_id *forced_clid, struct ast_party_id *stored_clid)
+	struct ast_party_id *forced_clid, struct ast_party_id *stored_clid,
+	char *opt_args[], struct chanlist *outgoing)
 {
 	char tmpchan[256];
 	struct ast_channel *original = o->chan;
@@ -808,6 +816,13 @@
 	char *tech;
 	int cause;
 	struct ast_party_caller caller;
+
+	/* XXX KH get interface name - fix for issue #17613 */
+	char interface[256];
+	ast_copy_string(tmpchan, c->name, sizeof(tmpchan));
+	stuff = strchr(tmpchan, '-');
+	*stuff++ = '\0';
+	ast_copy_string(interface, tmpchan, sizeof(interface));
 
 	ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
 	if ((stuff = strchr(tmpchan, '/'))) {
@@ -829,30 +844,98 @@
 	ast_cel_report_event(in, AST_CEL_FORWARD, NULL, c->call_forward, NULL);
 
 	/* Before processing channel, go ahead and check for forwarding */
-	ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
+	//ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
+
 	/* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
 	if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
 		ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
 		c = o->chan = NULL;
 		cause = AST_CAUSE_BUSY;
 	} else {
-		/* Setup parameters */
-		c = o->chan = ast_request(tech, in->nativeformats, in, stuff, &cause);
-		if (c) {
-			if (single)
-				ast_channel_make_compatible(o->chan, in);
-			ast_channel_inherit_variables(in, o->chan);
-			ast_channel_datastore_inherit(in, o->chan);
-			/* When a call is forwarded, we don't want to track new interfaces
-			 * dialed for CC purposes. Setting the done flag will ensure that
-			 * any Dial operations that happen later won't record CC interfaces.
-			 */
-			ast_ignore_cc(o->chan);
-			ast_log(LOG_NOTICE, "Not accepting call completion offers from call-forward recipient %s\n", o->chan->name);
-		} else
-			ast_log(LOG_NOTICE,
-				"Forwarding failed to create channel to dial '%s/%s' (cause = %d)\n",
-				tech, stuff, cause);
+		/* XXX KH remove from list of dialed interfaces when forwarder was already ringing - fix for issue #17613 */
+		if(c->_state == AST_STATE_RINGING) {
+			ast_verb(3, "detected forward request from interface '%s' after device was ringing.\n", interface);
+			struct ast_datastore *datastore = NULL;
+			struct ast_dialed_interface *di;
+			AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
+
+			ast_channel_lock(in);
+			datastore = ast_channel_datastore_find(in, &dialed_interface_info, NULL);
+			ast_channel_unlock(in);
+			if (datastore) {
+				dialed_interfaces = datastore->data;
+				AST_LIST_LOCK(dialed_interfaces);
+				AST_LIST_TRAVERSE_SAFE_BEGIN(dialed_interfaces, di, list) {
+					if (!strcasecmp(di->interface, interface)) {
+						ast_verb(3, "->> removed '%s' from list of dialed interfaces!\n", interface);
+						AST_LIST_REMOVE_CURRENT(list);
+					}
+				}
+				AST_LIST_TRAVERSE_SAFE_END;
+				AST_LIST_UNLOCK(dialed_interfaces);
+			}
+		}
+
+
+		const char *callback = NULL;
+		const char *callback_from = NULL;
+		const char *callforward_from = NULL;
+
+		if (opt_args[OPT_CONVERGED] && (strncmp(in->name, "Local", 5) == 0)) {
+			callback = pbx_builtin_getvar_helper(in, "CALLBACK");
+			callback_from = pbx_builtin_getvar_helper(in, "CALLBACK_FROM");
+
+			if (callback) {
+				ast_verb(4, ">> copying variables from forwarding channel: CALLBACK=%s CALLBACK_FROM=%s\n", callback, callback_from);
+				pbx_builtin_setvar_helper(in->requestor, "_CALLFORWARD", c->name);
+				pbx_builtin_setvar_helper(in->requestor, "CALLBACK", callback);
+				pbx_builtin_setvar_helper(in->requestor, "CALLBACK_FROM", callback_from);
+			}
+			ast_verb(3, "Now forwarding upstream (%s) to '%s/%s' (thanks to %s (%s))\n", in->requestor->name, tech, stuff, in->name, c->name);
+			ast_string_field_set(in->requestor, call_forward, c->call_forward);
+			//ast_hangup(in);
+			ast_clear_flag64(o, DIAL_STILLGOING);
+			c = o->chan = NULL;
+			cause = AST_CAUSE_NORMAL_CLEARING;
+		}
+		else {
+			callback = pbx_builtin_getvar_helper(c, "CALLBACK");
+			callback_from = pbx_builtin_getvar_helper(c, "CALLBACK_FROM");
+			callforward_from = pbx_builtin_getvar_helper(c, "CALLFORWARD");
+
+			struct ast_channel *forwarder = c;
+			ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, forwarder->name);
+
+			/* Setup parameters */
+			c = o->chan = ast_request(tech, in->nativeformats, in, stuff, &cause);
+			if (c) {
+				if (single)
+					ast_channel_make_compatible(o->chan, in);
+				ast_channel_inherit_variables(in, o->chan);
+				ast_channel_datastore_inherit(in, o->chan);
+				if (callforward_from) {
+					pbx_builtin_setvar_helper(o->chan, "_CALLFORWARD", callforward_from);
+				}
+				else {
+					pbx_builtin_setvar_helper(o->chan, "_CALLFORWARD", forwarder->name);
+				}
+				if (callback) {
+					ast_verb(4, ">> copying variables from forwarding channel: CALLBACK=%s CALLBACK_FROM=%s\n", callback, callback_from);
+					pbx_builtin_setvar_helper(o->chan, "CALLBACK", callback);
+					pbx_builtin_setvar_helper(o->chan, "CALLBACK_FROM", callback_from);
+				}
+                    		/* When a call is forwarded, we don't want to track new interfaces
+				 * dialed for CC purposes. Setting the done flag will ensure that
+				 * any Dial operations that happen later won't record CC interfaces.
+				 */
+				ast_ignore_cc(o->chan);
+				ast_log(LOG_NOTICE, "Not accepting call completion offers from call-forward recipient %s\n", o->chan->name);
+			} else {
+				ast_log(LOG_NOTICE,
+					"Forwarding failed to create channel to dial '%s/%s' (cause = %d)\n",
+					tech, stuff, cause);
+			}
+		}
 	}
 	if (!c) {
 		ast_clear_flag64(o, DIAL_STILLGOING);
@@ -956,6 +1039,24 @@
 		}
 		if (single) {
 			ast_indicate(in, -1);
+		}
+	}
+	if (opt_args[OPT_CONVERGED]) {
+		if(outgoing && outgoing->next) {
+			struct chanlist *m;
+			for (m = outgoing; m; m = m->next) {
+				// check if outgoing chan is already dead
+				if (ast_test_flag64(m, DIAL_STILLGOING)) {
+					if (o->chan == NULL || strcmp(m->chan->name, o->chan->name)) {
+						ast_verb(3, "%s is cancelled, multicall forwarded by '%s'\n", m->chan->name, in->name);
+						ast_set_flag(m->chan, AST_FLAG_ANSWERED_ELSEWHERE);
+						ast_hangup(m->chan);
+						m->chan = NULL;
+						ast_clear_flag64(m, DIAL_STILLGOING);
+					}
+				}
+			}
+			o->chan = c;
 		}
 	}
 }
@@ -1120,7 +1221,7 @@
 					}
 					ast_frfree(f);
 				}
-				do_forward(o, &num, peerflags, single, to, forced_clid, stored_clid);
+				do_forward(o, &num, peerflags, single, to, forced_clid, stored_clid, opt_args, outgoing);
 				continue;
 			}
 			f = ast_read(winner);
@@ -1192,6 +1293,12 @@
 					c = o->chan = NULL;
 					ast_clear_flag64(o, DIAL_STILLGOING);
 					handle_cause(AST_CAUSE_BUSY, &num);
+					if (opt_args[OPT_CONVERGED]) {
+						ast_verb(2, "At least one channel is busy at this time. Aborting call. (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
+						strcpy(pa->status, "BUSY");
+						*to = 0;
+						return NULL;
+					}
 					break;
 				case AST_CONTROL_CONGESTION:
 					ast_verb(3, "%s is circuit-busy\n", c->name);

Modified: team/kaii/1.8-multicall/channels/chan_local.c
URL: http://svnview.digium.com/svn/asterisk/team/kaii/1.8-multicall/channels/chan_local.c?view=diff&rev=323324&r1=323323&r2=323324
==============================================================================
--- team/kaii/1.8-multicall/channels/chan_local.c (original)
+++ team/kaii/1.8-multicall/channels/chan_local.c Tue Jun 14 05:02:13 2011
@@ -1044,6 +1044,7 @@
 		return NULL;
 	}
 
+	tmp2->requestor = tmp;
 	tmp2->tech = tmp->tech = &local_tech;
 
 	tmp->nativeformats = p->reqformat;

Modified: team/kaii/1.8-multicall/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/kaii/1.8-multicall/include/asterisk/channel.h?view=diff&rev=323324&r1=323323&r2=323324
==============================================================================
--- team/kaii/1.8-multicall/include/asterisk/channel.h (original)
+++ team/kaii/1.8-multicall/include/asterisk/channel.h Tue Jun 14 05:02:13 2011
@@ -360,7 +360,7 @@
  * PSTN gateway).
  *
  * \todo Implement settings for transliteration between UTF8 Caller ID names in
- *       to ASCII Caller ID's (DAHDI). Östen Åsklund might be transliterated into
+ *       to ASCII Caller ID's (DAHDI). �sten �sklund might be transliterated into
  *       Osten Asklund or Oesten Aasklund depending upon language and person...
  *       We need automatic routines for incoming calls and static settings for
  *       our own accounts.
@@ -861,6 +861,7 @@
 	char macrocontext[AST_MAX_CONTEXT];		/*!< Macro: Current non-macro context. See app_macro.c */
 	char macroexten[AST_MAX_EXTENSION];		/*!< Macro: Current non-macro extension. See app_macro.c */
 	char emulate_dtmf_digit;			/*!< Digit being emulated */
+	struct ast_channel *requestor;			/*!< reference to the channel which requested this one */
 };
 
 /*! \brief ast_channel_tech Properties */

Modified: team/kaii/1.8-multicall/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/kaii/1.8-multicall/main/channel.c?view=diff&rev=323324&r1=323323&r2=323324
==============================================================================
--- team/kaii/1.8-multicall/main/channel.c (original)
+++ team/kaii/1.8-multicall/main/channel.c Tue Jun 14 05:02:13 2011
@@ -5441,6 +5441,8 @@
 			return NULL;
 		}
 
+		c->requestor = (struct ast_channel *) requestor; /* UGLY */
+
 		/* no need to generate a Newchannel event here; it is done in the channel_alloc call */
 		return c;
 	}




More information about the svn-commits mailing list