[svn-commits] rmudgett: branch 1.8 r348101 - in /branches/1.8: apps/ bridges/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Dec 13 17:00:51 CST 2011


Author: rmudgett
Date: Tue Dec 13 17:00:45 2011
New Revision: 348101

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=348101
Log:
Fix FollowMe CallerID on outgoing calls.

The addition of the Connected Line support changed how CallerID is passed
to outgoing calls.  The FollowMe application was not updated to pass
CallerID to the outgoing calls.

* Fix FollowMe CallerID on outgoing calls.

* Restructured findmeexec() to fix several memory leaks and eliminate some
duplicated code.

* Made check the return value of create_followme_number().  Putting a NULL
into the numbers list is bad if create_followme_number() fails.

* Fixed a couple uses of ast_strdupa() inside loops.

* The changes to bridge_builtin_features.c fix a similar CallerID issue
with the bridging API attended and blind transfers.  (Not used at this
time.)

(closes issue ASTERISK-17557)
Reported by: hamlet505a
Tested by: rmudgett

Review: https://reviewboard.asterisk.org/r/1612/

Modified:
    branches/1.8/apps/app_followme.c
    branches/1.8/bridges/bridge_builtin_features.c

Modified: branches/1.8/apps/app_followme.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/apps/app_followme.c?view=diff&rev=348101&r1=348100&r2=348101
==============================================================================
--- branches/1.8/apps/app_followme.c (original)
+++ branches/1.8/apps/app_followme.c Tue Dec 13 17:00:45 2011
@@ -309,7 +309,6 @@
 	struct number *cur, *nm;
 	char numberstr[90];
 	int timeout;
-	char *timeoutstr;
 	int numorder;
 	const char *takecallstr;
 	const char *declinecallstr;
@@ -427,17 +426,17 @@
 				ast_copy_string(numberstr, var->value, sizeof(numberstr));
 				if ((tmp = strchr(numberstr, ','))) {
 					*tmp++ = '\0';
-					timeoutstr = ast_strdupa(tmp);
-					if ((tmp = strchr(timeoutstr, ','))) {
+					timeout = atoi(tmp);
+					if (timeout < 0) {
+						timeout = 25;
+					}
+					if ((tmp = strchr(tmp, ','))) {
 						*tmp++ = '\0';
 						numorder = atoi(tmp);
 						if (numorder < 0)
 							numorder = 0;
 					} else 
 						numorder = 0;
-					timeout = atoi(timeoutstr);
-					if (timeout < 0) 
-						timeout = 25;
 				} else {
 					timeout = 25;
 					numorder = 0;
@@ -450,7 +449,9 @@
 					numorder = idx;
 				}
 				cur = create_followme_number(numberstr, timeout, numorder);
-				AST_LIST_INSERT_TAIL(&f->numbers, cur, entry);
+				if (cur) {
+					AST_LIST_INSERT_TAIL(&f->numbers, cur, entry);
+				}
 			} else {
 				profile_set_param(f, var->name, var->value, var->lineno, 1);
 				ast_debug(2, "Logging parameter %s with value %s from lineno %d\n", var->name, var->value, var->lineno);
@@ -497,7 +498,6 @@
 			ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
 		ast_hangup(tmpuser->ochan);
 	}
-
 }
 
 static void clear_calling_tree(struct findme_user_listptr *findme_user_list) 
@@ -510,7 +510,18 @@
 	}
 }
 
-
+static void destroy_calling_tree(struct findme_user_listptr *findme_user_list)
+{
+	struct findme_user *fmuser;
+
+	while ((fmuser = AST_LIST_REMOVE_HEAD(findme_user_list, entry))) {
+		if (!fmuser->cleared) {
+			clear_caller(fmuser);
+		}
+		ast_free(fmuser);
+	}
+	ast_free(findme_user_list);
+}
 
 static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_user_list, struct number *nm, struct ast_channel *caller, char *namerecloc, int *status, struct fm_args *tpargs) 
 {
@@ -787,6 +798,7 @@
 	struct ast_channel *caller;
 	struct ast_channel *winner = NULL;
 	char dialarg[512];
+	char num[512];
 	int dg, idx;
 	char *rest, *number;
 	struct findme_user *tmpuser;
@@ -799,132 +811,121 @@
 
 	/* We're going to figure out what the longest possible string of digits to collect is */
 	ynlongest = 0;
-	if (strlen(tpargs->takecall) > ynlongest)
+	if (strlen(tpargs->takecall) > ynlongest) {
 		ynlongest = strlen(tpargs->takecall);
-	if (strlen(tpargs->nextindp) > ynlongest)
+	}
+	if (strlen(tpargs->nextindp) > ynlongest) {
 		ynlongest = strlen(tpargs->nextindp);
-
-	idx = 1;
+	}
+
 	caller = tpargs->chan;
-	AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry)
-		if (nm->order == idx)
+	for (idx = 1; !winner && !ast_check_hangup(caller); ++idx) {
+		/* Find next followme numbers to dial. */
+		AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) {
+			if (nm->order == idx) {
+				break;
+			}
+		}
+		if (!nm) {
 			break;
-
-	while (nm) {
+		}
+
 		ast_debug(2, "Number %s timeout %ld\n", nm->number,nm->timeout);
 
-		number = ast_strdupa(nm->number);
-		ast_debug(3, "examining %s\n", number);
-		do {
+		ast_copy_string(num, nm->number, sizeof(num));
+		for (number = num; number; number = rest) {
 			rest = strchr(number, '&');
 			if (rest) {
-				*rest = 0;
-				rest++;
+				*rest++ = 0;
 			}
 
-			/* We check if that context exists, before creating the ast_channel struct needed */
+			/* We check if the extension exists, before creating the ast_channel struct */
 			if (!ast_exists_extension(caller, tpargs->context, number, 1, S_COR(caller->caller.id.number.valid, caller->caller.id.number.str, NULL))) {
-				/* XXX Should probably restructure to simply skip this item, instead of returning. XXX */
 				ast_log(LOG_ERROR, "Extension '%s@%s' doesn't exist\n", number, tpargs->context);
-				free(findme_user_list);
-				return;
+				continue;
 			}
 
-			if (!strcmp(tpargs->context, ""))
+			if (!strcmp(tpargs->context, "")) {
 				snprintf(dialarg, sizeof(dialarg), "%s", number);
-			else
+			} else {
 				snprintf(dialarg, sizeof(dialarg), "%s@%s", number, tpargs->context);
+			}
 
 			tmpuser = ast_calloc(1, sizeof(*tmpuser));
 			if (!tmpuser) {
-				ast_free(findme_user_list);
-				return;
+				continue;
 			}
 
 			outbound = ast_request("Local", ast_best_codec(caller->nativeformats), caller, dialarg, &dg);
 			if (outbound) {
-				ast_set_callerid(outbound,
-					S_COR(caller->caller.id.number.valid, caller->caller.id.number.str, NULL),
-					S_COR(caller->caller.id.name.valid, caller->caller.id.name.str, NULL),
-					S_COR(caller->caller.id.number.valid, caller->caller.id.number.str, NULL));
-				ast_channel_inherit_variables(tpargs->chan, outbound);
-				ast_channel_datastore_inherit(tpargs->chan, outbound);
-				ast_string_field_set(outbound, language, tpargs->chan->language);
-				ast_string_field_set(outbound, accountcode, tpargs->chan->accountcode);
-				ast_string_field_set(outbound, musicclass, tpargs->chan->musicclass);
-				ast_verb(3, "calling %s\n", dialarg);
-				if (!ast_call(outbound,dialarg,0)) {
+				ast_channel_lock_both(caller, outbound);
+				ast_connected_line_copy_from_caller(&outbound->connected, &caller->caller);
+				ast_channel_inherit_variables(caller, outbound);
+				ast_channel_datastore_inherit(caller, outbound);
+				ast_string_field_set(outbound, language, caller->language);
+				ast_string_field_set(outbound, accountcode, caller->accountcode);
+				ast_string_field_set(outbound, musicclass, caller->musicclass);
+				ast_channel_unlock(outbound);
+				ast_channel_unlock(caller);
+				ast_verb(3, "calling Local/%s\n", dialarg);
+				if (!ast_call(outbound, dialarg, 0)) {
 					tmpuser->ochan = outbound;
 					tmpuser->state = 0;
 					tmpuser->cleared = 0;
 					ast_copy_string(tmpuser->dialarg, dialarg, sizeof(dialarg));
 					AST_LIST_INSERT_TAIL(findme_user_list, tmpuser, entry);
 				} else {
-					ast_verb(3, "couldn't reach at this number.\n"); 
-					if (outbound) {
-						if (!outbound->cdr) 
-							outbound->cdr = ast_cdr_alloc();
-						if (outbound->cdr) {
-							char tmp[256];
-
-							ast_cdr_init(outbound->cdr, outbound);
-							snprintf(tmp, sizeof(tmp), "%s/%s", "Local", dialarg);
-							ast_cdr_setapp(outbound->cdr, "FollowMe", tmp);
-							ast_cdr_update(outbound);
-							ast_cdr_start(outbound->cdr);
-							ast_cdr_end(outbound->cdr);
-							/* If the cause wasn't handled properly */
-							if (ast_cdr_disposition(outbound->cdr,outbound->hangupcause))
-								ast_cdr_failed(outbound->cdr);
-						} else {
-							ast_log(LOG_ERROR, "Unable to create Call Detail Record\n");
-							ast_hangup(outbound);
-							outbound = NULL;
+					ast_verb(3, "couldn't reach at this number.\n");
+					if (!outbound->cdr) {
+						outbound->cdr = ast_cdr_alloc();
+					}
+					if (outbound->cdr) {
+						char tmp[256];
+
+						ast_cdr_init(outbound->cdr, outbound);
+						snprintf(tmp, sizeof(tmp), "%s/%s", "Local", dialarg);
+						ast_cdr_setapp(outbound->cdr, "FollowMe", tmp);
+						ast_cdr_update(outbound);
+						ast_cdr_start(outbound->cdr);
+						ast_cdr_end(outbound->cdr);
+						/* If the cause wasn't handled properly */
+						if (ast_cdr_disposition(outbound->cdr, outbound->hangupcause)) {
+							ast_cdr_failed(outbound->cdr);
 						}
+					} else {
+						ast_log(LOG_ERROR, "Unable to create Call Detail Record\n");
 					}
+					ast_hangup(outbound);
+					ast_free(tmpuser);
 				}
-			} else 
+			} else {
 				ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n", dialarg, ast_cause2str(dg));
-
-			number = rest;
-		} while (number);
+				ast_free(tmpuser);
+			}
+		}
+
+		if (AST_LIST_EMPTY(findme_user_list)) {
+			continue;
+		}
 
 		status = 0;
-		if (!AST_LIST_EMPTY(findme_user_list))
-			winner = wait_for_winner(findme_user_list, nm, caller, tpargs->namerecloc, &status, tpargs);
-
+		winner = wait_for_winner(findme_user_list, nm, caller, tpargs->namerecloc, &status, tpargs);
+
+		/* Clean up all calls but winner. */
 		while ((fmuser = AST_LIST_REMOVE_HEAD(findme_user_list, entry))) {
-			if (!fmuser->cleared && fmuser->ochan != winner)
+			if (!fmuser->cleared && fmuser->ochan != winner) {
 				clear_caller(fmuser);
+			}
 			ast_free(fmuser);
 		}
-
-		fmuser = NULL;
-		tmpuser = NULL;
-		if (winner)
-			break;
-
-		if (!caller || ast_check_hangup(caller)) {
-			tpargs->status = 1;
-			ast_free(findme_user_list);
-			return;
-		}
-
-		idx++;
-		AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) {
-			if (nm->order == idx)
-				break;
-		}
-	}
-	ast_free(findme_user_list);
-	if (!winner) 
+	}
+	destroy_calling_tree(findme_user_list);
+	if (!winner) {
 		tpargs->status = 1;
-	else {
+	} else {
 		tpargs->status = 100;
 		tpargs->outbound = winner;
 	}
-
-	return;
 }
 
 static struct call_followme *find_realtime(const char *name)
@@ -1035,10 +1036,7 @@
 		return -1;
 	}
 
-	if (!(argstr = ast_strdupa((char *)data))) {
-		ast_log(LOG_ERROR, "Out of memory!\n");
-		return -1;
-	}
+	argstr = ast_strdupa((char *) data);
 
 	AST_STANDARD_APP_ARGS(args, argstr);
 
@@ -1086,7 +1084,9 @@
 	AST_LIST_HEAD_INIT_NOLOCK(&targs.cnumbers);
 	AST_LIST_TRAVERSE(&f->numbers, nm, entry) {
 		newnm = create_followme_number(nm->number, nm->timeout, nm->order);
-		AST_LIST_INSERT_TAIL(&targs.cnumbers, newnm, entry);
+		if (newnm) {
+			AST_LIST_INSERT_TAIL(&targs.cnumbers, newnm, entry);
+		}
 	}
 	ast_mutex_unlock(&f->lock);
 
@@ -1156,11 +1156,10 @@
 			goto outrun;
 		}
 		res = ast_bridge_call(caller, outbound, &config);
-		if (outbound)
-			ast_hangup(outbound);
-	}
-
-	outrun:
+		ast_hangup(outbound);
+	}
+
+outrun:
 
 	if (f->realtime) {
 		/* Not in list */

Modified: branches/1.8/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/bridges/bridge_builtin_features.c?view=diff&rev=348101&r1=348100&r2=348101
==============================================================================
--- branches/1.8/bridges/bridge_builtin_features.c (original)
+++ branches/1.8/bridges/bridge_builtin_features.c Tue Dec 13 17:00:45 2011
@@ -69,10 +69,10 @@
 }
 
 /*! \brief Helper function that creates an outgoing channel and returns it immediately */
-static struct ast_channel *dial_transfer(const struct ast_channel *caller, const char *exten, const char *context)
-{
-	char destination[AST_MAX_EXTENSION+AST_MAX_CONTEXT+1] = "";
-	struct ast_channel *chan = NULL;
+static struct ast_channel *dial_transfer(struct ast_channel *caller, const char *exten, const char *context)
+{
+	char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
+	struct ast_channel *chan;
 	int cause;
 
 	/* Fill the variable with the extension and context we want to call */
@@ -83,8 +83,13 @@
 		return NULL;
 	}
 
-	/* Before we actually dial out let's inherit the appropriate dialplan variables */
+	/* Before we actually dial out let's inherit appropriate information. */
+	ast_channel_lock_both(caller, chan);
+	ast_connected_line_copy_from_caller(&chan->connected, &caller->caller);
 	ast_channel_inherit_variables(caller, chan);
+	ast_channel_datastore_inherit(caller, chan);
+	ast_channel_unlock(chan);
+	ast_channel_unlock(caller);
 
 	/* Since the above worked fine now we actually call it and return the channel */
 	if (ast_call(chan, destination, 0)) {




More information about the svn-commits mailing list