[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r380122 - in /team/rmudgett/bridge_pha...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jan 25 14:48:34 CST 2013


Author: rmudgett
Date: Fri Jan 25 14:48:30 2013
New Revision: 380122

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=380122
Log:
Merged revisions 380108-380109 via svnmerge from 
file:///srv/subversion/repos/asterisk/trunk

........
  r380108 | rmudgett | 2013-01-25 13:29:04 -0600 (Fri, 25 Jan 2013) | 7 lines
  
  More trivial bridge code cleanup.
  
  * Breaking long lines
  * Word wrapping comment blocks.
  * Removing redundant initializers.
  * Debug message wording.
........
  r380109 | rmudgett | 2013-01-25 14:00:21 -0600 (Fri, 25 Jan 2013) | 20 lines
  
  Misc bridge code improvements
  
  * Made multiplexed_bridge_destroy() check if anything to destroy and
  cleared bridge_pvt pointer after destruction.
  
  * Made multiplexed_add_or_remove() handling of the chans array simpler.
  
  * Extracted bridge_channel_poke().
  
  * Simplified bridge_array_remove() handling of the bridge->array[].  The
  array does not have a NULL sentinel pointer.
  
  * Made ast_bridge_new() not create a temporary bridge just to see if it
  can be done.  Only need to check if there is an appropriate bridge tech
  available.
  
  * Made ast_bridge_new() clean up on allocation failures.
  
  * Made destroy_bridge() free resources in the opposite order of creation.
........
........

Merged revisions 380110 from http://svn.asterisk.org/svn/asterisk/team/group/bridge_construction

Modified:
    team/rmudgett/bridge_phase/   (props changed)
    team/rmudgett/bridge_phase/bridges/bridge_multiplexed.c
    team/rmudgett/bridge_phase/bridges/bridge_simple.c
    team/rmudgett/bridge_phase/bridges/bridge_softmix.c
    team/rmudgett/bridge_phase/main/bridging.c

Propchange: team/rmudgett/bridge_phase/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/rmudgett/bridge_phase/
------------------------------------------------------------------------------
--- bridge_construction-integrated (original)
+++ bridge_construction-integrated Fri Jan 25 14:48:30 2013
@@ -1,1 +1,1 @@
-/trunk:1-380083
+/trunk:1-380109

Propchange: team/rmudgett/bridge_phase/
------------------------------------------------------------------------------
--- bridge_phase-integrated (original)
+++ bridge_phase-integrated Fri Jan 25 14:48:30 2013
@@ -1,1 +1,1 @@
-/team/group/bridge_construction:1-380092
+/team/group/bridge_construction:1-380120

Modified: team/rmudgett/bridge_phase/bridges/bridge_multiplexed.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/bridges/bridge_multiplexed.c?view=diff&rev=380122&r1=380121&r2=380122
==============================================================================
--- team/rmudgett/bridge_phase/bridges/bridge_multiplexed.c (original)
+++ team/rmudgett/bridge_phase/bridges/bridge_multiplexed.c Fri Jan 25 14:48:30 2013
@@ -100,11 +100,13 @@
 	ao2_lock(multiplexed_threads);
 
 	/* Try to find an existing thread to handle our additional channels */
-	if (!(multiplexed_thread = ao2_callback(multiplexed_threads, 0, find_multiplexed_thread, NULL))) {
+	multiplexed_thread = ao2_callback(multiplexed_threads, 0, find_multiplexed_thread, NULL);
+	if (!multiplexed_thread) {
 		int flags;
 
 		/* If we failed we will have to create a new one from scratch */
-		if (!(multiplexed_thread = ao2_alloc(sizeof(*multiplexed_thread), destroy_multiplexed_thread))) {
+		multiplexed_thread = ao2_alloc(sizeof(*multiplexed_thread), destroy_multiplexed_thread);
+		if (!multiplexed_thread) {
 			ast_debug(1, "Failed to find or create a new multiplexed thread for bridge '%p'\n", bridge);
 			ao2_unlock(multiplexed_threads);
 			return -1;
@@ -176,7 +178,12 @@
 /*! \brief Destroy function which unreserves/unreferences/removes a multiplexed thread structure */
 static int multiplexed_bridge_destroy(struct ast_bridge *bridge)
 {
-	struct multiplexed_thread *multiplexed_thread = bridge->bridge_pvt;
+	struct multiplexed_thread *multiplexed_thread;
+
+	multiplexed_thread = bridge->bridge_pvt;
+	if (!multiplexed_thread) {
+		return -1;
+	}
 
 	ao2_lock(multiplexed_threads);
 
@@ -192,6 +199,7 @@
 	ao2_unlock(multiplexed_threads);
 
 	ao2_ref(multiplexed_thread, -1);
+	bridge->bridge_pvt = NULL;
 
 	return 0;
 }
@@ -207,11 +215,14 @@
 	ast_debug(1, "Starting actual thread for multiplexed thread '%p'\n", multiplexed_thread);
 
 	while (multiplexed_thread->thread != AST_PTHREADT_STOP) {
-		struct ast_channel *winner = NULL, *first = multiplexed_thread->chans[0];
-		int to = -1, outfd = -1;
+		struct ast_channel *winner;
+		struct ast_channel *first = multiplexed_thread->chans[0];
+		int to = -1;
+		int outfd = -1;
 
 		/* Move channels around so not just the first one gets priority */
-		memmove(multiplexed_thread->chans, multiplexed_thread->chans + 1, sizeof(struct ast_channel *) * (multiplexed_thread->service_count - 1));
+		memmove(multiplexed_thread->chans, multiplexed_thread->chans + 1,
+			sizeof(struct ast_channel *) * (multiplexed_thread->service_count - 1));
 		multiplexed_thread->chans[multiplexed_thread->service_count - 1] = first;
 
 		multiplexed_thread->waiting = 1;
@@ -233,8 +244,9 @@
 			}
 		}
 		if (winner && ast_channel_internal_bridge(winner)) {
-			struct ast_bridge *bridge = ast_channel_internal_bridge(winner);
+			struct ast_bridge *bridge;
 			int stop = 0;
+
 			ao2_unlock(multiplexed_thread);
 			while ((bridge = ast_channel_internal_bridge(winner)) && ao2_trylock(bridge)) {
 				sched_yield();
@@ -264,26 +276,36 @@
 /*! \brief Helper function which adds or removes a channel and nudges the thread */
 static void multiplexed_add_or_remove(struct multiplexed_thread *multiplexed_thread, struct ast_channel *chan, int add)
 {
-	int i, removed = 0;
+	int idx;
 	pthread_t thread = AST_PTHREADT_NULL;
 
 	ao2_lock(multiplexed_thread);
 
 	multiplexed_nudge(multiplexed_thread);
 
-	for (i = 0; i < MULTIPLEXED_MAX_CHANNELS; i++) {
-		if (multiplexed_thread->chans[i] == chan) {
+	for (idx = 0; idx < ARRAY_LEN(multiplexed_thread->chans); ++idx) {
+		if (multiplexed_thread->chans[idx] == chan) {
 			if (!add) {
-				multiplexed_thread->chans[i] = NULL;
-				multiplexed_thread->service_count--;
-				removed = 1;
+				memmove(multiplexed_thread->chans + idx,
+					multiplexed_thread->chans + idx + 1,
+					sizeof(struct ast_channel *) * (ARRAY_LEN(multiplexed_thread->chans) - (idx + 1)));
+				multiplexed_thread->chans[ARRAY_LEN(multiplexed_thread->chans) - 1] = NULL;
+				--multiplexed_thread->service_count;
 			}
 			break;
-		} else if (!multiplexed_thread->chans[i] && add) {
-			multiplexed_thread->chans[i] = chan;
-			multiplexed_thread->service_count++;
+		}
+		if (!multiplexed_thread->chans[idx]) {
+			if (add) {
+				multiplexed_thread->chans[idx] = chan;
+				++multiplexed_thread->service_count;
+			}
 			break;
 		}
+	}
+	if (ARRAY_LEN(multiplexed_thread->chans) == idx && add) {
+		ast_log(LOG_ERROR, "Could not add channel %s to multiplexed thread %p.  Array not large enough.\n",
+			ast_channel_name(chan), multiplexed_thread);
+		ast_assert(0);
 	}
 
 	if (multiplexed_thread->service_count && multiplexed_thread->thread == AST_PTHREADT_NULL) {
@@ -293,11 +315,11 @@
 			ast_log(LOG_WARNING, "Failed to create the bridge thread for multiplexed thread '%p', trying next time\n",
 				multiplexed_thread);
 		}
-	} else if (!multiplexed_thread->service_count && multiplexed_thread->thread != AST_PTHREADT_NULL) {
+	} else if (!multiplexed_thread->service_count
+		&& multiplexed_thread->thread != AST_PTHREADT_NULL
+		&& multiplexed_thread->thread != AST_PTHREADT_STOP) {
 		thread = multiplexed_thread->thread;
 		multiplexed_thread->thread = AST_PTHREADT_STOP;
-	} else if (!add && removed) {
-		memmove(multiplexed_thread->chans + i, multiplexed_thread->chans + i + 1, sizeof(struct ast_channel *) * (MULTIPLEXED_MAX_CHANNELS - (i + 1)));
 	}
 
 	ao2_unlock(multiplexed_thread);
@@ -310,7 +332,8 @@
 /*! \brief Join function which actually adds the channel into the array to be monitored */
 static int multiplexed_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
-	struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan, *c1 = AST_LIST_LAST(&bridge->channels)->chan;
+	struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
+	struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
 	struct multiplexed_thread *multiplexed_thread = bridge->bridge_pvt;
 
 	ast_debug(1, "Adding channel '%s' to multiplexed thread '%p' for monitoring\n", ast_channel_name(bridge_channel->chan), multiplexed_thread);

Modified: team/rmudgett/bridge_phase/bridges/bridge_simple.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/bridges/bridge_simple.c?view=diff&rev=380122&r1=380121&r2=380122
==============================================================================
--- team/rmudgett/bridge_phase/bridges/bridge_simple.c (original)
+++ team/rmudgett/bridge_phase/bridges/bridge_simple.c Fri Jan 25 14:48:30 2013
@@ -47,7 +47,8 @@
 
 static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
-	struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan, *c1 = AST_LIST_LAST(&bridge->channels)->chan;
+	struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
+	struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
 
 	/* If this is the first channel we can't make it compatible... unless we make it compatible with itself O.o */
 	if (AST_LIST_FIRST(&bridge->channels) == AST_LIST_LAST(&bridge->channels)) {

Modified: team/rmudgett/bridge_phase/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/bridges/bridge_softmix.c?view=diff&rev=380122&r1=380121&r2=380122
==============================================================================
--- team/rmudgett/bridge_phase/bridges/bridge_softmix.c (original)
+++ team/rmudgett/bridge_phase/bridges/bridge_softmix.c Fri Jan 25 14:48:30 2013
@@ -284,7 +284,8 @@
 
 static void softmix_translate_helper_cleanup(struct softmix_translate_helper *trans_helper)
 {
-	struct softmix_translate_helper_entry *entry = NULL;
+	struct softmix_translate_helper_entry *entry;
+
 	AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
 		if (entry->out_frame) {
 			ast_frfree(entry->out_frame);
@@ -328,8 +329,10 @@
 /*! \brief Function called when a bridge is destroyed */
 static int softmix_bridge_destroy(struct ast_bridge *bridge)
 {
-	struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
-	if (!bridge->bridge_pvt) {
+	struct softmix_bridge_data *softmix_data;
+
+	softmix_data = bridge->bridge_pvt;
+	if (!softmix_data) {
 		return -1;
 	}
 	ao2_ref(softmix_data, -1);
@@ -382,7 +385,7 @@
 /*! \brief Function called when a channel is joined into the bridge */
 static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
-	struct softmix_channel *sc = NULL;
+	struct softmix_channel *sc;
 	struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
 
 	/* Create a new softmix_channel structure and allocate various things on it */
@@ -718,7 +721,7 @@
 	memset(mixing_array, 0, sizeof(*mixing_array));
 	mixing_array->max_num_entries = starting_num_entries;
 	if (!(mixing_array->buffers = ast_calloc(mixing_array->max_num_entries, sizeof(int16_t *)))) {
-		ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure. \n");
+		ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure.\n");
 		return -1;
 	}
 	return 0;
@@ -735,7 +738,7 @@
 	/* give it some room to grow since memory is cheap but allocations can be expensive */
 	mixing_array->max_num_entries = num_entries;
 	if (!(tmp = ast_realloc(mixing_array->buffers, (mixing_array->max_num_entries * sizeof(int16_t *))))) {
-		ast_log(LOG_NOTICE, "Failed to re-allocate softmix mixing structure. \n");
+		ast_log(LOG_NOTICE, "Failed to re-allocate softmix mixing structure.\n");
 		return -1;
 	}
 	mixing_array->buffers = tmp;
@@ -747,7 +750,7 @@
 {
 	struct softmix_stats stats = { { 0 }, };
 	struct softmix_mixing_array mixing_array;
-	struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
+	struct softmix_bridge_data *softmix_data;
 	struct ast_timer *timer;
 	struct softmix_translate_helper trans_helper;
 	int16_t buf[MAX_DATALEN];
@@ -757,7 +760,8 @@
 	int i, x;
 	int res = -1;
 
-	if (!(softmix_data = bridge->bridge_pvt)) {
+	softmix_data = bridge->bridge_pvt;
+	if (!softmix_data) {
 		goto softmix_cleanup;
 	}
 
@@ -769,12 +773,11 @@
 
 	/* Give the mixing array room to grow, memory is cheap but allocations are expensive. */
 	if (softmix_mixing_array_init(&mixing_array, bridge->num + 10)) {
-		ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure. \n");
 		goto softmix_cleanup;
 	}
 
 	while (!bridge->stop && !bridge->refresh && bridge->array_num) {
-		struct ast_bridge_channel *bridge_channel = NULL;
+		struct ast_bridge_channel *bridge_channel;
 		int timeout = -1;
 		enum ast_format_id cur_slin_id = ast_format_slin_by_rate(softmix_data->internal_rate);
 		unsigned int softmix_samples = SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
@@ -790,7 +793,8 @@
 		}
 
 		/* Grow the mixing array buffer as participants are added. */
-		if (mixing_array.max_num_entries < bridge->num && softmix_mixing_array_grow(&mixing_array, bridge->num + 5)) {
+		if (mixing_array.max_num_entries < bridge->num
+			&& softmix_mixing_array_grow(&mixing_array, bridge->num + 5)) {
 			goto softmix_cleanup;
 		}
 
@@ -887,7 +891,7 @@
 		/* Wait for the timing source to tell us to wake up and get things done */
 		ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
 		if (ast_timer_ack(timer, 1) < 0) {
-			ast_log(LOG_ERROR, "Failed to acknowledge timer in softmix bridge\n");
+			ast_log(LOG_ERROR, "Failed to acknowledge timer in softmix bridge.\n");
 			ao2_lock(bridge);
 			goto softmix_cleanup;
 		}

Modified: team/rmudgett/bridge_phase/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/bridging.c?view=diff&rev=380122&r1=380121&r2=380122
==============================================================================
--- team/rmudgett/bridge_phase/main/bridging.c (original)
+++ team/rmudgett/bridge_phase/main/bridging.c Fri Jan 25 14:48:30 2013
@@ -118,6 +118,14 @@
 	return current ? 0 : -1;
 }
 
+static void bridge_channel_poke(struct ast_bridge_channel *bridge_channel)
+{
+	ao2_lock(bridge_channel);
+	pthread_kill(bridge_channel->thread, SIGURG);
+	ast_cond_signal(&bridge_channel->cond);
+	ao2_unlock(bridge_channel);
+}
+
 /*! \note This function assumes the bridge_channel is locked. */
 static void ast_bridge_change_state_nolock(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state)
 {
@@ -138,7 +146,11 @@
 	ao2_unlock(bridge_channel);
 }
 
-/*! \brief Helper function to poke the bridge thread */
+/*!
+ * \brief Helper function to poke the bridge thread
+ *
+ * \note This function assumes the bridge is locked.
+ */
 static void bridge_poke(struct ast_bridge *bridge)
 {
 	/* Poke the thread just in case */
@@ -167,7 +179,8 @@
 	ao2_lock(bridge);
 }
 
-/*! \brief Helper function to add a channel to the bridge array
+/*!
+ * \brief Helper function to add a channel to the bridge array
  *
  * \note This function assumes the bridge is locked.
  */
@@ -181,17 +194,21 @@
 
 	bridge->array[bridge->array_num++] = chan;
 
-	ast_debug(1, "Added channel %s(%p) to bridge array on %p, new count is %d\n", ast_channel_name(chan), chan, bridge, (int)bridge->array_num);
+	ast_debug(1, "Added channel %s(%p) to bridge array on %p, new count is %d\n",
+		ast_channel_name(chan), chan, bridge, (int) bridge->array_num);
 
 	/* If the next addition of a channel will exceed our array size grow it out */
 	if (bridge->array_num == bridge->array_size) {
-		struct ast_channel **tmp;
-		ast_debug(1, "Growing bridge array on %p from %d to %d\n", bridge, (int)bridge->array_size, (int)bridge->array_size + BRIDGE_ARRAY_GROW);
-		if (!(tmp = ast_realloc(bridge->array, (bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(struct ast_channel *)))) {
-			ast_log(LOG_ERROR, "Failed to allocate more space for another channel on bridge '%p', this is not going to end well\n", bridge);
+		struct ast_channel **new_array;
+
+		ast_debug(1, "Growing bridge array on %p from %d to %d\n",
+			bridge, (int) bridge->array_size, (int) bridge->array_size + BRIDGE_ARRAY_GROW);
+		new_array = ast_realloc(bridge->array,
+			(bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(*bridge->array));
+		if (!new_array) {
 			return;
 		}
-		bridge->array = tmp;
+		bridge->array = new_array;
 		bridge->array_size += BRIDGE_ARRAY_GROW;
 	}
 }
@@ -202,7 +219,7 @@
  */
 static void bridge_array_remove(struct ast_bridge *bridge, struct ast_channel *chan)
 {
-	int i;
+	int idx;
 
 	/* We have to make sure the bridge thread is not using the bridge array before messing with it */
 	while (bridge->waiting) {
@@ -210,12 +227,12 @@
 		sched_yield();
 	}
 
-	for (i = 0; i < bridge->array_num; i++) {
-		if (bridge->array[i] == chan) {
-			bridge->array[i] = (bridge->array[(bridge->array_num - 1)] != chan ? bridge->array[(bridge->array_num - 1)] : NULL);
-			bridge->array[(bridge->array_num - 1)] = NULL;
-			bridge->array_num--;
-			ast_debug(1, "Removed channel %p from bridge array on %p, new count is %d\n", chan, bridge, (int)bridge->array_num);
+	for (idx = 0; idx < bridge->array_num; ++idx) {
+		if (bridge->array[idx] == chan) {
+			--bridge->array_num;
+			bridge->array[idx] = bridge->array[bridge->array_num];
+			ast_debug(1, "Removed channel %p from bridge array on %p, new count is %d\n",
+				chan, bridge, (int) bridge->array_num);
 			break;
 		}
 	}
@@ -268,7 +285,10 @@
 /*! \brief Internal function to see whether a bridge should dissolve, and if so do it */
 static void bridge_check_dissolve(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
-	if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE) && (!bridge_channel->features || !bridge_channel->features->usable || !ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_FLAG_DISSOLVE))) {
+	if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE)
+		&& (!bridge_channel->features
+			|| !bridge_channel->features->usable
+			|| !ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_FLAG_DISSOLVE))) {
 		return;
 	}
 
@@ -344,7 +364,8 @@
 			/* Signal the thread that is handling the bridged channel that it should be ended */
 			ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
 		} else if (frame->frametype == AST_FRAME_CONTROL && bridge_drop_control_frame(frame->subclass.integer)) {
-			ast_debug(1, "Dropping control frame from bridge channel %p\n", bridge_channel);
+			ast_debug(1, "Dropping control frame %d from bridge channel %p\n",
+				frame->subclass.integer, bridge_channel);
 		} else if (frame->frametype == AST_FRAME_DTMF_BEGIN || frame->frametype == AST_FRAME_DTMF_END) {
 			int dtmf_passthrough = bridge_channel->features ?
 				bridge_channel->features->dtmf_passthrough :
@@ -392,7 +413,7 @@
 static int generic_thread_loop(struct ast_bridge *bridge)
 {
 	while (!bridge->stop && !bridge->refresh && bridge->array_num) {
-		struct ast_channel *winner = NULL;
+		struct ast_channel *winner;
 		int to = -1;
 
 		/* Move channels around for priority reasons if we have more than one channel in our array */
@@ -405,7 +426,7 @@
 		/* Wait on the channels */
 		bridge->waiting = 1;
 		ao2_unlock(bridge);
-		winner = ast_waitfor_n(bridge->array, (int)bridge->array_num, &to);
+		winner = ast_waitfor_n(bridge->array, (int) bridge->array_num, &to);
 		bridge->waiting = 0;
 		ao2_lock(bridge);
 
@@ -439,7 +460,10 @@
 			bridge->technology->thread ? bridge->technology->thread : generic_thread_loop,
 			bridge);
 
-		/* Execute the appropriate thread function. If the technology does not provide one we use the generic one */
+		/*
+		 * Execute the appropriate thread function.  If the technology
+		 * does not provide one we use the generic one.
+		 */
 		res = bridge->technology->thread
 			? bridge->technology->thread(bridge)
 			: generic_thread_loop(bridge);
@@ -502,41 +526,41 @@
 	if (bridge->technology->destroy) {
 		ast_debug(1, "Giving bridge technology %s the bridge structure %p to destroy\n", bridge->technology->name, bridge);
 		if (bridge->technology->destroy(bridge)) {
-			ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... trying our best\n", bridge->technology->name, bridge);
-		}
-	}
+			ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... some memory may have leaked\n",
+				bridge->technology->name, bridge);
+		}
+	}
+
+	cleanup_video_mode(bridge);
+
+	/* Clean up the features configuration */
+	ast_bridge_features_cleanup(&bridge->features);
 
 	/* We are no longer using the bridge technology so decrement the module reference count on it */
 	ast_module_unref(bridge->technology->mod);
 
-	/* Last but not least clean up the features configuration */
-	ast_bridge_features_cleanup(&bridge->features);
-
 	/* Drop the array of channels */
 	ast_free(bridge->array);
-
-	cleanup_video_mode(bridge);
 }
 
 struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags)
 {
-	struct ast_bridge *bridge = NULL;
-	struct ast_bridge_technology *bridge_technology = NULL;
+	struct ast_bridge *bridge;
+	struct ast_bridge_technology *bridge_technology;
 
 	/* If we need to be a smart bridge see if we can move between 1to1 and multimix bridges */
 	if (flags & AST_BRIDGE_FLAG_SMART) {
-		struct ast_bridge *other_bridge;
-
-/* BUGBUG why cannot find_best_technology() do this? */
-		if (!(other_bridge = ast_bridge_new((capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) ? AST_BRIDGE_CAPABILITY_MULTIMIX : AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) {
+		if (!ast_bridge_check((capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX)
+			? AST_BRIDGE_CAPABILITY_MULTIMIX : AST_BRIDGE_CAPABILITY_1TO1MIX)) {
 			return NULL;
 		}
-
-		ast_bridge_destroy(other_bridge);
-	}
-
-	/* If capabilities were provided use our helper function to find the "best" bridge technology, otherwise we can
-	 * just look for the most basic capability needed, single 1to1 mixing. */
+	}
+
+	/*
+	 * If capabilities were provided use our helper function to find
+	 * the "best" bridge technology, otherwise we can just look for
+	 * the most basic capability needed, single 1to1 mixing.
+	 */
 	bridge_technology = capabilities
 		? find_best_technology(capabilities)
 		: find_best_technology(AST_BRIDGE_CAPABILITY_1TO1MIX);
@@ -547,7 +571,9 @@
 	}
 
 	/* We have everything we need to create this bridge... so allocate the memory, link things together, and fire her up! */
-	if (!(bridge = ao2_alloc(sizeof(*bridge), destroy_bridge))) {
+	bridge = ao2_alloc(sizeof(*bridge), destroy_bridge);
+	if (!bridge) {
+		ast_module_unref(bridge_technology->mod);
 		return NULL;
 	}
 
@@ -555,7 +581,11 @@
 	bridge->thread = AST_PTHREADT_NULL;
 
 	/* Create an array of pointers for the channels that will be joining us */
-	bridge->array = ast_calloc(BRIDGE_ARRAY_START, sizeof(struct ast_channel*));
+	bridge->array = ast_malloc(BRIDGE_ARRAY_START * sizeof(*bridge->array));
+	if (!bridge->array) {
+		ao2_ref(bridge, -1);
+		return NULL;
+	}
 	bridge->array_size = BRIDGE_ARRAY_START;
 
 	ast_set_flag(&bridge->feature_flags, flags);
@@ -566,7 +596,7 @@
 		if (bridge->technology->create(bridge)) {
 			ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", bridge->technology->name, bridge);
 			ao2_ref(bridge, -1);
-			bridge = NULL;
+			return NULL;
 		}
 	}
 
@@ -667,23 +697,26 @@
 static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int count)
 {
 	uint32_t new_capabilities = 0;
-	struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology;
+	struct ast_bridge_technology *new_technology;
+	struct ast_bridge_technology *old_technology = bridge->technology;
 	struct ast_bridge temp_bridge = {
 		.technology = bridge->technology,
 		.bridge_pvt = bridge->bridge_pvt,
 	};
-	struct ast_bridge_channel *bridge_channel2 = NULL;
+	struct ast_bridge_channel *bridge_channel2;
 
 	/* Based on current feature determine whether we want to change bridge technologies or not */
 	if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
 		if (count <= 2) {
-			ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name);
+			ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n",
+				bridge, count, bridge->technology->name);
 			return 0;
 		}
 		new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
 	} else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
 		if (count > 2) {
-			ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name);
+			ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n",
+				bridge, count, bridge->technology->name);
 			return 0;
 		}
 		new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX;
@@ -699,11 +732,17 @@
 		return -1;
 	}
 
-	ast_debug(1, "Performing smart bridge operation on bridge %p, moving from bridge technology %s to %s\n", bridge, old_technology->name, new_technology->name);
+	ast_debug(1, "Performing smart bridge operation on bridge %p, moving from bridge technology %s to %s\n",
+		bridge, old_technology->name, new_technology->name);
 
 	/* If a thread is currently executing for the current technology tell it to stop */
 	if (bridge->thread != AST_PTHREADT_NULL) {
-		/* If the new bridge technology also needs a thread simply tell the bridge thread to refresh itself. This has the benefit of not incurring the cost/time of tearing down and bringing up a new thread. */
+		/*
+		 * If the new bridge technology also needs a thread simply tell
+		 * the bridge thread to refresh itself.  This has the benefit of
+		 * not incurring the cost/time of tearing down and bringing up a
+		 * new thread.
+		 */
 		if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) {
 			ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge);
 			bridge->refresh = 1;
@@ -714,15 +753,22 @@
 		}
 	}
 
-	/* Since we are soon going to pass this bridge to a new technology we need to NULL out the bridge_pvt pointer but don't worry as it still exists in temp_bridge, ditto for the old technology */
+	/*
+	 * Since we are soon going to pass this bridge to a new
+	 * technology we need to NULL out the bridge_pvt pointer but
+	 * don't worry as it still exists in temp_bridge, ditto for the
+	 * old technology.
+	 */
 	bridge->bridge_pvt = NULL;
 	bridge->technology = new_technology;
 
 	/* Pass the bridge to the new bridge technology so it can set it up */
 	if (new_technology->create) {
-		ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", new_technology->name, bridge);
+		ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n",
+			new_technology->name, bridge);
 		if (new_technology->create(bridge)) {
-			ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", new_technology->name, bridge);
+			ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n",
+				new_technology->name, bridge);
 		}
 	}
 
@@ -735,9 +781,11 @@
 
 		/* First we part them from the old technology */
 		if (old_technology->leave) {
-			ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p (really %p)\n", old_technology->name, bridge_channel2, &temp_bridge, bridge);
+			ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p (really %p)\n",
+				old_technology->name, bridge_channel2, &temp_bridge, bridge);
 			if (old_technology->leave(&temp_bridge, bridge_channel2)) {
-				ast_debug(1, "Bridge technology %s failed to allow %p (really %p) to leave bridge %p\n", old_technology->name, bridge_channel2, &temp_bridge, bridge);
+				ast_debug(1, "Bridge technology %s failed to allow %p (really %p) to leave bridge %p\n",
+					old_technology->name, bridge_channel2, &temp_bridge, bridge);
 			}
 		}
 
@@ -746,24 +794,25 @@
 
 		/* Third we join them to the new technology */
 		if (new_technology->join) {
-			ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->name, bridge_channel2, bridge);
+			ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n",
+				new_technology->name, bridge_channel2, bridge);
 			if (new_technology->join(bridge, bridge_channel2)) {
-				ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", new_technology->name, bridge_channel2, bridge);
+				ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n",
+					new_technology->name, bridge_channel2, bridge);
 			}
 		}
 
 		/* Fourth we tell them to wake up so they become aware that the above has happened */
-		pthread_kill(bridge_channel2->thread, SIGURG);
-		ao2_lock(bridge_channel2);
-		ast_cond_signal(&bridge_channel2->cond);
-		ao2_unlock(bridge_channel2);
+		bridge_channel_poke(bridge_channel2);
 	}
 
 	/* Now that all the channels have been moved over we need to get rid of all the information the old technology may have left around */
 	if (old_technology->destroy) {
-		ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge);
+		ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n",
+			old_technology->name, &temp_bridge, bridge);
 		if (old_technology->destroy(&temp_bridge)) {
-			ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p (really %p)... some memory may have leaked\n", old_technology->name, &temp_bridge, bridge);
+			ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p (really %p)... some memory may have leaked\n",
+				old_technology->name, &temp_bridge, bridge);
 		}
 	}
 
@@ -917,9 +966,12 @@
 	/* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */
 	if (hook) {
 		hook->callback(bridge, bridge_channel, hook->hook_pvt);
-		/* If we are handing the channel off to an external hook for ownership,
-		 * we are not guaranteed what kind of state it will come back in.  If
-		 * the channel hungup, we need to detect that here. */
+		/*
+		 * If we are handing the channel off to an external hook for
+		 * ownership, we are not guaranteed what kind of state it will
+		 * come back in.  If the channel hungup, we need to detect that
+		 * here if the hook did not already change the state.
+		 */
 		if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
 			ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
 		}
@@ -1010,7 +1062,8 @@
 		/* Update bridge pointer on channel */
 		ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge);
 		/* If the technology requires a thread and one is not running, start it up */
-		if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
+		if (bridge_channel->bridge->thread == AST_PTHREADT_NULL
+			&& (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
 			bridge_channel->bridge->stop = 0;
 			ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
 			ao2_ref(bridge_channel->bridge, +1);
@@ -1347,10 +1400,7 @@
 		}
 
 		/* Poke the bridge channel, this will cause it to wake up and execute the proper threading model for the new bridge it is in */
-		pthread_kill(bridge_channel->thread, SIGURG);
-		ao2_lock(bridge_channel);
-		ast_cond_signal(&bridge_channel->cond);
-		ao2_unlock(bridge_channel);
+		bridge_channel_poke(bridge_channel);
 	}
 
 	ast_debug(1, "Merged channels from bridge %p into bridge %p\n", bridge1, bridge0);




More information about the asterisk-commits mailing list