[asterisk-commits] russell: branch russell/chan_refcount r100143 - /team/russell/chan_refcount/m...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jan 24 11:13:42 CST 2008


Author: russell
Date: Thu Jan 24 11:13:41 2008
New Revision: 100143

URL: http://svn.digium.com/view/asterisk?view=rev&rev=100143
Log:
Apply my res_features changes to features.c

Modified:
    team/russell/chan_refcount/main/features.c

Change Statistics:
 0 files changed

Modified: team/russell/chan_refcount/main/features.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/main/features.c?view=diff&rev=100143&r1=100142&r2=100143
==============================================================================
--- team/russell/chan_refcount/main/features.c (original)
+++ team/russell/chan_refcount/main/features.c Thu Jan 24 11:13:41 2008
@@ -2917,6 +2917,8 @@
 */
 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
 {
+	ast_channel_lock_both(chan, tmpchan);
+
 	ast_moh_stop(chan);
 	ast_channel_lock(chan);
 	ast_setstate(tmpchan, chan->_state);
@@ -2927,8 +2929,9 @@
 	ast_do_masquerade(tmpchan);
 	/* when returning from bridge, the channel will continue at the next priority */
 	ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
+
+	ast_channel_unlock(chan);
 	ast_channel_unlock(tmpchan);
-	ast_channel_unlock(chan);
 }
 
 /*!
@@ -2953,52 +2956,55 @@
 	struct ast_channel *chana = NULL, *chanb = NULL;
 	struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
 	struct ast_bridge_thread_obj *tobj = NULL;
+	const char *err_msg = NULL;
+	int res = 0;
 
 	/* make sure valid channels were specified */
-	if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
-		chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
-		chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
-		if (chana)
-			ast_channel_unlock(chana);
-		if (chanb)
-			ast_channel_unlock(chanb);
-
-		/* send errors if any of the channels could not be found/locked */
-		if (!chana) {
-			char buf[256];
-			snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
-			astman_send_error(s, m, buf);
-			return 0;
-		}
-		if (!chanb) {
-			char buf[256];
-			snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
-			astman_send_error(s, m, buf);
-			return 0;
-		}
-	} else {
+	if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
 		astman_send_error(s, m, "Missing channel parameter in request");
 		return 0;
 	}
 
-	/* Answer the channels if needed */
+	if (!(chana = ast_channel_get_by_name_prefix(channela, strlen(channela)))) {
+		char buf[256];
+
+		snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
+		astman_send_error(s, m, buf);
+
+		return 0;
+	}
+
+	if (!(chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb)))) {
+		char buf[256];
+
+		ast_channel_unref(chana);
+
+		snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
+		astman_send_error(s, m, buf);
+
+		return 0;
+	}
+
 	if (chana->_state != AST_STATE_UP)
 		ast_answer(chana);
+
 	if (chanb->_state != AST_STATE_UP)
 		ast_answer(chanb);
 
 	/* create the placeholder channels and grab the other channels */
 	if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
 		NULL, NULL, 0, "Bridge/%s", chana->name))) {
-		astman_send_error(s, m, "Unable to create temporary channel!");
-		return 1;
+		err_msg = "Unable to create temporary channel!";
+		res = 1;
+		goto return_cleanup;
 	}
 
 	if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
 		NULL, NULL, 0, "Bridge/%s", chanb->name))) {
-		astman_send_error(s, m, "Unable to create temporary channels!");
-		ast_channel_free(tmpchana);
-		return 1;
+		err_msg = "Unable to create temporary channel!";
+		tmpchana = ast_channel_release(tmpchana);
+		res = 1;
+		goto return_cleanup;
 	}
 
 	do_bridge_masquerade(chana, tmpchana);
@@ -3007,19 +3013,21 @@
 	/* make the channels compatible, send error if we fail doing so */
 	if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
 		ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
-		astman_send_error(s, m, "Could not make channels compatible for manager bridge");
+		err_msg = "Could not make channels compatible for manager bridge";
 		ast_hangup(tmpchana);
 		ast_hangup(tmpchanb);
-		return 1;
+		res = 1;
+		goto return_cleanup;
 	}
 
 	/* setup the bridge thread object and start the bridge */
 	if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
 		ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
-		astman_send_error(s, m, "Unable to spawn a new bridge thread");
+		err_msg = "Unable to spawn a new bridge thread";
 		ast_hangup(tmpchana);
 		ast_hangup(tmpchanb);
-		return 1;
+		res = 1;
+		goto return_cleanup;
 	}
 
 	tobj->chan = tmpchana;
@@ -3037,7 +3045,14 @@
 
 	astman_send_ack(s, m, "Launched bridge thread with success");
 
-	return 0;
+return_cleanup:
+	ast_channel_unref(chana);
+	ast_channel_unref(chanb);
+
+	if (err_msg)
+		astman_send_error(s, m, err_msg);
+
+	return res;
 }
 
 /*!
@@ -3188,24 +3203,23 @@
 		return 0;
 	}
 
-	ch1 = ast_get_channel_by_name_locked(channel);
-	if (!ch1) {
+	if (!(ch1 = ast_channel_get_by_name(channel))) {
 		snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
 		astman_send_error(s, m, buf);
 		return 0;
 	}
 
-	ch2 = ast_get_channel_by_name_locked(channel2);
-	if (!ch2) {
+	if (!(ch2 = ast_channel_get_by_name(channel2))) {
+		ast_channel_unref(ch1);
 		snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
 		astman_send_error(s, m, buf);
-		ast_channel_unlock(ch1);
 		return 0;
 	}
 
-	if (!ast_strlen_zero(timeout)) {
+	if (!ast_strlen_zero(timeout))
 		sscanf(timeout, "%d", &to);
-	}
+
+	ast_channel_lock_both(ch1, ch2);
 
 	res = ast_masq_park_call(ch1, ch2, to, &parkExt);
 	if (!res) {
@@ -3217,6 +3231,9 @@
 
 	ast_channel_unlock(ch1);
 	ast_channel_unlock(ch2);
+
+	ast_channel_unref(ch1);
+	ast_channel_unref(ch2);
 
 	return 0;
 }
@@ -3233,17 +3250,27 @@
 {
 	struct ast_channel *cur = NULL;
 	int res = -1;
-
-	while ((cur = ast_channel_walk_locked(cur)) != NULL) {
+	struct ast_channel_iterator *iter;
+
+	if (!(iter = ast_channel_iterator_all_new()))
+		return -1;
+
+	while ((cur = ast_channel_iterator_next(iter))) {
+		ast_channel_lock(cur);
 		if (!cur->pbx && 
 			(cur != chan) &&
 			(chan->pickupgroup & cur->callgroup) &&
 			((cur->_state == AST_STATE_RINGING) ||
 			 (cur->_state == AST_STATE_RING))) {
+			 	ast_channel_unlock(cur);
 			 	break;
 		}
 		ast_channel_unlock(cur);
-	}
+		ast_channel_unref(cur);
+	}
+
+	iter = ast_channel_iterator_destroy(iter);
+
 	if (cur) {
 		ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
 		res = ast_answer(chan);
@@ -3255,10 +3282,11 @@
 		res = ast_channel_masquerade(cur, chan);
 		if (res)
 			ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);		/* Done */
-		ast_channel_unlock(cur);
+		ast_channel_unref(cur);
 	} else	{
 		ast_debug(1, "No call pickup possible...\n");
 	}
+
 	return res;
 }
 
@@ -3329,7 +3357,7 @@
 	}
 
 	/* make sure we have a valid end point */
-	if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan, 
+	if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan, 
 		strlen(args.dest_chan)))) {
 		ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
 			"cannot get its lock\n", args.dest_chan);
@@ -3341,7 +3369,6 @@
 		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
 		return 0;
 	}
-	ast_channel_unlock(current_dest_chan);
 
 	/* answer the channel if needed */
 	if (current_dest_chan->_state != AST_STATE_UP)
@@ -3356,11 +3383,21 @@
 					"Reason: cannot create placeholder\r\n"
 					"Channel1: %s\r\n"
 					"Channel2: %s\r\n", chan->name, args.dest_chan);
-	}
+		ast_hangup(current_dest_chan);
+		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
+		return 0;
+	}
+
+	ast_channel_lock_both(current_dest_chan, final_dest_chan);
 	do_bridge_masquerade(current_dest_chan, final_dest_chan);
+	ast_channel_unlock(final_dest_chan);
+	ast_channel_unlock(current_dest_chan);
+	current_dest_chan = ast_channel_unref(current_dest_chan);
+
 
 	/* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
 	/* try to make compatible, send error if we fail */
+	ast_channel_lock(final_dest_chan);
 	if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
 		ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
 		manager_event(EVENT_FLAG_CALL, "BridgeExec",
@@ -3368,6 +3405,7 @@
 					"Reason: Could not make channels compatible for bridge\r\n"
 					"Channel1: %s\r\n"
 					"Channel2: %s\r\n", chan->name, final_dest_chan->name);
+		ast_channel_unlock(final_dest_chan);
 		ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
 		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
 		return 0;
@@ -3386,7 +3424,9 @@
 				ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
 		}
 	}
-	
+
+	ast_channel_unlock(final_dest_chan);
+
 	/* do the bridge */
 	ast_bridge_call(chan, final_dest_chan, &bconfig);
 
@@ -3402,6 +3442,8 @@
 			ast_hangup(final_dest_chan);
 		} else
 			ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
+
+		ast_channel_unref(final_dest_chan);
 	} else {
 		ast_debug(1, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
 		ast_hangup(final_dest_chan);




More information about the asterisk-commits mailing list