[asterisk-commits] rmudgett: trunk r397472 - in /trunk: apps/ bridges/ include/asterisk/ main/ r...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Aug 22 16:10:00 CDT 2013


Author: rmudgett
Date: Thu Aug 22 16:09:52 2013
New Revision: 397472

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=397472
Log:
Bridge API: Set a cause code on a channel when it is ejected from a bridge.

The cause code needs to be passed from the disconnecting channel to the
bridge peers if the disconnecting channel dissolves the bridge.

* Made the call to an app_agent_pool agent disconnect with the busy cause
code if the agent does not ack the call in time or hangs up before acking
the call.

(closes issue ASTERISK-22042)
Reported by: Matt Jordan

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

Modified:
    trunk/apps/app_agent_pool.c
    trunk/apps/app_bridgewait.c
    trunk/apps/app_confbridge.c
    trunk/apps/app_dial.c
    trunk/bridges/bridge_builtin_features.c
    trunk/bridges/bridge_builtin_interval_features.c
    trunk/include/asterisk/bridge.h
    trunk/include/asterisk/bridge_channel.h
    trunk/include/asterisk/bridge_internal.h
    trunk/main/bridge.c
    trunk/main/bridge_basic.c
    trunk/main/bridge_channel.c
    trunk/main/features.c
    trunk/res/parking/parking_applications.c
    trunk/res/parking/parking_bridge_features.c
    trunk/res/res_parking.c
    trunk/res/res_stasis.c

Modified: trunk/apps/app_agent_pool.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_agent_pool.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/apps/app_agent_pool.c (original)
+++ trunk/apps/app_agent_pool.c Thu Aug 22 16:09:52 2013
@@ -49,6 +49,7 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/stasis_channels.h"
+#include "asterisk/causes.h"
 
 /*** DOCUMENTATION
 	<application name="AgentLogin" language="en_US">
@@ -760,7 +761,7 @@
 
 	ast_party_connected_line_free(&doomed->waiting_colp);
 	if (doomed->caller_bridge) {
-		ast_bridge_destroy(doomed->caller_bridge);
+		ast_bridge_destroy(doomed->caller_bridge, AST_CAUSE_USER_BUSY);
 		doomed->caller_bridge = NULL;
 	}
 	if (doomed->logged) {
@@ -1019,15 +1020,17 @@
 
 	if (!caller_bridge) {
 		/* Reset agent. */
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+			AST_CAUSE_NORMAL_CLEARING);
 		return;
 	}
 	res = ast_bridge_move(caller_bridge, bridge_channel->bridge, bridge_channel->chan,
 		NULL, 0);
 	if (res) {
 		/* Reset agent. */
-		ast_bridge_destroy(caller_bridge);
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+		ast_bridge_destroy(caller_bridge, AST_CAUSE_USER_BUSY);
+		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+			AST_CAUSE_NORMAL_CLEARING);
 		return;
 	}
 	ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_ANSWER, NULL, 0);
@@ -1122,13 +1125,15 @@
 
 	if (deferred_logoff) {
 		ast_debug(1, "Agent %s: Deferred logoff.\n", agent->username);
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+			AST_CAUSE_NORMAL_CLEARING);
 	} else if (probation_timedout) {
 		ast_debug(1, "Agent %s: Login complete.\n", agent->username);
 		agent_devstate_changed(agent->username);
 	} else if (ack_timedout) {
 		ast_debug(1, "Agent %s: Ack call timeout.\n", agent->username);
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+			AST_CAUSE_NORMAL_CLEARING);
 	} else if (wrapup_timedout) {
 		ast_debug(1, "Agent %s: Wrapup timeout. Ready for new call.\n", agent->username);
 		agent_devstate_changed(agent->username);
@@ -1233,7 +1238,8 @@
 		 * agent will have some slightly different behavior in corner
 		 * cases.
 		 */
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+			AST_CAUSE_NORMAL_CLEARING);
 		return 0;
 	}
 
@@ -1455,7 +1461,7 @@
 	agent_devstate_changed(agent->username);
 
 	if (caller_bridge) {
-		ast_bridge_destroy(caller_bridge);
+		ast_bridge_destroy(caller_bridge, AST_CAUSE_USER_BUSY);
 	}
 
 	send_agent_logoff(logged, agent->username, time_logged_in);
@@ -1479,6 +1485,7 @@
 	struct ast_bridge_features features;
 
 	if (ast_bridge_features_init(&features)) {
+		ast_channel_hangupcause_set(logged, AST_CAUSE_NORMAL_CLEARING);
 		goto agent_run_cleanup;
 	}
 	for (;;) {
@@ -1487,6 +1494,8 @@
 		struct agent_cfg *cfg_old;
 		struct ast_bridge *holding;
 		struct ast_bridge *caller_bridge;
+
+		ast_channel_hangupcause_set(logged, AST_CAUSE_NORMAL_CLEARING);
 
 		holding = ao2_global_obj_ref(agent_holding);
 		if (!holding) {
@@ -1535,7 +1544,7 @@
 		agent_unlock(agent);
 		ao2_ref(cfg_old, -1);
 		if (caller_bridge) {
-			ast_bridge_destroy(caller_bridge);
+			ast_bridge_destroy(caller_bridge, AST_CAUSE_USER_BUSY);
 		}
 
 		if (agent->state == AGENT_STATE_LOGGING_OUT
@@ -1661,13 +1670,14 @@
 		agent->caller_bridge = NULL;
 		agent_unlock(agent);
 		if (caller_bridge) {
-			ast_bridge_destroy(caller_bridge);
+			ast_bridge_destroy(caller_bridge, AST_CAUSE_USER_BUSY);
 		}
 		return;
 	}
 
 	/* Kick the agent out of the holding bridge to reset it. */
-	ast_bridge_channel_leave_bridge_nolock(logged, BRIDGE_CHANNEL_STATE_END);
+	ast_bridge_channel_leave_bridge_nolock(logged, BRIDGE_CHANNEL_STATE_END,
+		AST_CAUSE_NORMAL_CLEARING);
 	ast_bridge_channel_unlock(logged);
 }
 
@@ -1677,7 +1687,8 @@
 
 	if (agent->state == AGENT_STATE_CALL_PRESENT) {
 		ast_verb(3, "Agent '%s' did not respond.  Safety timeout.\n", agent->username);
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+			AST_CAUSE_USER_BUSY);
 		caller_abort_agent(agent);
 	}
 
@@ -1829,7 +1840,7 @@
 	case AGENT_STATE_LOGGING_OUT:
 		agent_unlock(agent);
 		ast_party_connected_line_free(&connected);
-		ast_bridge_destroy(caller_bridge);
+		ast_bridge_destroy(caller_bridge, 0);
 		ast_bridge_features_cleanup(&caller_features);
 		ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
 		pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "NOT_LOGGED_IN");
@@ -1843,7 +1854,7 @@
 	default:
 		agent_unlock(agent);
 		ast_party_connected_line_free(&connected);
-		ast_bridge_destroy(caller_bridge);
+		ast_bridge_destroy(caller_bridge, 0);
 		ast_bridge_features_cleanup(&caller_features);
 		ast_verb(3, "Agent '%s' is busy.\n", agent->username);
 		pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "BUSY");
@@ -1855,7 +1866,7 @@
 	logged = agent_bridge_channel_get_lock(agent);
 	if (!logged) {
 		ast_party_connected_line_free(&connected);
-		ast_bridge_destroy(caller_bridge);
+		ast_bridge_destroy(caller_bridge, 0);
 		ast_bridge_features_cleanup(&caller_features);
 		ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
 		pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "NOT_LOGGED_IN");
@@ -1870,7 +1881,7 @@
 	ast_bridge_channel_unlock(logged);
 	ao2_ref(logged, -1);
 	if (res) {
-		ast_bridge_destroy(caller_bridge);
+		ast_bridge_destroy(caller_bridge, 0);
 		ast_bridge_features_cleanup(&caller_features);
 		ast_verb(3, "Agent '%s': Failed to alert the agent.\n", agent->username);
 		pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "ERROR");
@@ -2499,7 +2510,7 @@
 	/* Destroy agent holding bridge. */
 	holding = ao2_global_obj_replace(agent_holding, NULL);
 	if (holding) {
-		ast_bridge_destroy(holding);
+		ast_bridge_destroy(holding, 0);
 	}
 
 	destroy_config();

Modified: trunk/apps/app_bridgewait.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_bridgewait.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/apps/app_bridgewait.c (original)
+++ trunk/apps/app_bridgewait.c Thu Aug 22 16:09:52 2013
@@ -48,6 +48,7 @@
 #include "asterisk/bridge.h"
 #include "asterisk/musiconhold.h"
 #include "asterisk/astobj2.h"
+#include "asterisk/causes.h"
 
 /*** DOCUMENTATION
 	<application name="BridgeWait" language="en_US">
@@ -127,8 +128,9 @@
 static void wait_bridge_wrapper_destructor(void *obj)
 {
 	struct wait_bridge_wrapper *wrapper = obj;
+
 	if (wrapper->bridge) {
-		ast_bridge_destroy(wrapper->bridge);
+		ast_bridge_destroy(wrapper->bridge, 0);
 	}
 }
 
@@ -204,7 +206,8 @@
 static int bridgewait_timeout_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 {
 	ast_verb(3, "Channel %s timed out.\n", ast_channel_name(bridge_channel->chan));
-	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+		AST_CAUSE_NORMAL_CLEARING);
 	return -1;
 }
 
@@ -321,9 +324,8 @@
 
 	bridge_wrapper = ao2_alloc_options(sizeof(*bridge_wrapper) + strlen(bridge_name) + 1,
 		wait_bridge_wrapper_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
-
 	if (!bridge_wrapper) {
-		ast_bridge_destroy(bridge);
+		ast_bridge_destroy(bridge, 0);
 		return NULL;
 	}
 

Modified: trunk/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_confbridge.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/apps/app_confbridge.c (original)
+++ trunk/apps/app_confbridge.c Thu Aug 22 16:09:52 2013
@@ -892,7 +892,7 @@
 
 	/* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
 	if (conference->bridge) {
-		ast_bridge_destroy(conference->bridge);
+		ast_bridge_destroy(conference->bridge, 0);
 		conference->bridge = NULL;
 	}
 

Modified: trunk/apps/app_dial.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_dial.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/apps/app_dial.c (original)
+++ trunk/apps/app_dial.c Thu Aug 22 16:09:52 2013
@@ -3024,7 +3024,6 @@
 
 				ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0);
 			}
-/* BUGBUG bridge needs to set hangup cause on chan when peer breaks the bridge. */
 			setup_peer_after_bridge_goto(chan, peer, &opts, opt_args);
 			res = ast_bridge_call(chan, peer, &config);
 		}

Modified: trunk/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/bridges/bridge_builtin_features.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/bridges/bridge_builtin_features.c (original)
+++ trunk/bridges/bridge_builtin_features.c Thu Aug 22 16:09:52 2013
@@ -53,6 +53,7 @@
 #include "asterisk/monitor.h"
 #include "asterisk/mixmonitor.h"
 #include "asterisk/audiohook.h"
+#include "asterisk/causes.h"
 
 enum set_touch_variables_res {
 	SET_TOUCH_SUCCESS,
@@ -487,7 +488,8 @@
 	 * bridge_channel to force the channel out of the bridge and the
 	 * core takes care of the rest.
 	 */
-	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+		AST_CAUSE_NORMAL_CLEARING);
 	return 0;
 }
 

Modified: trunk/bridges/bridge_builtin_interval_features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/bridges/bridge_builtin_interval_features.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/bridges/bridge_builtin_interval_features.c (original)
+++ trunk/bridges/bridge_builtin_interval_features.c Thu Aug 22 16:09:52 2013
@@ -45,10 +45,10 @@
 #include "asterisk/app.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/test.h"
-
 #include "asterisk/say.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/musiconhold.h"
+#include "asterisk/causes.h"
 
 static int bridge_features_duration_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 {
@@ -58,9 +58,11 @@
 		ast_stream_and_wait(bridge_channel->chan, limits->duration_sound, AST_DIGIT_NONE);
 	}
 
-	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
-
-	ast_test_suite_event_notify("BRIDGE_TIMELIMIT", "Channel1: %s", ast_channel_name(bridge_channel->chan));
+	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END,
+		AST_CAUSE_NORMAL_CLEARING);
+
+	ast_test_suite_event_notify("BRIDGE_TIMELIMIT", "Channel1: %s",
+		ast_channel_name(bridge_channel->chan));
 	return -1;
 }
 

Modified: trunk/include/asterisk/bridge.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridge.h?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/include/asterisk/bridge.h (original)
+++ trunk/include/asterisk/bridge.h Thu Aug 22 16:09:52 2013
@@ -304,6 +304,8 @@
 	 * \note Temporary as in try again in a moment.
 	 */
 	unsigned int inhibit_merge;
+	/*! Cause code of the dissolved bridge. */
+	int cause;
 	/*! TRUE if the bridge was reconfigured. */
 	unsigned int reconfigured:1;
 	/*! TRUE if the bridge has been dissolved.  Any channel that now tries to join is immediately ejected. */
@@ -395,6 +397,7 @@
  * \brief Destroy a bridge
  *
  * \param bridge Bridge to destroy
+ * \param cause Cause of bridge being destroyed.  (If cause <= 0 then use AST_CAUSE_NORMAL_CLEARING)
  *
  * \retval 0 on success
  * \retval -1 on failure
@@ -402,12 +405,12 @@
  * Example usage:
  *
  * \code
- * ast_bridge_destroy(bridge);
+ * ast_bridge_destroy(bridge, AST_CAUSE_NORMAL_CLEARING);
  * \endcode
  *
  * This destroys a bridge that was previously created.
  */
-int ast_bridge_destroy(struct ast_bridge *bridge);
+int ast_bridge_destroy(struct ast_bridge *bridge, int cause);
 
 /*!
  * \brief Notify bridging that this channel was just masqueraded.

Modified: trunk/include/asterisk/bridge_channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridge_channel.h?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/include/asterisk/bridge_channel.h (original)
+++ trunk/include/asterisk/bridge_channel.h Thu Aug 22 16:09:52 2013
@@ -239,36 +239,40 @@
  *
  * \param bridge_channel Channel to change the state on
  * \param new_state The new state to place the channel into
+ * \param cause Cause of channel leaving bridge.
+ *   If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.
  *
  * Example usage:
  *
  * \code
- * ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+ * ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, AST_CAUSE_NORMAL_CLEARING);
  * \endcode
  *
  * This places the channel pointed to by bridge_channel into the
  * state BRIDGE_CHANNEL_STATE_END if it was
  * BRIDGE_CHANNEL_STATE_WAIT before.
  */
-void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state);
+void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause);
 
 /*!
  * \brief Set bridge channel state to leave bridge (if not leaving already).
  *
  * \param bridge_channel Channel to change the state on
  * \param new_state The new state to place the channel into
+ * \param cause Cause of channel leaving bridge.
+ *   If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.
  *
  * Example usage:
  *
  * \code
- * ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+ * ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, AST_CAUSE_NORMAL_CLEARING);
  * \endcode
  *
  * This places the channel pointed to by bridge_channel into the
  * state BRIDGE_CHANNEL_STATE_END if it was
  * BRIDGE_CHANNEL_STATE_WAIT before.
  */
-void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state);
+void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause);
 
 /*!
  * \brief Get the peer bridge channel of a two party bridge.
@@ -599,13 +603,15 @@
  * \since 12.0.0
  *
  * \param bridge_channel Which channel is being kicked or hungup.
+ * \param cause Cause of channel being kicked.
+ *   If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.
  *
  * \note This is intended to be called by bridge hooks and the
  * bridge channel thread.
  *
  * \return Nothing
  */
-void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel);
+void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel, int cause);
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }

Modified: trunk/include/asterisk/bridge_internal.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridge_internal.h?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/include/asterisk/bridge_internal.h (original)
+++ trunk/include/asterisk/bridge_internal.h Thu Aug 22 16:09:52 2013
@@ -198,6 +198,7 @@
  * \since 12.0.0
  *
  * \param bridge Bridge to eject all channels
+ * \param cause Cause of bridge being dissolved.  (If cause <= 0 then use AST_CAUSE_NORMAL_CLEARING)
  *
  * \details
  * Force out all channels that are not already going out of the
@@ -207,6 +208,6 @@
  *
  * \return Nothing
  */
-void bridge_dissolve(struct ast_bridge *bridge);
+void bridge_dissolve(struct ast_bridge *bridge, int cause);
 
 #endif /* _ASTERISK_PRIVATE_BRIDGING_H */

Modified: trunk/main/bridge.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/main/bridge.c (original)
+++ trunk/main/bridge.c Thu Aug 22 16:09:52 2013
@@ -55,7 +55,6 @@
 #include "asterisk/pbx.h"
 #include "asterisk/test.h"
 #include "asterisk/_private.h"
-
 #include "asterisk/heap.h"
 #include "asterisk/say.h"
 #include "asterisk/timing.h"
@@ -66,6 +65,7 @@
 #include "asterisk/parking.h"
 #include "asterisk/core_local.h"
 #include "asterisk/core_unreal.h"
+#include "asterisk/causes.h"
 
 /*! All bridges container. */
 static struct ao2_container *bridges;
@@ -241,22 +241,7 @@
 	return 0;
 }
 
-/*!
- * \internal
- * \brief Dissolve the bridge.
- * \since 12.0.0
- *
- * \param bridge Bridge to eject all channels
- *
- * \details
- * Force out all channels that are not already going out of the
- * bridge.  Any new channels joining will leave immediately.
- *
- * \note On entry, bridge is already locked.
- *
- * \return Nothing
- */
-void bridge_dissolve(struct ast_bridge *bridge)
+void bridge_dissolve(struct ast_bridge *bridge, int cause)
 {
 	struct ast_bridge_channel *bridge_channel;
 	struct ast_frame action = {
@@ -269,11 +254,17 @@
 	}
 	bridge->dissolved = 1;
 
-	ast_debug(1, "Bridge %s: dissolving bridge\n", bridge->uniqueid);
-
-/* BUGBUG need a cause code on the bridge for the later ejected channels. */
+	if (cause <= 0) {
+		cause = AST_CAUSE_NORMAL_CLEARING;
+	}
+	bridge->cause = cause;
+
+	ast_debug(1, "Bridge %s: dissolving bridge with cause %d(%s)\n",
+		bridge->uniqueid, cause, ast_cause2str(cause));
+
 	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+		ast_bridge_channel_leave_bridge(bridge_channel,
+			BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, cause);
 	}
 
 	/* Must defer dissolving bridge because it is already locked. */
@@ -302,7 +293,7 @@
 		&& ast_test_flag(&bridge_channel->features->feature_flags,
 			AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP)) {
 		/* The stolen channel controlled the bridge it was stolen from. */
-		bridge_dissolve(bridge);
+		bridge_dissolve(bridge, 0);
 		return;
 	}
 	if (bridge->num_channels < 2
@@ -311,7 +302,7 @@
 		 * The stolen channel has not left enough channels to keep the
 		 * bridge alive.  Assume the stolen channel hung up.
 		 */
-		bridge_dissolve(bridge);
+		bridge_dissolve(bridge, 0);
 		return;
 	}
 }
@@ -648,7 +639,7 @@
 		bridge->construction_completed = 1;
 		ast_bridge_publish_state(bridge);
 		if (!ao2_link(bridges, bridge)) {
-			ast_bridge_destroy(bridge);
+			ast_bridge_destroy(bridge, 0);
 			bridge = NULL;
 		}
 	}
@@ -852,11 +843,11 @@
 	return bridge;
 }
 
-int ast_bridge_destroy(struct ast_bridge *bridge)
+int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
 {
 	ast_debug(1, "Bridge %s: telling all channels to leave the party\n", bridge->uniqueid);
 	ast_bridge_lock(bridge);
-	bridge_dissolve(bridge);
+	bridge_dissolve(bridge, cause);
 	ast_bridge_unlock(bridge);
 
 	ao2_ref(bridge, -1);
@@ -1366,7 +1357,7 @@
 	if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART)
 		&& smart_bridge_operation(bridge)) {
 		/* Smart bridge failed. */
-		bridge_dissolve(bridge);
+		bridge_dissolve(bridge, 0);
 		return;
 	}
 	bridge_complete_join(bridge);
@@ -1652,7 +1643,8 @@
 	 * channel thread.
 	 */
 
-	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+	ast_bridge_channel_leave_bridge(bridge_channel,
+		BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
 
 	/* Wait for the depart thread to die */
 	ast_debug(1, "Waiting for %p(%s) bridge thread to die.\n",
@@ -1680,7 +1672,8 @@
 		return -1;
 	}
 
-	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+	ast_bridge_channel_leave_bridge(bridge_channel,
+		BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
 
 	ast_bridge_unlock(bridge);
 
@@ -1689,7 +1682,7 @@
 
 static void kick_it(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
 {
-	ast_bridge_channel_kick(bridge_channel);
+	ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
 }
 
 int ast_bridge_kick(struct ast_bridge *bridge, struct ast_channel *chan)
@@ -1770,7 +1763,8 @@
 		if (kick_me) {
 			for (idx = 0; idx < num_kick; ++idx) {
 				if (bridge_channel == kick_me[idx]) {
-					ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+					ast_bridge_channel_leave_bridge(bridge_channel,
+						BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
 					break;
 				}
 			}
@@ -1788,7 +1782,8 @@
 		bridge_channel_change_bridge(bridge_channel, dst_bridge);
 
 		if (bridge_channel_internal_push(bridge_channel)) {
-			ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+			ast_bridge_channel_leave_bridge(bridge_channel,
+				BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
 		}
 	}
 	AST_LIST_TRAVERSE_SAFE_END;
@@ -1802,7 +1797,8 @@
 			bridge_channel = kick_me[idx];
 			ast_bridge_channel_lock(bridge_channel);
 			if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
-				ast_bridge_channel_leave_bridge_nolock(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+				ast_bridge_channel_leave_bridge_nolock(bridge_channel,
+					BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
 				bridge_channel_internal_pull(bridge_channel);
 			}
 			ast_bridge_channel_unlock(bridge_channel);
@@ -2036,10 +2032,12 @@
 			bridge_channel_change_bridge(bridge_channel, orig_bridge);
 
 			if (bridge_channel_internal_push(bridge_channel)) {
-				ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+				ast_bridge_channel_leave_bridge(bridge_channel,
+					BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
 			}
 		} else {
-			ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+			ast_bridge_channel_leave_bridge(bridge_channel,
+				BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
 		}
 		res = -1;
 	}
@@ -2452,7 +2450,8 @@
 		}
 		other->swap = dst_bridge_channel->chan;
 		if (!bridge_do_move(dst_bridge, other, 1, 1)) {
-			ast_bridge_channel_leave_bridge(src_bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+			ast_bridge_channel_leave_bridge(src_bridge_channel,
+				BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
 			res = -1;
 		}
 		if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
@@ -4063,7 +4062,8 @@
 			return AST_BRIDGE_TRANSFER_FAIL;
 		}
 		/* Must kick the source channel out of its bridge. */
-		ast_bridge_channel_leave_bridge(source_bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+		ast_bridge_channel_leave_bridge(source_bridge_channel,
+			BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
 		return AST_BRIDGE_TRANSFER_SUCCESS;
 	} else {
 		return AST_BRIDGE_TRANSFER_INVALID;
@@ -4619,7 +4619,7 @@
 	}
 
 	ast_cli(a->fd, "Destroying bridge '%s'\n", a->argv[2]);
-	ast_bridge_destroy(bridge);
+	ast_bridge_destroy(bridge, 0);
 
 	return CLI_SUCCESS;
 }

Modified: trunk/main/bridge_basic.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge_basic.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/main/bridge_basic.c (original)
+++ trunk/main/bridge_basic.c Thu Aug 22 16:09:52 2013
@@ -299,7 +299,8 @@
 	}
 	if (2 <= bridge_count) {
 		/* Just allow this channel to leave the multi-party bridge. */
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+		ast_bridge_channel_leave_bridge(bridge_channel,
+			BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, 0);
 	}
 	ast_bridge_unlock(bridge_channel->bridge);
 	return 0;
@@ -1488,7 +1489,7 @@
 	}
 
 	if (props->target_bridge) {
-		ast_bridge_destroy(props->target_bridge);
+		ast_bridge_destroy(props->target_bridge, 0);
 		props->target_bridge = NULL;
 	}
 
@@ -2454,7 +2455,7 @@
 static int fail_enter(struct attended_transfer_properties *props)
 {
 	if (props->transferee_bridge) {
-		ast_bridge_destroy(props->transferee_bridge);
+		ast_bridge_destroy(props->transferee_bridge, 0);
 		props->transferee_bridge = NULL;
 	}
 	return 0;

Modified: trunk/main/bridge_channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge_channel.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/main/bridge_channel.c (original)
+++ trunk/main/bridge_channel.c Thu Aug 22 16:09:52 2013
@@ -53,6 +53,7 @@
 #include "asterisk/musiconhold.h"
 #include "asterisk/features_config.h"
 #include "asterisk/parking.h"
+#include "asterisk/causes.h"
 
 /*!
  * \brief Used to queue an action frame onto a bridge channel and write an action frame into a bridge.
@@ -101,13 +102,6 @@
 	return ast_bridge_channel_queue_frame(bridge_channel, &action);
 }
 
-void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state)
-{
-	ast_bridge_channel_lock(bridge_channel);
-	ast_bridge_channel_leave_bridge_nolock(bridge_channel, new_state);
-	ast_bridge_channel_unlock(bridge_channel);
-}
-
 /*!
  * \internal
  * \brief Poke the bridge_channel thread
@@ -122,9 +116,33 @@
 	}
 }
 
-void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state)
-{
-/* BUGBUG need cause code for the bridge_channel leaving the bridge. */
+/*!
+ * \internal
+ * \brief Set actual cause on channel.
+ * \since 12.0.0
+ *
+ * \param chan Channel to set cause.
+ * \param cause Cause to set on channel.
+ *   If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.
+ *
+ * \return Actual cause set on channel.
+ */
+static int channel_set_cause(struct ast_channel *chan, int cause)
+{
+	ast_channel_lock(chan);
+	if (cause <= 0) {
+		cause = ast_channel_hangupcause(chan);
+		if (cause <= 0) {
+			cause = AST_CAUSE_NORMAL_CLEARING;
+		}
+	}
+	ast_channel_hangupcause_set(chan, cause);
+	ast_channel_unlock(chan);
+	return cause;
+}
+
+void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
+{
 	if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
 		return;
 	}
@@ -133,10 +151,19 @@
 		bridge_channel, ast_channel_name(bridge_channel->chan), bridge_channel->state,
 		new_state);
 
+	channel_set_cause(bridge_channel->chan, cause);
+
 	/* Change the state on the bridge channel */
 	bridge_channel->state = new_state;
 
 	bridge_channel_poke(bridge_channel);
+}
+
+void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
+{
+	ast_bridge_channel_lock(bridge_channel);
+	ast_bridge_channel_leave_bridge_nolock(bridge_channel, new_state, cause);
+	ast_bridge_channel_unlock(bridge_channel);
 }
 
 struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel)
@@ -263,11 +290,18 @@
 	}
 }
 
-void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel)
+void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel, int cause)
 {
 	struct ast_bridge_features *features = bridge_channel->features;
 	struct ast_bridge_hook *hook;
 	struct ao2_iterator iter;
+
+	ast_bridge_channel_lock(bridge_channel);
+	if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
+		channel_set_cause(bridge_channel->chan, cause);
+		cause = 0;
+	}
+	ast_bridge_channel_unlock(bridge_channel);
 
 	/* Run any hangup hooks. */
 	iter = ao2_iterator_init(features->other_hooks, 0);
@@ -287,7 +321,7 @@
 	ao2_iterator_destroy(&iter);
 
 	/* Default hangup action. */
-	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
+	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, cause);
 }
 
 /*!
@@ -595,7 +629,7 @@
 	}
 	if (run_app_helper(bridge_channel->chan, app_name, S_OR(app_args, ""))) {
 		/* Break the bridge if the app returns non-zero. */
-		ast_bridge_channel_kick(bridge_channel);
+		ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
 	}
 	if (moh_class) {
 		ast_bridge_channel_write_unhold(bridge_channel);
@@ -1106,7 +1140,7 @@
 		 * here if the hook did not already change the state.
 		 */
 		if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
-			ast_bridge_channel_kick(bridge_channel);
+			ast_bridge_channel_kick(bridge_channel, 0);
 		}
 	} else if (features->dtmf_passthrough) {
 		/* Stream any collected DTMF to the other channels. */
@@ -1219,7 +1253,7 @@
 		struct blind_transfer_data *blind_data)
 {
 	ast_async_goto(bridge_channel->chan, blind_data->context, blind_data->exten, 1);
-	ast_bridge_channel_kick(bridge_channel);
+	ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
 }
 
 /*!
@@ -1235,7 +1269,7 @@
 	chan_target = ast_channel_get_by_name(target_chan_name);
 	if (!chan_target) {
 		/* Dang, it disappeared somehow */
-		ast_bridge_channel_kick(bridge_channel);
+		ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
 		return;
 	}
 
@@ -1252,7 +1286,7 @@
 		/* Release the ref we tried to pass to ast_bridge_set_after_callback(). */
 		ast_channel_unref(chan_target);
 	}
-	ast_bridge_channel_kick(bridge_channel);
+	ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
 }
 
 /*!
@@ -1337,7 +1371,7 @@
 	if (!bridge->num_channels
 		&& ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_EMPTY)) {
 		/* Last channel leaving the bridge turns off the lights. */
-		bridge_dissolve(bridge);
+		bridge_dissolve(bridge, ast_channel_hangupcause(bridge_channel->chan));
 		return;
 	}
 
@@ -1348,7 +1382,7 @@
 			|| (bridge_channel->features->usable
 				&& ast_test_flag(&bridge_channel->features->feature_flags,
 					AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP))) {
-			bridge_dissolve(bridge);
+			bridge_dissolve(bridge, ast_channel_hangupcause(bridge_channel->chan));
 			return;
 		}
 		break;
@@ -1357,9 +1391,14 @@
 	}
 
 	if (bridge->num_lonely && bridge->num_lonely == bridge->num_channels) {
-		/* This will start a chain reaction where each channel leaving enters this function and causes
-		 * the next to leave as long as there aren't non-lonely channels in the bridge. */
-		ast_bridge_channel_leave_bridge(AST_LIST_FIRST(&bridge->channels), BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+		/*
+		 * This will start a chain reaction where each channel leaving
+		 * enters this function and causes the next to leave as long as
+		 * there aren't non-lonely channels in the bridge.
+		 */
+		ast_bridge_channel_leave_bridge(AST_LIST_FIRST(&bridge->channels),
+			BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE,
+			ast_channel_hangupcause(bridge_channel->chan));
 	}
 }
 
@@ -1473,7 +1512,7 @@
 
 	ast_bridge_publish_enter(bridge, bridge_channel->chan, swap ? swap->chan : NULL);
 	if (swap) {
-		ast_bridge_channel_leave_bridge(swap, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+		ast_bridge_channel_leave_bridge(swap, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, 0);
 		bridge_channel_internal_pull(swap);
 	}
 
@@ -1671,14 +1710,14 @@
 	}
 
 	if (!frame) {
-		ast_bridge_channel_kick(bridge_channel);
+		ast_bridge_channel_kick(bridge_channel, 0);
 		return;
 	}
 	switch (frame->frametype) {
 	case AST_FRAME_CONTROL:
 		switch (frame->subclass.integer) {
 		case AST_CONTROL_HANGUP:
-			ast_bridge_channel_kick(bridge_channel);
+			ast_bridge_channel_kick(bridge_channel, 0);
 			ast_frfree(frame);
 			return;
 /* BUGBUG This is where incoming HOLD/UNHOLD memory should register.  Write UNHOLD into bridge when this channel is pulled. */
@@ -1885,7 +1924,8 @@
 	}
 
 	if (bridge_channel_internal_push(bridge_channel)) {
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+		ast_bridge_channel_leave_bridge(bridge_channel,
+			BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
 		res = -1;
 	}
 	bridge_reconfigured(bridge_channel->bridge, 1);

Modified: trunk/main/features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/features.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/main/features.c (original)
+++ trunk/main/features.c Thu Aug 22 16:09:52 2013
@@ -676,7 +676,7 @@
 
 	/* Put peer into the bridge */
 	if (ast_bridge_impart(bridge, peer, NULL, peer_features, 1)) {
-		ast_bridge_destroy(bridge);
+		ast_bridge_destroy(bridge, 0);
 		ast_bridge_features_cleanup(&chan_features);
 		bridge_failed_peer_goto(chan, peer);
 		return -1;
@@ -829,7 +829,7 @@
 	if (ast_bridge_add_channel(bridge, chana, NULL, playtone & PLAYTONE_CHANNEL1, xfer_cfg_a ? xfer_cfg_a->xfersound : NULL)) {
 		snprintf(buf, sizeof(buf), "Unable to add Channel1 to bridge: %s", ast_channel_name(chana));
 		astman_send_error(s, m, buf);
-		ast_bridge_destroy(bridge);
+		ast_bridge_destroy(bridge, 0);
 		return 0;
 	}
 
@@ -837,7 +837,7 @@
 	if (ast_bridge_add_channel(bridge, chanb, NULL, playtone & PLAYTONE_CHANNEL2, xfer_cfg_b ? xfer_cfg_b->xfersound : NULL)) {
 		snprintf(buf, sizeof(buf), "Unable to add Channel2 to bridge: %s", ast_channel_name(chanb));
 		astman_send_error(s, m, buf);
-		ast_bridge_destroy(bridge);
+		ast_bridge_destroy(bridge, 0);
 		return 0;
 	}
 
@@ -1125,7 +1125,7 @@
 		ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE), xfer_cfg ? xfer_cfg->xfersound : NULL)) {
 		ast_bridge_features_destroy(peer_features);
 		ast_bridge_features_cleanup(&chan_features);
-		ast_bridge_destroy(bridge);
+		ast_bridge_destroy(bridge, 0);
 		goto done;
 	}
 

Modified: trunk/res/parking/parking_applications.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/parking/parking_applications.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/res/parking/parking_applications.c (original)
+++ trunk/res/parking/parking_applications.c Thu Aug 22 16:09:52 2013
@@ -618,14 +618,14 @@
 
 	/* Move the parkee into the new bridge */
 	if (ast_bridge_move(retrieval_bridge, lot->parking_bridge, pu->chan, NULL, 0)) {
-		ast_bridge_destroy(retrieval_bridge);
+		ast_bridge_destroy(retrieval_bridge, 0);
 		return -1;
 	}
 
 	/* Initialize our bridge features */
 	res = ast_bridge_features_init(&chan_features);
 	if (res) {
-		ast_bridge_destroy(retrieval_bridge);
+		ast_bridge_destroy(retrieval_bridge, 0);
 		ast_bridge_features_cleanup(&chan_features);
 		return -1;
 	}

Modified: trunk/res/parking/parking_bridge_features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/parking/parking_bridge_features.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/res/parking/parking_bridge_features.c (original)
+++ trunk/res/parking/parking_bridge_features.c Thu Aug 22 16:09:52 2013
@@ -42,6 +42,7 @@
 #include "asterisk/stasis.h"
 #include "asterisk/module.h"
 #include "asterisk/core_local.h"
+#include "asterisk/causes.h"
 
 struct parked_subscription_datastore {
 	struct stasis_subscription *parked_subscription;
@@ -483,7 +484,8 @@
 	user->resolution = PARK_TIMEOUT;
 	ao2_unlock(user);
 
-	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+	ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE,
+		AST_CAUSE_NORMAL_CLEARING);
 
 	/* Set parking timeout channel variables */
 	snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
@@ -571,14 +573,17 @@
 	if (sscanf(payload, "%u %u", &hangup_after, &numeric_value) != 2) {
 		/* If say_parking_space is called with a non-numeric string, we have a problem. */
 		ast_assert(0);
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+		ast_bridge_channel_leave_bridge(bridge_channel,
+			BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
 		return;
 	}
 
-	ast_say_digits(bridge_channel->chan, numeric_value, "", ast_channel_language(bridge_channel->chan));
+	ast_say_digits(bridge_channel->chan, numeric_value, "",
+		ast_channel_language(bridge_channel->chan));
 
 	if (hangup_after) {
-		ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
+		ast_bridge_channel_leave_bridge(bridge_channel,
+			BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
 	}
 }
 

Modified: trunk/res/res_parking.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_parking.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/res/res_parking.c (original)
+++ trunk/res/res_parking.c Thu Aug 22 16:09:52 2013
@@ -580,7 +580,7 @@
 	struct parking_lot *lot = obj;
 
 	if (lot->parking_bridge) {
-		ast_bridge_destroy(lot->parking_bridge);
+		ast_bridge_destroy(lot->parking_bridge, 0);
 	}
 	ao2_cleanup(lot->parked_users);
 	ao2_cleanup(lot->cfg);

Modified: trunk/res/res_stasis.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_stasis.c?view=diff&rev=397472&r1=397471&r2=397472
==============================================================================
--- trunk/res/res_stasis.c (original)
+++ trunk/res/res_stasis.c Thu Aug 22 16:09:52 2013
@@ -471,7 +471,7 @@
 		return;
 	}
 	ao2_unlink(app_bridges, bridge);
-	ast_bridge_destroy(bridge);
+	ast_bridge_destroy(bridge, 0);
 }
 
 int app_send_start_msg(struct app *app, struct ast_channel *chan,




More information about the asterisk-commits mailing list