[asterisk-commits] jrose: branch jrose/bridge_projects r386991 - in /team/jrose/bridge_projects:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Apr 30 13:13:56 CDT 2013


Author: jrose
Date: Tue Apr 30 13:13:52 2013
New Revision: 386991

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386991
Log:
address comments by Richard on 4/29

Modified:
    team/jrose/bridge_projects/CHANGES
    team/jrose/bridge_projects/include/asterisk/features.h
    team/jrose/bridge_projects/include/asterisk/parking.h
    team/jrose/bridge_projects/main/bridging.c
    team/jrose/bridge_projects/main/features.c
    team/jrose/bridge_projects/main/parking.c
    team/jrose/bridge_projects/res/parking/parking_applications.c
    team/jrose/bridge_projects/res/parking/parking_bridge.c
    team/jrose/bridge_projects/res/parking/parking_bridge_features.c
    team/jrose/bridge_projects/res/parking/parking_controller.c
    team/jrose/bridge_projects/res/parking/parking_manager.c
    team/jrose/bridge_projects/res/parking/res_parking.h
    team/jrose/bridge_projects/res/res_parking.c

Modified: team/jrose/bridge_projects/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/CHANGES?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/CHANGES (original)
+++ team/jrose/bridge_projects/CHANGES Tue Apr 30 13:13:52 2013
@@ -54,7 +54,7 @@
    'UnParkedCall' have changed significantly in the new res_parking module.
    First, channel snapshot data is included for both the parker and the parkee
    in lieu of the "From" and "Channel" fields. They follow standard channel
-   snapshot format but each field is suffixed with '(parker)' or '(parkee)'
+   snapshot format but each field is suffixed with 'Parker' or 'Parkee'
    depending on which side it applies to. The 'Exten' field is replaced with
    'ParkingSpace' since the registration of extensions as for parking spaces
    is no longer mandatory.

Modified: team/jrose/bridge_projects/include/asterisk/features.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/features.h?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/features.h (original)
+++ team/jrose/bridge_projects/include/asterisk/features.h Tue Apr 30 13:13:52 2013
@@ -26,7 +26,6 @@
 
 #include "asterisk/pbx.h"
 #include "asterisk/linkedlists.h"
-#include "asterisk/bridging.h"
 
 #define FEATURE_MAX_LEN		11
 #define FEATURE_APP_LEN		64

Modified: team/jrose/bridge_projects/include/asterisk/parking.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/parking.h?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/parking.h (original)
+++ team/jrose/bridge_projects/include/asterisk/parking.h Tue Apr 30 13:13:52 2013
@@ -121,14 +121,16 @@
 	const char *parker_uuid,
 	const char *app_data);
 
+typedef int (*ast_park_blind_xfer_fn)(struct ast_bridge *bridge, struct ast_bridge_channel *parker,
+	struct ast_exten *park_exten);
+
 /*!
  * \brief install a callback for handling blind transfers to a parking extension
  * \since 12
  *
  * \param parking_func Function to use for transfers to 'Park' applications
  */
-void ast_install_park_blind_xfer_func(int (*park_blind_xfer_func)(struct ast_bridge *bridge, struct ast_bridge_channel *parker,
-		struct ast_exten *park_exten));
+void ast_install_park_blind_xfer_func(ast_park_blind_xfer_fn park_blind_xfer_func);
 
 /*!
  * \brief uninstall a callback for handling blind transfers to a parking extension
@@ -150,14 +152,16 @@
 int ast_park_blind_xfer(struct ast_bridge *bridge, struct ast_bridge_channel *parker,
 		struct ast_exten *park_exten);
 
+typedef void (*ast_bridge_channel_park_fn)(struct ast_bridge_channel *parkee, const char *parkee_uuid,
+	const char *parker_uuid, const char *app_data);
+
 /*!
  * \brief Install a function for ast_bridge_channel_park
  * \since 12
  *
  * \param bridge_channel_park_func function callback to use for ast_bridge_channel_park
  */
-void ast_install_bridge_channel_park_func(void (*bridge_channel_park_func)(struct ast_bridge_channel *parkee,
-	const char *parkee_uuid, const char *parker_uuid, const char *app_data));
+void ast_install_bridge_channel_park_func(ast_bridge_channel_park_fn bridge_channel_park_func);
 
 /*!
  * \brief Uninstall the ast_bridge_channel_park function callback

Modified: team/jrose/bridge_projects/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/bridging.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/main/bridging.c (original)
+++ team/jrose/bridge_projects/main/bridging.c Tue Apr 30 13:13:52 2013
@@ -515,8 +515,6 @@
 		}
 	}
 
-	ast_bridge_channel_clear_roles(bridge_channel);
-
 	/* Remove channel from the bridge */
 	if (!bridge_channel->suspended) {
 		--bridge->num_active;
@@ -524,6 +522,8 @@
 	--bridge->num_channels;
 	AST_LIST_REMOVE(&bridge->channels, bridge_channel, entry);
 	bridge->v_table->pull(bridge, bridge_channel);
+
+	ast_bridge_channel_clear_roles(bridge_channel);
 
 	bridge_dissolve_check(bridge_channel);
 
@@ -563,15 +563,14 @@
 	}
 
 	/* Add channel to the bridge */
-	if (ast_bridge_channel_establish_roles(bridge_channel)
-		|| bridge->dissolved
+	if (bridge->dissolved
 		|| bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT
-		|| bridge->v_table->push(bridge, bridge_channel, swap)) {
+		|| bridge->v_table->push(bridge, bridge_channel, swap)
+		|| ast_bridge_channel_establish_roles(bridge_channel)) {
 		ast_debug(1, "Bridge %s: pushing %p(%s) into bridge failed\n",
 			bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
 		return -1;
 	}
-
 	bridge_channel->in_bridge = 1;
 	bridge_channel->just_joined = 1;
 	AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
@@ -915,7 +914,9 @@
 
 static void bridge_channel_park(struct ast_bridge_channel *bridge_channel, struct bridge_park *payload)
 {
-	ast_bridge_channel_park(bridge_channel, payload->parkee_uuid, &payload->parkee_uuid[payload->parker_uuid_offset], payload->app_data_offset ? &payload->parkee_uuid[payload->app_data_offset] : NULL);
+	ast_bridge_channel_park(bridge_channel, payload->parkee_uuid,
+		&payload->parkee_uuid[payload->parker_uuid_offset],
+		payload->app_data_offset ? &payload->parkee_uuid[payload->app_data_offset] : NULL);
 }
 
 static void payload_helper_park(ast_bridge_channel_post_action_data post_it,

Modified: team/jrose/bridge_projects/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/features.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/main/features.c (original)
+++ team/jrose/bridge_projects/main/features.c Tue Apr 30 13:13:52 2013
@@ -250,7 +250,6 @@
 			</variablelist>
 		</description>
 	</application>
-
 	<manager name="Park" language="en_US">
 		<synopsis>
 			Park a channel.
@@ -8213,4 +8212,3 @@
 
 	return res;
 }
-

Modified: team/jrose/bridge_projects/main/parking.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/parking.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/main/parking.c (original)
+++ team/jrose/bridge_projects/main/parking.c Tue Apr 30 13:13:52 2013
@@ -41,12 +41,10 @@
 static struct stasis_topic *parking_topic;
 
 /*! \brief Function Callback for handling blind transfers to park applications */
-static int (*ast_park_blind_xfer_func)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel,
-		struct ast_exten *park_exten) = NULL;
+static ast_park_blind_xfer_fn ast_park_blind_xfer_func = NULL;
 
 /*! \brief Function Callback for handling a bridge channel trying to park itself */
-static void (*ast_bridge_channel_park_func)(struct ast_bridge_channel *parkee, const char *parkee_uuid,
-		const char *parker_uuid, const char *app_data) = NULL;
+static ast_bridge_channel_park_fn ast_bridge_channel_park_func = NULL;
 
 void ast_parking_stasis_init(void)
 {
@@ -127,14 +125,12 @@
 	return payload;
 }
 
-void ast_install_park_blind_xfer_func(int (*park_blind_xfer_func)(struct ast_bridge *bridge, struct ast_bridge_channel *parker,
-	struct ast_exten *park_exten))
+void ast_install_park_blind_xfer_func(ast_park_blind_xfer_fn park_blind_xfer_func)
 {
 	ast_park_blind_xfer_func = park_blind_xfer_func;
 }
 
-void ast_install_bridge_channel_park_func(void (*bridge_channel_park_func)(struct ast_bridge_channel *parkee,
-	const char *parkee_uuid, const char *parker_uuid, const char *app_data))
+void ast_install_bridge_channel_park_func(ast_bridge_channel_park_fn bridge_channel_park_func)
 {
 	ast_bridge_channel_park_func = bridge_channel_park_func;
 }

Modified: team/jrose/bridge_projects/res/parking/parking_applications.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_applications.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_applications.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_applications.c Tue Apr 30 13:13:52 2013
@@ -298,36 +298,29 @@
 	ast_channel_unlock(parkee);
 }
 
-struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_channel *parker, const char *app_data)
+struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_channel *parker, const char *app_data, int *silence_announcements)
 {
 	int use_ringing = 0;
 	int randomize = 0;
 	int time_limit = -1;
 	char *lot_name;
 
-	int silence_announcements = 0;
-
 	struct ast_bridge *parking_bridge;
 	RAII_VAR(char *, comeback_override, NULL, ast_free);
 	RAII_VAR(char *, lot_name_app_arg, NULL, ast_free);
 	RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
 
 	if (app_data) {
-		park_app_parse_data(app_data, &silence_announcements, &use_ringing, &randomize, &time_limit, &comeback_override, &lot_name_app_arg);
+		park_app_parse_data(app_data, silence_announcements, &use_ringing, &randomize, &time_limit, &comeback_override, &lot_name_app_arg);
 	}
 
 	lot_name = lot_name_app_arg;
 
-	/* If the name of the aprking lot isn't specified in the arguments, find it based on the channel. */
+	/* If the name of the parking lot isn't specified in the arguments, find it based on the channel. */
 	if (ast_strlen_zero(lot_name)) {
 		ast_channel_lock(parker);
 		lot_name = ast_strdupa(find_channel_parking_lot_name(parker));
 		ast_channel_unlock(parker);
-
-		/* If the name couldn't be pulled from that either, use the default parking lot name. */
-		if (ast_strlen_zero(lot_name)) {
-			lot_name = DEFAULT_PARKING_LOT;
-		}
 	}
 
 	lot = parking_lot_find_by_name(lot_name);
@@ -344,7 +337,8 @@
 	if (parking_bridge) {
 		/* Apply relevant bridge roles and such to the parking channel */
 		parking_channel_set_roles(parkee, lot, use_ringing);
-		setup_park_common_datastore(parkee, ast_channel_uniqueid(parker), randomize, time_limit, silence_announcements);
+		setup_park_common_datastore(parkee, ast_channel_uniqueid(parker), randomize, time_limit,
+			silence_announcements ? *silence_announcements : 0);
 		return parking_bridge;
 	}
 
@@ -356,20 +350,13 @@
  *     Currently all parking by the park application is treated as calls parking themselves.
  *     However, it's possible for calls to be transferred here when the Park application is
  *     set after the first priority of an extension. In that case, there used to be a variable
- *     (BLINDTRANSFER) set indicating which channel placed that call here, but that channel may
- *     be gone already by the time the application executes, so just knowing the name of that
- *     channel won't be enough.
- *
- *     It will be necessary to find a way to handle that for the purpose of comebacktoorigin
- *     on parked call timeouts as well as for generating proper Parker information in stasis.
- *     One way to do this might be to store a snapshot of the transferer on the channel when
- *     performing transfers. Then if the parker is the same as the parkee when calling
- *     park_common_setup, the parkee's channel can be checked for that snapshot and then
- *     referenced accordingly. Alternatively, this could simply be left as is and the parkee
- *     could just be treated as the parkee (in many ways in these scenarios, the parkee really
- *     is parking itself since the channel that transferred isn't really involved in executing
- *     the park at this point) and the BLINDTRANSFER variable could just be used as data for
- *     generating the comebacktoorigin location and extensions.
+ *     (BLINDTRANSFER) set indicating which channel placed that call here.
+ *
+ *     If BLINDTRANSFER is set, this channel name will need to be referenced in Park events
+ *     generated by stasis. Ideally we would get a whole channel snapshot and use that for the
+ *     parker, but that would likely require applying the channel snapshot to a channel datastore
+ *     on all transfers. Alternatively just the name of the parking channel could be applied along
+ *     with an indication that it's dead.
  */
 int park_app_exec(struct ast_channel *chan, const char *data)
 {
@@ -377,16 +364,25 @@
 
 	struct ast_bridge_features chan_features;
 	int res;
+	int silence_announcements;
+	const char *blind_transfer;
 
 	/* answer the channel if needed */
 	if (ast_channel_state(chan) != AST_STATE_UP) {
 		ast_answer(chan);
 	}
 
+	ast_channel_lock(chan);
+	if ((blind_transfer = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"))) {
+		blind_transfer = ast_strdupa(blind_transfer);
+	}
+	ast_channel_unlock(chan);
+
 	/* Handle the common parking setup stuff */
-	if (!(parking_bridge = park_common_setup(chan, chan, data))) {
-		ast_log(LOG_NOTICE, "bleh?\n");
-		ast_stream_and_wait(chan, "pbx-parkingfailed", "");
+	if (!(parking_bridge = park_common_setup(chan, chan, data, &silence_announcements))) {
+		if (!silence_announcements && !blind_transfer) {
+			ast_stream_and_wait(chan, "pbx-parkingfailed", "");
+		}
 		return 0;
 	}
 
@@ -446,16 +442,11 @@
 
 	lot_name = args.lot_name;
 
-	/* If the name of the aprking lot isn't in the arguments, find it based on the channel. */
+	/* If the name of the parking lot isn't in the arguments, find it based on the channel. */
 	if (ast_strlen_zero(lot_name)) {
 		ast_channel_lock(chan);
 		lot_name = ast_strdupa(find_channel_parking_lot_name(chan));
 		ast_channel_unlock(chan);
-	}
-
-	/* If the name couldn't be pulled from that either, use the default parking lot name. */
-	if (ast_strlen_zero(lot_name)) {
-		lot_name = DEFAULT_PARKING_LOT;
 	}
 
 	lot = parking_lot_find_by_name(lot_name);
@@ -499,6 +490,7 @@
 	/* Initialize our bridge features */
 	res = ast_bridge_features_init(&chan_features);
 	if (res) {
+		ast_bridge_destroy(retrieval_bridge);
 		ast_bridge_features_cleanup(&chan_features);
 		return -1;
 	}

Modified: team/jrose/bridge_projects/res/parking/parking_bridge.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_bridge.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_bridge.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_bridge.c Tue Apr 30 13:13:52 2013
@@ -58,14 +58,14 @@
 {
 	struct parking_lot *lot = self->lot;
 
-	ast_bridge_base_v_table.dissolving(&self->base);
-
 	/* Unlink the parking bridge from the parking lot that owns it */
 	lot->parking_bridge = NULL;
 	ao2_ref(lot, -1);
 
 	/* Disassociate the bridge from the parking lot as well. */
 	self->lot = NULL;
+
+	ast_bridge_base_v_table.dissolving(&self->base);
 }
 
 static void destroy_parked_user(void *obj)
@@ -115,10 +115,17 @@
 		return NULL;
 	}
 
+
 	if (use_random_space) {
 		preferred_space = ast_random() % (lot->cfg->parking_stop - lot->cfg->parking_start + 1);
 		preferred_space += lot->cfg->parking_start;
-	} else if ((parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"), "")))) {
+	} else {
+		ast_channel_lock(chan);
+		if ((parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"))) {
+			parkingexten = ast_strdupa(parkingexten);
+		}
+		ast_channel_unlock(chan);
+
 		if (!ast_strlen_zero(parkingexten)) {
 			if (sscanf(parkingexten, "%30d", &preferred_space) != 1 || preferred_space <= 0) {
 				ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n", parkingexten);
@@ -128,6 +135,7 @@
 		}
 	}
 
+
 	/* We need to keep the lot locked between parking_lot_get_space and actually placing it in the lot. Or until we decide not to. */
 	ao2_lock(lot);
 
@@ -180,21 +188,24 @@
 static int bridge_parking_push(struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
 {
 	struct parked_user *pu;
-
 	int randomize = 0;
 	int time_limit = -1;
 	int silence = 0;
+	const char *blind_transfer;
 	RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
 	RAII_VAR(char *, parker_uuid, NULL, ast_free);
-	const char *blind_transfer;
+
+	ast_bridge_base_v_table.push(&self->base, bridge_channel, swap);
 
 	/* Swaps for parking bridges should only occur as a result of local channel optimization */
 	if (swap) {
+		ao2_lock(swap);
 		pu = swap->bridge_pvt;
 		if (!pu) {
 			/* This should be impossible since the only way a channel can enter in the first place
 			 * is if it has a parked user associated with it */
 			publish_parked_call_failure(bridge_channel->chan);
+			ao2_unlock(swap);
 			return -1;
 		}
 
@@ -205,6 +216,8 @@
 
 		/* XXX Add a parked call swap message type to relay information about parked channel swaps */
 
+		ao2_unlock(swap);
+
 		return 0;
 	}
 
@@ -214,8 +227,13 @@
 	/* If the parker and the parkee are the same channel pointer, then the channel entered using
 	 * the park application. It's possible the the blindtransfer channel is still alive (particularly
 	 * when a multichannel bridge is parked), so try to get the real parker if possible. */
+	ast_channel_lock(bridge_channel->chan);
 	blind_transfer = S_OR(pbx_builtin_getvar_helper(bridge_channel->chan, "BLINDTRANSFER"),
 		ast_channel_name(bridge_channel->chan));
+	if (blind_transfer) {
+		blind_transfer = ast_strdupa(blind_transfer);
+	}
+	ast_channel_unlock(bridge_channel->chan);
 
 	if (parker == bridge_channel->chan) {
 		struct ast_channel *real_parker = ast_channel_get_by_name(blind_transfer);

Modified: team/jrose/bridge_projects/res/parking/parking_bridge_features.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_bridge_features.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_bridge_features.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_bridge_features.c Tue Apr 30 13:13:52 2013
@@ -166,10 +166,15 @@
 	strcpy(subscription_data->parkee_uuid, parkee_uuid);
 	strcpy(subscription_data->parker_uuid, parker_uuid);
 
-	if (!(parked_datastore->parked_subscription = stasis_subscribe(ast_parking_topic(), parker_update_cb, subscription_data)))
+	if (!(parked_datastore->parked_subscription = stasis_subscribe(ast_parking_topic(), parker_update_cb, subscription_data))) {
+		return -1;
+	}
 
 	datastore->data = parked_datastore;
+
+	ast_channel_lock(chan);
 	ast_channel_datastore_add(chan, datastore);
+	ast_channel_unlock(chan);
 
 	return 0;
 }
@@ -192,11 +197,6 @@
 	char *semi_pos;
 
 	/* Fill the variable with the extension and context we want to call */
-	/* BUGBUG if local channel optimization is using masquerades then this needs /n so the destination keeps its DTMF features.
-	 * Or use /n to keep the peer channel stable until after the atxfer completes and remove the /n from the channel.
-	 *
-	 * Local channel optimization currently is disabled because I don't set the chan->bridge pointers.
-	 */
 	snprintf(destination, sizeof(destination), "%s@%s", exten, context);
 
 	/* Now we request that chan_local prepare to call the destination */
@@ -214,8 +214,8 @@
 	ast_channel_unlock(parkee);
 	ast_channel_unlock(parker);
 
-	/* XXX This is a bit of a hack to make the subscription be on the ;2 local channel when doing a multiparty bridge park.
-	 *     It would be nice if we could clean this up later. */
+	/* BUGBUG This is a bit of a hack to make the subscription be on the ;2 local channel when doing
+	 *        a multiparty bridge park. Richard is working on something for us to clean this up. */
 	parkee_name = ast_strdupa(ast_channel_name(parkee));
 
 	semi_pos = strrchr(parkee_name, ';');
@@ -313,6 +313,7 @@
 static void park_bridge_channel(struct ast_bridge_channel *bridge_channel, const char *uuid_parkee, const char *uuid_parker, const char *app_data)
 {
 	RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_bridge *, original_bridge, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
 
 	if (strcmp(ast_channel_uniqueid(bridge_channel->chan), uuid_parkee)) {
@@ -324,17 +325,32 @@
 
 	if (!parker) {
 		ast_log(LOG_NOTICE, "Channel with uuid %s left before we could start parking the call. Parking canceled.\n", uuid_parker);
-		return;
-	}
-
-	if (!(parking_bridge = park_common_setup(bridge_channel->chan, parker, app_data))) {
 		publish_parked_call_failure(bridge_channel->chan);
 		return;
 	}
 
+	if (!(parking_bridge = park_common_setup(bridge_channel->chan, parker, app_data, NULL))) {
+		publish_parked_call_failure(bridge_channel->chan);
+		return;
+	}
+
 	pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", ast_channel_name(parker));
 
-	if (ast_bridge_move(parking_bridge, bridge_channel->bridge, bridge_channel->chan, NULL, 1)) {
+	/* bridge_channel must be locked so we can get a reference to the bridge it is currently on */
+	ao2_lock(bridge_channel);
+
+	original_bridge = bridge_channel->bridge;
+	if (!original_bridge) {
+		ao2_unlock(bridge_channel);
+		publish_parked_call_failure(bridge_channel->chan);
+		return;
+	}
+
+	ao2_ref(original_bridge, +1); /* Cleaned by RAII_VAR */
+
+	ao2_unlock(bridge_channel);
+
+	if (ast_bridge_move(parking_bridge, original_bridge, bridge_channel->chan, NULL, 1)) {
 		ast_log(LOG_ERROR, "Failed to move %s into the parking bridge.\n",
 			ast_channel_name(bridge_channel->chan));
 	}
@@ -342,7 +358,8 @@
 
 static int feature_park(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 {
-	return park_feature_helper(bridge, bridge_channel, NULL);
+	park_feature_helper(bridge, bridge_channel, NULL);
+	return 0;
 }
 
 static void parking_duration_cb_destroyer(void *hook_pvt)

Modified: team/jrose/bridge_projects/res/parking/parking_controller.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_controller.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_controller.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_controller.c Tue Apr 30 13:13:52 2013
@@ -91,10 +91,9 @@
 	int wrap;
 
 	if (lot->cfg->parkfindnext) {
-		/* Use next_space if the lot has already has next_space set; otherwise use lot start. */
+		/* Use next_space if the lot already has next_space set; otherwise use lot start. */
 		original_target = lot->next_space ? lot->next_space : lot->cfg->parking_start;
 	} else {
-		/* If not using find next mode, we just start at the start of the parking lot always. */
 		original_target = lot->cfg->parking_start;
 	}
 
@@ -108,7 +107,7 @@
 
 	i = ao2_iterator_init(lot->parked_users, 0);
 	while ((user = ao2_iterator_next(&i))) {
-		/* Only deal with wrap until we get to the target */
+		/* Increment the wrap on each pass until we find an empty space */
 		if (wrap == user->parking_space) {
 			wrap += 1;
 		}
@@ -125,7 +124,7 @@
 			break;
 		}
 
-		/* We found one already parked here. Bump the target by 1 and try again. */
+		/* We found one already parked here. */
 		current_target += 1;
 		ao2_ref(user, -1);
 	}
@@ -140,11 +139,6 @@
 	}
 
 	return -1;
-}
-
-static int retrieve_parked_user_first(void *obj, void *arg, int flags)
-{
-	return CMP_MATCH;
 }
 
 static int retrieve_parked_user_targeted(void *obj, void *arg, int flags)
@@ -163,7 +157,7 @@
 	RAII_VAR(struct parked_user *, user, NULL, ao2_cleanup);
 
 	if (target < 0) {
-		user = ao2_callback(lot->parked_users, 0, retrieve_parked_user_first, NULL);
+		user = ao2_callback(lot->parked_users, 0, NULL, NULL);
 	} else {
 		user = ao2_callback(lot->parked_users, 0, retrieve_parked_user_targeted, &target);
 	}
@@ -194,7 +188,10 @@
 {
 	/* Enabling features here should be additive to features that are already on the channel. */
 	struct ast_flags feature_flags = { 0 };
-	struct ast_flags *existing_features = ast_bridge_features_ds_get(chan);
+	struct ast_flags *existing_features;
+
+	ast_channel_lock(chan);
+	existing_features = ast_bridge_features_ds_get(chan);
 
 	if (existing_features) {
 		feature_flags = *existing_features;
@@ -214,11 +211,11 @@
 	}
 
 	if (lot->cfg->parkedcallrecording & recipient_mode) {
-		ast_set_flag(&feature_flags, AST_FEATURE_AUTOMON);
 		ast_set_flag(&feature_flags, AST_FEATURE_AUTOMIXMON);
 	}
 
 	ast_bridge_features_ds_set(chan, &feature_flags);
+	ast_channel_unlock(chan);
 
 	return;
 }
@@ -247,7 +244,13 @@
 {
 	struct ast_channel *chan = pu->chan;
 	char *peername;
-	const char *blindtransfer = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
+	const char *blindtransfer;
+
+	ast_channel_lock(chan);
+	if ((blindtransfer = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"))) {
+		blindtransfer = ast_strdupa(blindtransfer);
+	}
+	ast_channel_unlock(chan);
 
 	peername = blindtransfer ? ast_strdupa(blindtransfer) : ast_strdupa(pu->parker->name);
 
@@ -260,6 +263,7 @@
 	if (lot->cfg->comebacktoorigin) {
 		if (ast_exists_extension(chan, PARK_DIAL_CONTEXT, peername, 1, NULL)) {
 			ast_async_goto(chan, PARK_DIAL_CONTEXT, peername, 1);
+			return 0;
 		} else {
 			ast_log(LOG_ERROR, "Can not start %s at %s,%s,1 because extension does not exist. Terminating call.\n",
 				ast_channel_name(chan), PARK_DIAL_CONTEXT, peername);
@@ -286,8 +290,3 @@
 
 	return 0;
 }
-
-void reset_parked_time(struct parked_user *pu)
-{
-	pu->start = ast_tvnow();
-}

Modified: team/jrose/bridge_projects/res/parking/parking_manager.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_manager.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_manager.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_manager.c Tue Apr 30 13:13:52 2013
@@ -269,7 +269,6 @@
 static struct ast_str *manager_build_parked_call_string(const struct ast_parked_call_payload *payload)
 {
 	struct ast_str *out = ast_str_create(1024);
-	int res = 0;
 	RAII_VAR(struct ast_str *, parkee_string, NULL, ast_free);
 	RAII_VAR(struct ast_str *, parker_string, NULL, ast_free);
 	RAII_VAR(struct ast_str *, retriever_string, NULL, ast_free);
@@ -288,7 +287,7 @@
 		retriever_string = ast_manager_build_channel_state_string_suffix(payload->retriever, "Retriever");
 	}
 
-	res = ast_str_set(&out, 0,
+	ast_str_set(&out, 0,
 		"%s" /* parkee channel state */
 		"%s" /* parker channel state */
 		"%s" /* retriever channel state (when available) */
@@ -305,10 +304,6 @@
 		payload->timeout,
 		payload->duration);
 
-	if (!res) {
-		return NULL;
-	}
-
 	return out;
 }
 
@@ -330,8 +325,17 @@
 	while ((curuser = ao2_iterator_next(&iter_users))) {
 		RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
 		RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
+
 		payload = parked_call_payload_from_parked_user(curuser, PARKED_CALL);
+		if (!payload) {
+			return RESULT_FAILURE;
+		}
+
 		parked_call_string = manager_build_parked_call_string(payload);
+		if (!parked_call_string) {
+			return RESULT_FAILURE;
+		}
+
 		total++;
 
 		astman_append(s, "Event: ParkedCall\r\n"
@@ -382,8 +386,17 @@
 		while ((curuser = ao2_iterator_next(&iter_users))) {
 			RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
 			RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
+
 			payload = parked_call_payload_from_parked_user(curuser, PARKED_CALL);
+			if (!payload) {
+				return RESULT_FAILURE;
+			}
+
 			parked_call_string = manager_build_parked_call_string(payload);
+			if (!payload) {
+				return RESULT_FAILURE;
+			}
+
 			total++;
 
 			astman_append(s, "Event: ParkedCall\r\n"
@@ -541,6 +554,10 @@
 	}
 
 	parked_call_string = manager_build_parked_call_string(parked_call);
+	if (!parked_call_string) {
+		ast_log(LOG_ERROR, "Failed to issue an AMI event of '%s' in response to a stasis message.\n", event_type);
+		return;
+	}
 
 	manager_event(EVENT_FLAG_CALL, event_type,
 			"%s",

Modified: team/jrose/bridge_projects/res/parking/res_parking.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/res_parking.h?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/res/parking/res_parking.h (original)
+++ team/jrose/bridge_projects/res/parking/res_parking.h Tue Apr 30 13:13:52 2013
@@ -55,19 +55,6 @@
 	                                 *  valid transitions: PARKINGLOT_DISABLED */
 	PARKINGLOT_DISABLED,            /*! The parking lot is no longer linked to a parking lot in configuration. It can no longer be parked to.
 	                                 *  and it can not be parked to. Terminal Mode doest. */
-};
-
-struct parking_lot {
-	int next_space;                           /*!< When using parkfindnext, which space we should start searching from next time we park */
-	struct ast_bridge *parking_bridge;        /*!< Bridged where parked calls will rest until they are answered or otherwise leave */
-	struct ao2_container *parked_users;       /*!< List of parked users rigidly ordered by their parking space */
-	struct parking_lot_cfg *cfg;              /*!< Reference to configuration object for the parking lot */
-	enum parking_lot_modes mode;              /*!< Whether a parking lot is operational, being reconfigured, primed for deletion, or dynamically created. */
-	int disable_mark;                         /*!< On reload, disable this parking lot if it doesn't receive a new configuration. */
-
-	AST_DECLARE_STRING_FIELDS(
-		AST_STRING_FIELD(name);               /*!< Name of the parking lot object */
-	);
 };
 
 struct parking_lot_cfg {
@@ -96,6 +83,19 @@
 	);
 };
 
+struct parking_lot {
+	int next_space;                           /*!< When using parkfindnext, which space we should start searching from next time we park */
+	struct ast_bridge *parking_bridge;        /*!< Bridged where parked calls will rest until they are answered or otherwise leave */
+	struct ao2_container *parked_users;       /*!< List of parked users rigidly ordered by their parking space */
+	struct parking_lot_cfg *cfg;              /*!< Reference to configuration object for the parking lot */
+	enum parking_lot_modes mode;              /*!< Whether a parking lot is operational, being reconfigured, primed for deletion, or dynamically created. */
+	int disable_mark;                         /*!< On reload, disable this parking lot if it doesn't receive a new configuration. */
+
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(name);               /*!< Name of the parking lot object */
+	);
+};
+
 struct parked_user {
 	struct ast_channel *chan;                 /*!< Parked channel */
 	struct ast_channel_snapshot *parker;      /*!< Snapshot of the channel that parked the call at the time of parking */
@@ -234,6 +234,7 @@
  * \retval pointer to the parking lot container.
  */
 struct ao2_container *get_parking_lot_container(void);
+
 /*!
  * \since 12
  * \brief Find a parking lot based on its name
@@ -253,25 +254,12 @@
  *
  * \param chan The channel we want the parking lot name for
  *
- * \retval name of the parking lot if it is defined
- * \retval NULL if the parking lot is not defined.
+ * \retval name of the channel's assigned parking lot if it is defined by the channel in some way
+ * \retval name of the default parking lot if it is not
  *
  * \note Channel needs to be locked while the returned string is in use.
  */
 const char *find_channel_parking_lot_name(struct ast_channel *chan);
-
-/*!
- * \since 12
- * \brief Reset the start time of a parked user to now
- *
- * \param pu Parked user having the time reset
- *
- * \note This is useful for when you have things happening between the generation of a parked user
- *       and when they actually enter the parking bridge. If the start time isn't actually when the
- *       channel is placed into the parking bridge then there will likely be some discrepencies
- *       between real timeouts and expected timeouts when reporting for manager events.
- */
-void reset_parked_time(struct parked_user *pu);
 
 /*!
  * \since 12
@@ -330,13 +318,15 @@
  * \param parkee The channel being preparred for parking
  * \param parker The channel initiating the park; may be the parkee as well
  * \param app_data arguments supplied to the Park application. May be NULL.
+ * \param silence_announcements optional pointer to an integer where we want to store the silence option flag
  *
  * \retval reference to a parking bridge if successful
  * \retval NULL on failure
  *
  * \note ao2_cleanup this reference when you are done using it or you'll cause leaks.
  */
-struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_channel *parker, const char *app_data);
+struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_channel *parker,
+	const char *app_data, int *silence_announcements);
 
 struct park_common_datastore {
 	char *parker_uuid;     /*!< Unique ID of the channel parking the call. */

Modified: team/jrose/bridge_projects/res/res_parking.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/res_parking.c?view=diff&rev=386991&r1=386990&r2=386991
==============================================================================
--- team/jrose/bridge_projects/res/res_parking.c (original)
+++ team/jrose/bridge_projects/res/res_parking.c Tue Apr 30 13:13:52 2013
@@ -210,11 +210,6 @@
 	return cmp;
 }
 
-static int parking_lot_cmp_fn(void *obj, void *arg, const int flags)
-{
-	return CMP_MATCH;
-}
-
 /*! All parking lots that are currently alive in some fashion can be obtained from here */
 static struct ao2_container *parking_lot_container;
 
@@ -232,7 +227,7 @@
 
 struct parking_config {
 	struct parking_global_config *global;
-	struct ao2_container *parking_lot_list;
+	struct ao2_container *parking_lots;
 };
 
 static struct aco_type global_option = {
@@ -252,7 +247,7 @@
 	.category = "^(general)$",
 	.item_alloc = parking_lot_cfg_alloc,
 	.item_find = named_item_find,
-	.item_offset = offsetof(struct parking_config, parking_lot_list),
+	.item_offset = offsetof(struct parking_config, parking_lots),
 };
 
 struct aco_type *parking_lot_types[] = ACO_TYPES(&parking_lot_type);
@@ -275,15 +270,16 @@
 	const struct parking_lot_cfg *entry;
 	const char *key;
 
-	switch (flags & (OBJ_POINTER | OBJ_KEY)) {
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
 	case OBJ_KEY:
 		key = obj;
 		return ast_str_hash(key);
-	case OBJ_POINTER:
+	case OBJ_PARTIAL_KEY:
+		ast_assert(0);
+		return 0;
+	default:
 		entry = obj;
 		return ast_str_hash(entry->name);
-	default:
-		return 0;
 	}
 }
 
@@ -315,7 +311,7 @@
 static void parking_config_destructor(void *obj)
 {
 	struct parking_config *cfg = obj;
-	ao2_cleanup(cfg->parking_lot_list);
+	ao2_cleanup(cfg->parking_lots);
 	ao2_cleanup(cfg->global);
 }
 
@@ -334,7 +330,7 @@
 		return NULL;
 	}
 
-	if (!(cfg->parking_lot_list = ao2_container_alloc(37, parking_lot_cfg_hash_fn, parking_lot_cfg_cmp_fn))) {
+	if (!(cfg->parking_lots = ao2_container_alloc(37, parking_lot_cfg_hash_fn, parking_lot_cfg_cmp_fn))) {
 		return NULL;
 	}
 
@@ -350,7 +346,7 @@
 void parking_lot_remove_if_unused(struct parking_lot *lot)
 {
 
-	if (!(lot->mode == PARKINGLOT_DISABLED)) {
+	if (lot->mode != PARKINGLOT_DISABLED) {
 		return;
 	}
 
@@ -551,17 +547,26 @@
 
 	/* The channel variable overrides everything */
 	name = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
-	if (!name && !ast_strlen_zero(ast_channel_parkinglot(chan))) {
+	if (ast_strlen_zero(name) && !ast_strlen_zero(ast_channel_parkinglot(chan))) {
 		/* Use the channel's parking lot. */
 		name = ast_channel_parkinglot(chan);
 	}
+
+	/* If the name couldn't be pulled from that either, use the default parking lot name. */
+	if (ast_strlen_zero(name)) {
+		name = DEFAULT_PARKING_LOT;
+	}
+
 	return name;
 }
 
 static void parking_lot_destructor(void *obj)
 {
 	struct parking_lot *lot = obj;
-	ao2_cleanup(lot->parking_bridge);
+
+	if (lot->parking_bridge) {
+		ast_bridge_destroy(lot->parking_bridge);
+	}
 	ao2_cleanup(lot->parked_users);
 	ao2_cleanup(lot->cfg);
 	ast_string_field_free_memory(lot);
@@ -633,7 +638,7 @@
 	struct parking_lot_cfg *lot_cfg;
 	struct ao2_iterator iter;
 
-	for (iter = ao2_iterator_init(cfg->parking_lot_list, 0); (lot_cfg = ao2_iterator_next(&iter)); ao2_ref(lot_cfg, -1)) {
+	for (iter = ao2_iterator_init(cfg->parking_lots, 0); (lot_cfg = ao2_iterator_next(&iter)); ao2_ref(lot_cfg, -1)) {
 		RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
 		lot = parking_lot_build_or_update(lot_cfg);
 	}
@@ -690,7 +695,7 @@
 	parking_lot_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK,
 		AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT,
 		parking_lot_sort_fn,
-		parking_lot_cmp_fn);
+		NULL);
 
 	if (!parking_lot_container) {
 		goto error;




More information about the asterisk-commits mailing list