[asterisk-commits] twilson: branch 1.4 r122589 - in /branches/1.4: apps/ res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jun 13 11:29:08 CDT 2008


Author: twilson
Date: Fri Jun 13 11:29:07 2008
New Revision: 122589

URL: http://svn.digium.com/view/asterisk?view=rev&rev=122589
Log:
This should fix the behavior of the 'T' dial feature being passed incorrectly to the transferee when builtin_atxfers are used.
Also, doing a builtin_atxfer to parking was broken and is fixed here as well.

(closes issue #11898)
	Reported by: sergee
	Tested by: otherwiseguy

Modified:
    branches/1.4/apps/app_dial.c
    branches/1.4/res/res_features.c

Modified: branches/1.4/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/apps/app_dial.c?view=diff&rev=122589&r1=122588&r2=122589
==============================================================================
--- branches/1.4/apps/app_dial.c (original)
+++ branches/1.4/apps/app_dial.c Fri Jun 13 11:29:07 2008
@@ -789,7 +789,7 @@
 	return 0;
 }
 
-static void set_dial_features(struct ast_flags *opts, struct ast_dial_features *features)
+static void set_dial_features(struct ast_flags *opts, struct ast_dial_features *features, struct ast_channel *chan)
 {
 	struct ast_flags perm_opts = {.flags = 0};
 
@@ -800,6 +800,22 @@
 	memset(features->options, 0, sizeof(features->options));
 
 	ast_app_options2str(dial_exec_options, &perm_opts, features->options, sizeof(features->options));
+	if (ast_test_flag(&perm_opts, OPT_CALLEE_TRANSFER))
+		ast_set_flag(&(features->features_callee), AST_FEATURE_REDIRECT);
+	if (ast_test_flag(&perm_opts, OPT_CALLER_TRANSFER))
+		ast_set_flag(&(features->features_caller), AST_FEATURE_REDIRECT);
+	if (ast_test_flag(&perm_opts, OPT_CALLEE_HANGUP))
+		ast_set_flag(&(features->features_callee), AST_FEATURE_DISCONNECT);
+	if (ast_test_flag(&perm_opts, OPT_CALLER_HANGUP))
+		ast_set_flag(&(features->features_caller), AST_FEATURE_DISCONNECT);
+	if (ast_test_flag(&perm_opts, OPT_CALLEE_MONITOR))
+		ast_set_flag(&(features->features_callee), AST_FEATURE_AUTOMON);
+	if (ast_test_flag(&perm_opts, OPT_CALLER_MONITOR))
+		ast_set_flag(&(features->features_caller), AST_FEATURE_AUTOMON);
+	if (ast_test_flag(&perm_opts, OPT_CALLEE_PARK))
+		ast_set_flag(&(features->features_callee), AST_FEATURE_PARKCALL);
+	if (ast_test_flag(&perm_opts, OPT_CALLER_PARK))
+		ast_set_flag(&(features->features_caller), AST_FEATURE_PARKCALL);
 }
 
 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags, int *continue_exec)
@@ -1109,18 +1125,16 @@
 		goto out;
 	}
 
-	if (!(caller_features = ast_malloc(sizeof(*caller_features)))) {
+	if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
 		ast_log(LOG_WARNING, "Unable to allocate memory for feature flags. Aborting!\n");
 		goto out;
 	}
 
+	ast_channel_lock(chan);
 	caller_features->is_caller = 1;
-	set_dial_features(&opts, caller_features);
-
-	ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
+	set_dial_features(&opts, caller_features, chan);
+	ds_caller_features->inheritance = -1;
 	ds_caller_features->data = caller_features;
-
-	ast_channel_lock(chan);
 	ast_channel_datastore_add(chan, ds_caller_features);
 	ast_channel_unlock(chan);
 
@@ -1291,22 +1305,19 @@
 			goto out;
 		}
 
-		if (!(callee_features = ast_malloc(sizeof(*callee_features)))) {
+		if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
 			ast_log(LOG_WARNING, "Unable to allocate memory for feature flags. Aborting!\n");
 			ast_free(tmp);
 			goto out;
 		}
 
+		ast_channel_lock(tmp->chan);
 		callee_features->is_caller = 0;
-		set_dial_features(&opts, callee_features);
-
-		ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
+		set_dial_features(&opts, callee_features, tmp->chan);
+		ds_callee_features->inheritance = -1;
 		ds_callee_features->data = callee_features;
-
-		ast_channel_lock(tmp->chan);
 		ast_channel_datastore_add(tmp->chan, ds_callee_features);
 		ast_channel_unlock(tmp->chan);
-
 
 		/* Place the call, but don't wait on the answer */
 		res = ast_call(tmp->chan, numsubst, 0);

Modified: branches/1.4/res/res_features.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/res/res_features.c?view=diff&rev=122589&r1=122588&r2=122589
==============================================================================
--- branches/1.4/res/res_features.c (original)
+++ branches/1.4/res/res_features.c Fri Jun 13 11:29:07 2008
@@ -391,8 +391,30 @@
 	if (extout)
 		*extout = x;
 
-	if (peer) 
-		ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
+	if (peer) { 
+		/* This is so ugly that it hurts, but implementing get_base_channel() on local channels
+			could have ugly side effects.  We could have transferer<->local,1<->local,2<->parking
+			and we need the callback name to be that of transferer.  Since local,1/2 have the same
+			name we can be tricky and just grab the bridged channel from the other side of the local
+		*/
+		if (!strcasecmp(peer->tech->type, "Local")) {
+			struct ast_channel *tmpchan, *base_peer;
+			char other_side[AST_CHANNEL_NAME];
+			char *c;
+			ast_copy_string(other_side, peer->name, sizeof(other_side));
+			if ((c = strrchr(other_side, ','))) {
+				*++c = '1';
+			}
+			if ((tmpchan = ast_get_channel_by_name_locked(other_side))) {
+				if ((base_peer = ast_bridged_channel(tmpchan))) {
+					ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
+				}
+				ast_channel_unlock(tmpchan);
+			}
+		} else {
+			ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
+		}
+	}
 
 	/* Remember what had been dialed, so that if the parking
 	   expires, we try to come back to the same place */
@@ -792,6 +814,8 @@
 	struct ast_bridge_config bconfig;
 	struct ast_frame *f;
 	int l;
+	struct ast_datastore *features_datastore;
+	struct ast_dial_features *dialfeatures = NULL;
 
 	if (option_debug)
 		ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
@@ -834,9 +858,22 @@
 	}
 
 	l = strlen(xferto);
-	snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);	/* append context */
+	snprintf(xferto + l, sizeof(xferto) - l, "@%s", transferer_real_context);	/* append context */
 	newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats),
 		xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, transferer->language);
+
+	/* If we are the callee and we are being transferred, after the masquerade
+	* caller features will really be the original callee features */
+	ast_channel_lock(transferee);
+	if ((features_datastore = ast_channel_datastore_find(transferee, &dial_features_info, NULL))) {
+		dialfeatures = features_datastore->data;
+	}
+	ast_channel_unlock(transferee);
+
+	if (dialfeatures && !dialfeatures->is_caller) {
+		ast_copy_flags(&(config->features_caller), &(dialfeatures->features_callee), AST_FLAGS_ALL);
+	}
+
 	ast_indicate(transferer, -1);
 	if (!newchan) {
 		finishup(transferee);
@@ -909,6 +946,19 @@
 		ast_hangup(newchan);
 		return -1;
 	}
+    
+	/* For the case where the transfer target is being connected with the original
+		caller store the target's original features, and apply to the bridge */
+	ast_channel_lock(newchan);
+	if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
+		dialfeatures = features_datastore->data;
+	}
+	ast_channel_unlock(newchan);
+
+	if (dialfeatures) {
+		ast_copy_flags(&(config->features_callee), &(dialfeatures->features_callee), AST_FLAGS_ALL);
+	}
+
 	tobj->chan = newchan;
 	tobj->peer = xferchan;
 	tobj->bconfig = *config;




More information about the asterisk-commits mailing list