[asterisk-commits] jrose: branch jrose/bridge_projects r386625 - /team/jrose/bridge_projects/res...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Apr 26 15:12:59 CDT 2013


Author: jrose
Date: Fri Apr 26 15:12:55 2013
New Revision: 386625

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386625
Log:
Parking stuff as usual. Mostly improvements to parking multi-channel bridges.

Modified:
    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/res_parking.h

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=386625&r1=386624&r2=386625
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_applications.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_applications.c Fri Apr 26 15:12:55 2013
@@ -221,7 +221,84 @@
 	return 0;
 }
 
-struct ast_bridge *park_common_setup_blargfish(struct ast_channel *parkee, const char *parker_uuid, const char *app_data)
+static void park_common_datastore_destroy(void *data)
+{
+	struct park_common_datastore *datastore = data;
+	ast_free(datastore->parker_uuid);
+}
+
+static const struct ast_datastore_info park_common_info = {
+	.type = "park entry data",
+	.destroy = park_common_datastore_destroy,
+};
+
+static void wipe_park_common_datastore(struct ast_channel *chan)
+{
+	struct ast_datastore *datastore;
+
+	ast_channel_lock(chan);
+	datastore = ast_channel_datastore_find(chan, &park_common_info, NULL);
+	if (datastore) {
+		ast_channel_datastore_remove(chan, datastore);
+		ast_datastore_free(datastore);
+	}
+	ast_channel_unlock(chan);
+}
+
+static int setup_park_common_datastore(struct ast_channel *parkee, const char *parker_uuid, int randomize, int time_limit, int silence_announce)
+{
+	struct ast_datastore *datastore = NULL;
+	struct park_common_datastore *park_datastore;
+
+	wipe_park_common_datastore(parkee);
+
+	if (!(datastore = ast_datastore_alloc(&park_common_info, NULL))) {
+		return -1;
+	}
+
+	if (!(park_datastore = ast_calloc(1, sizeof(*park_datastore)))) {
+		ast_datastore_free(datastore);
+		return -1;
+	}
+
+	park_datastore->parker_uuid = ast_strdup(parker_uuid);
+	park_datastore->randomize = randomize;
+	park_datastore->time_limit = time_limit;
+	park_datastore->silence_announce = silence_announce;
+
+	datastore->data = park_datastore;
+	ast_channel_datastore_add(parkee, datastore);
+
+	return 0;
+}
+
+void get_park_common_datastore_data(struct ast_channel *parkee, char **parker_uuid, int *randomize, int *time_limit, int *silence_announce)
+{
+	struct ast_datastore *datastore;
+	struct park_common_datastore *data;
+
+	ast_channel_lock(parkee);
+	if (!(datastore = ast_channel_datastore_find(parkee, &park_common_info, NULL))) {
+		ast_channel_unlock(parkee);
+		return;
+	}
+
+	data = datastore->data;
+
+	if (!data) {
+		/* This data should always be populated if this datastore was appended to the channel */
+		ast_assert(0);
+	}
+
+	*parker_uuid = ast_strdup(data->parker_uuid);
+	*randomize = data->randomize;
+	*time_limit = data->time_limit;
+	*silence_announce = data->silence_announce;
+
+	ast_channel_unlock(parkee);
+}
+
+struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_channel *parker, const char *app_data)
 {
 	int use_ringing = 0;
 	int randomize = 0;
@@ -233,17 +310,7 @@
 	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 ast_channel *, parker, NULL, ao2_cleanup);
 	RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
-
-	/* Try to get the parker channel based on uuid. If that fails, we have a problem. */
-	parker = ast_channel_get_by_name(parker_uuid);
-
-	if (!parker) {
-		ast_log(LOG_NOTICE, "Could not find the alleged parker by uniqueid '%s' to park '%s'\n",
-			parker_uuid, ast_channel_name(parkee));
-		return NULL;
-	}
 
 	if (app_data) {
 		park_app_parse_data(app_data, &silence_announcements, &use_ringing, &randomize, &time_limit, &comeback_override, &lot_name_app_arg);
@@ -277,77 +344,12 @@
 	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);
 		return parking_bridge;
 	}
-
-	
 
 	/* Couldn't get the parking bridge. Epic failure. */
 	return NULL;
-}
-
-int park_common_setup(struct parking_lot **lot, struct ast_bridge **parking_bridge,
-		struct parked_user **pu, int *silence_announcements,
-		struct ast_channel *parker, struct ast_channel *parkee, const char *app_data)
-{
-	int use_ringing = 0;
-	int randomize = 0;
-	int time_limit = -1;
-	RAII_VAR(char *, comeback_override, NULL, ast_free);
-	RAII_VAR(char *, lot_name_app_arg, NULL, ast_free);
-	char *lot_name;
-
-	/* parse the app data if we have it */
-	if (app_data) {
-		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 (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);
-
-	if (!*lot) {
-		ast_log(LOG_ERROR, "Could not find parking lot: '%s'\n", lot_name);
-		return -1;
-	}
-
-	ao2_lock(*lot);
-	*parking_bridge = parking_lot_get_bridge(*lot);
-	ao2_unlock(*lot);
-
-	if (!*parking_bridge) {
-		ast_log(LOG_ERROR, "Could not acquire holding bridge to park into\n");
-		return -1;
-	}
-
-	*pu = generate_parked_user(*lot, parkee, parker, randomize, time_limit);
-
-	if (!*pu) {
-		return -1;
-	}
-
-	/* Apply relevant bridge roles and such to the parking channel */
-	parking_channel_set_roles(parkee, *lot, use_ringing);
-
-	/* If we need to go somewhere special after timeout, set special comeback arguments */
-	if (!ast_strlen_zero(comeback_override)) {
-		ast_copy_string((*pu)->comeback, comeback_override, sizeof((*pu)->comeback));
-	}
-
-	return 0;
 }
 
 /* XXX BUGBUG - determining the parker when transferred to deep park priority
@@ -366,15 +368,12 @@
  *     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 BLINDTRASFER variable could just be used as data for
+ *     the park at this point) and the BLINDTRANSFER variable could just be used as data for
  *     generating the comebacktoorigin location and extensions.
  */
 int park_app_exec(struct ast_channel *chan, const char *data)
 {
-	RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
-	RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
-	int silence_announcements = 0;
 
 	struct ast_bridge_features chan_features;
 	int res;
@@ -384,16 +383,11 @@
 		ast_answer(chan);
 	}
 
-	/* Handle all the common aprking setup stuff */
-	if (park_common_setup(&lot, &parking_bridge, &pu, &silence_announcements, chan, chan, data)) {
+	/* 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", "");
-		return -1;
-	}
-
-	/* Announce parking space to the parking channel */
-	/* Need to make this conditional */
-	if (!silence_announcements) {
-		ast_say_digits(chan, pu->parking_space, "", ast_channel_language(chan));
+		return 0;
 	}
 
 	/* Initialize bridge features for the channel. */
@@ -404,7 +398,10 @@
 	}
 
 	/* Now for the fun part... park it! */
-	ast_bridge_join(parking_bridge, chan, NULL, &chan_features, NULL, 0);
+	if (ast_bridge_join(parking_bridge, chan, NULL, &chan_features, NULL, 0)) {
+		/* XXX Need to add reactions based on the return value. */
+		//ast_stream_and_wait(chan, "pbx-parkingfailed", "");
+	}
 
 	/*
 	 * If the bridge was broken for a hangup that isn't real, then

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=386625&r1=386624&r2=386625
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_bridge.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_bridge.c Fri Apr 26 15:12:55 2013
@@ -28,6 +28,7 @@
 #include "res_parking.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/features.h"
+#include "asterisk/say.h"
 
 struct ast_bridge_parking
 {
@@ -67,6 +68,101 @@
 	self->lot = NULL;
 }
 
+static void destroy_parked_user(void *obj)
+{
+	struct parked_user *pu = obj;
+
+	ao2_cleanup(pu->lot);
+	pu->lot = NULL;
+
+	ao2_cleanup(pu->parker);
+	pu->parker = NULL;
+}
+
+/*!
+ * \internal
+ * \since 12
+ * \brief Construct a parked_user struct assigned to the specified parking lot
+ *
+ * \param lot The parking lot we are assigning the user to
+ * \param parkee The channel being parked
+ * \param parker The channel performing the park operation (may be the same channel)
+ * \param use_random_space if true, prioritize using a random parking space instead
+ *        of ${PARKINGEXTEN} and/or automatic assignment from the parking lot
+ * \param time_limit If using a custom timeout, this should be supplied so that the
+ *        parked_user struct can provide this information for manager events. If <0,
+ *        use the parking lot limit instead.
+ *
+ * \retval NULL on failure
+ * \retval reference to the parked user
+ *
+ * \note ao2_cleanup this reference when you are done using it or you'll cause leaks.
+ */
+static struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *chan, struct ast_channel *parker, int use_random_space, int time_limit)
+{
+	struct parked_user *new_parked_user;
+	int preferred_space = -1; /* Initialize to use parking lot defaults */
+	int parking_space;
+	const char *parkingexten;
+
+	if (lot->mode == PARKINGLOT_DISABLED) {
+		ast_log(LOG_NOTICE, "Tried to park in a parking lot that is no longer able to be parked to.\n");
+		return NULL;
+	}
+
+	new_parked_user = ao2_alloc(sizeof(*new_parked_user), destroy_parked_user);
+	if (!new_parked_user) {
+		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"), "")))) {
+		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);
+				ao2_ref(new_parked_user, -1);
+				return NULL;
+			}
+		}
+	}
+
+	/* 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);
+
+	parking_space = parking_lot_get_space(lot, preferred_space);
+	if (parking_space == -1) {
+		ast_log(LOG_NOTICE, "Failed to get parking space in lot '%s'. All full.\n", lot->name);
+		ao2_ref(new_parked_user, -1);
+		ao2_unlock(lot);
+		return NULL;
+	}
+
+	lot->next_space = ((parking_space + 1) - lot->cfg->parking_start) % (lot->cfg->parking_stop - lot->cfg->parking_start + 1) + lot->cfg->parking_start;
+	new_parked_user->chan = chan;
+	new_parked_user->parking_space = parking_space;
+
+	/* Have the parked user take a reference to the parking lot. This reference should be immutable and released at destruction */
+	new_parked_user->lot = lot;
+	ao2_ref(lot, +1);
+
+	new_parked_user->start = ast_tvnow();
+	new_parked_user->time_limit = (time_limit >= 0) ? time_limit : lot->cfg->parkingtime;
+	new_parked_user->parker = ast_channel_snapshot_create(parker);
+	if (!new_parked_user->parker) {
+		ao2_ref(new_parked_user, -1);
+		ao2_unlock(lot);
+		return NULL;
+	}
+
+	/* Insert into the parking lot's parked user list. We can unlock the lot now. */
+	ao2_link(lot->parked_users, new_parked_user);
+	ao2_unlock(lot);
+
+	return new_parked_user;
+}
+
 /*!
  * \internal
  * \brief ast_bridge parking push method.
@@ -84,7 +180,13 @@
 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;
-	struct ao2_iterator iter;
+
+	int randomize = 0;
+	int time_limit = -1;
+	int silence = 0;
+	RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
+	RAII_VAR(char *, parker_uuid, NULL, ast_free);
+	const char *blind_transfer;
 
 	/* Swaps for parking bridges should only occur as a result of local channel optimization */
 	if (swap) {
@@ -105,29 +207,36 @@
 		return 0;
 	}
 
-	/* We should already have a parked user set for the channel when we push. Take a reference to it. We'll keep this. */
-	for (iter = ao2_iterator_init(self->lot->parked_users, 0); (pu = ao2_iterator_next(&iter)); ao2_ref(pu, -1)) {
-		if (bridge_channel->chan != pu->chan) {
-			continue;
-		}
-		break;
-	}
-	ao2_iterator_destroy(&iter);
-
+	get_park_common_datastore_data(bridge_channel->chan, &parker_uuid, &randomize, &time_limit, &silence);
+	parker = ast_channel_get_by_name(parker_uuid);
+
+	if (!parker) {
+		return -1;
+	}
+
+	pu = generate_parked_user(self->lot, bridge_channel->chan, parker, randomize, time_limit);
 	if (!pu) {
-		ast_assert(0);
+		publish_parked_call_failure(bridge_channel->chan);
+		return -1;
 	}
 
 	/* Apply parking duration limits */
-	reset_parked_time(pu);
 	parking_set_duration(bridge_channel->features, pu);
 
 	/* Set this to the bridge pvt so that we don't have to refind the parked user associated with this bridge channel again. */
 	bridge_channel->bridge_pvt = pu;
 
-	/* Raise bridged flag so that the call can actually be retrieved */
+	/* Raise bridged flag so that the call can actually be retrieved. XXX this whole concept probably isn't necessary any more. */
 	pu->bridged = 1;
 
+	blind_transfer = S_OR(pbx_builtin_getvar_helper(bridge_channel->chan, "BLINDTRANSFER"), ast_channel_name(bridge_channel->chan));
+
+	/* If the parkee and the parker are the same and silence_announce isn't set, play the announcement to the parkee */
+	if (!strcmp(blind_transfer, ast_channel_name(bridge_channel->chan)) && !silence) {
+		ast_say_digits(bridge_channel->chan, pu->parking_space, "", ast_channel_language(bridge_channel->chan));
+	}
+
+	reset_parked_time(pu);
 	/* Generate ParkedCall Stasis Message */
 	publish_parked_call(pu, PARKED_CALL);
 

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=386625&r1=386624&r2=386625
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_bridge_features.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_bridge_features.c Fri Apr 26 15:12:55 2013
@@ -171,13 +171,14 @@
 		return -1;
 	}
 
-	if (!(subscription_data = ast_calloc(1, sizeof(*subscription_data) + parker_uuid_size + strlen(parkee_uuid) + 1))) {
+	if (!(subscription_data = ast_calloc(1, sizeof(*subscription_data) + parker_uuid_size +
+			strlen(parkee_uuid) + 1))) {
 		ast_datastore_free(datastore);
 		ast_free(parked_datastore);
+		return -1;
 	}
 
 	subscription_data->parkee_uuid = subscription_data->parker_uuid + parker_uuid_size;
-
 	strcpy(subscription_data->parkee_uuid, parkee_uuid);
 	strcpy(subscription_data->parker_uuid, parker_uuid);
 
@@ -187,6 +188,74 @@
 	ast_channel_datastore_add(chan, datastore);
 
 	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Helper function that creates an outgoing channel and returns it immediately. This function is nearly
+ *        identical to the dial_transfer function in bridge_builtin_features.c, however it doesn't swap the
+ *        local channel and the channel that instigated the park.
+ */
+static struct ast_channel *park_local_transfer(struct ast_channel *parker, const char *exten, const char *context)
+{
+	RAII_VAR(struct ast_channel *, parkee_side_2, NULL, ao2_cleanup);
+	char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
+	struct ast_channel *parkee;
+	int cause;
+
+	/* Used for side_2 hack */
+	char *parkee_name;
+	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 */
+	parkee = ast_request("Local", ast_channel_nativeformats(parker), parker, destination,
+		&cause);
+	if (!parkee) {
+		return NULL;
+	}
+
+	/* Before we actually dial out let's inherit appropriate information. */
+	ast_channel_lock_both(parker, parkee);
+	ast_connected_line_copy_from_caller(ast_channel_connected(parkee), ast_channel_caller(parker));
+	ast_channel_inherit_variables(parker, parkee);
+	ast_channel_datastore_inherit(parker, parkee);
+	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. */
+	parkee_name = ast_strdupa(ast_channel_name(parkee));
+
+	semi_pos = strrchr(parkee_name, ';');
+	if (!semi_pos) {
+		/* There should always be a semicolon present in the string if is used since it's a local channel. */
+		ast_assert(0);
+		return NULL;
+	}
+
+	parkee_name[(semi_pos - parkee_name) + 1] = '2';
+	parkee_side_2 = ast_channel_get_by_name(parkee_name);
+
+	/* We need to have the parker subscribe to the new local channel before hand. */
+	create_parked_subscription(parker, ast_channel_uniqueid(parkee_side_2));
+
+	pbx_builtin_setvar_helper(parkee_side_2, "BLINDTRANSFER", ast_channel_name(parker));
+
+	/* Since the above worked fine now we actually call it and return the channel */
+	if (ast_call(parkee, destination, 0)) {
+		ast_hangup(parkee);
+		return NULL;
+	}
+
+	return parkee;
 }
 
 static int park_feature_helper(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_exten *park_exten)
@@ -201,14 +270,38 @@
 	bridge_peers = ast_bridge_peers(bridge);
 
 	if (ao2_container_count(bridge_peers) < 2) {
-		/* Can't do anything with that. */
+		/* There is nothing to do if there is no one to park. */
 		return 0;
 	}
 
 	if (ao2_container_count(bridge_peers) > 2) {
-		/* XXX Need to do the multiparty bridge park... which is a local channel to the parking lot */
+		/* With a multiparty bridge, we need to do a regular blind transfer. We link the existing bridge to the parking lot with a
+		 * local channel rather than transferring others. */
+		struct ast_channel *transfer_chan = NULL;
+
+		if (!park_exten) {
+			/* This simply doesn't work. The user attempted to one-touch park the parking lot and we can't originate a local channel
+			 * without knowing an extension to transfer it to.
+			 * XXX However, when parking lots are changed to be able to register extensions then this will be doable. */
+			ast_log(LOG_ERROR, "Can not one-touch park a multiparty bridge.\n");
+			return 0;
+		}
+
+		transfer_chan = park_local_transfer(bridge_channel->chan,
+			ast_get_extension_name(park_exten), ast_get_context_name(ast_get_extension_context(park_exten)));
+
+		if (!transfer_chan) {
+			return 0;
+		}
+
+		if (ast_bridge_impart(bridge_channel->bridge, transfer_chan, NULL, NULL, 1)) {
+			ast_hangup(transfer_chan);
+		}
+
 		return 0;
 	}
+
+	/* Since neither of the above cases were used, we are doing a simple park with a two party bridge. */
 
 	for (iter = ao2_iterator_init(bridge_peers, 0); (other = ao2_iterator_next(&iter)); ao2_ref(other, -1)) {
 		/* We need the channel that isn't the bridge_channel's channel. */
@@ -235,8 +328,6 @@
 
 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 parking_lot *, lot, NULL, ao2_cleanup);
-	RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
 
@@ -249,18 +340,19 @@
 
 	if (!parker) {
 		ast_log(LOG_NOTICE, "Channel with uuid %s left before we could start parking the call. Parking canceled.\n", uuid_parker);
+		return;
 	}
 
 	/* XXX Most of this can be moved into the push. Doing so will keep all of the publishing of parking events in
 	 * the bridge join/pull functions. Also, silence option is not respected here in park_common_setup */
-	if (park_common_setup(&lot, &parking_bridge, &pu, NULL, parker, bridge_channel->chan, app_data)) {
+	if (!(parking_bridge = park_common_setup(bridge_channel->chan, parker, app_data))) {
 		publish_parked_call_failure(bridge_channel->chan);
 		return;
 	}
 
 	if (ast_bridge_move(bridge_channel->bridge, parking_bridge, bridge_channel->chan)) {
-		ast_log(LOG_ERROR, "Failed to move %s into the parking bridge for %s\n",
-			ast_channel_name(bridge_channel->chan), lot->name);
+		ast_log(LOG_ERROR, "Failed to move %s into the parking bridge.\n",
+			ast_channel_name(bridge_channel->chan));
 	}
 }
 

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=386625&r1=386624&r2=386625
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_controller.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_controller.c Fri Apr 26 15:12:55 2013
@@ -229,17 +229,6 @@
 	return;
 }
 
-static void destroy_parked_user(void *obj)
-{
-	struct parked_user *pu = obj;
-
-	ao2_cleanup(pu->lot);
-	pu->lot = NULL;
-
-	ao2_cleanup(pu->parker);
-	pu->parker = NULL;
-}
-
 void flatten_peername(char *peername)
 {
 	int i;
@@ -302,119 +291,3 @@
 {
 	pu->start = ast_tvnow();
 }
-
-static void park_common_datastore_destroy(void *data)
-{
-	struct park_common_datastore *datastore = data;
-	ast_free(datastore->parker_uuid);
-}
-
-static const struct ast_datastore_info park_common_info = {
-	.type = "park entry data",
-	.destroy = park_common_datastore_destroy,
-};
-
-static void wipe_park_common_datastore(struct ast_channel *chan)
-{
-	struct ast_datastore *datastore;
-
-	ast_channel_lock(chan);
-	datastore = ast_channel_datastore_find(chan, &park_common_info, NULL);
-	if (datastore) {
-		ast_channel_datastore_remove(chan, datastore);
-		ast_datastore_free(datastore);
-	}
-	ast_channel_unlock(chan);
-}
-
-int setup_park_common_datastore(struct ast_channel *parkee, const char *parker_uuid, int randomize, int time_limit)
-{
-	struct ast_datastore *datastore = NULL;
-	struct park_common_datastore *park_datastore;
-
-	wipe_park_common_datastore(parkee);
-
-	if (!(datastore = ast_datastore_alloc(&park_common_info, NULL))) {
-		return -1;
-	}
-
-	if (!(park_datastore = ast_calloc(1, sizeof(*park_datastore)))) {
-		ast_datastore_free(datastore);
-		return -1;
-	}
-
-	park_datastore->parker_uuid = ast_strdup(parker_uuid);
-	park_datastore->randomize = randomize;
-	park_datastore->time_limit = time_limit;
-
-	datastore->data = park_datastore;
-	ast_channel_datastore_add(parkee, datastore);
-
-	return 0;
-}
-
-struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *chan, struct ast_channel *parker, int use_random_space, int time_limit)
-{
-	struct parked_user *new_parked_user;
-	int preferred_space = -1; /* Initialize to use parking lot defaults */
-	int parking_space;
-	const char *parkingexten;
-
-	if (lot->mode == PARKINGLOT_DISABLED) {
-		ast_log(LOG_NOTICE, "Tried to park in a parking lot that is no longer able to be parked to.\n");
-		return NULL;
-	}
-
-	new_parked_user = ao2_alloc(sizeof(*new_parked_user), destroy_parked_user);
-	if (!new_parked_user) {
-		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"), "")))) {
-		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);
-				ao2_ref(new_parked_user, -1);
-				return NULL;
-			}
-		}
-	}
-
-	/* 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);
-
-	parking_space = parking_lot_get_space(lot, preferred_space);
-	if (parking_space == -1) {
-		ast_log(LOG_NOTICE, "Failed to get parking space in lot '%s'. All full.\n", lot->name);
-		ao2_ref(new_parked_user, -1);
-		ao2_unlock(lot);
-		return NULL;
-	}
-
-	lot->next_space = ((parking_space + 1) - lot->cfg->parking_start) % (lot->cfg->parking_stop - lot->cfg->parking_start + 1) + lot->cfg->parking_start;
-	new_parked_user->chan = chan;
-	new_parked_user->parking_space = parking_space;
-
-	/* Have the parked user take a reference to the parking lot. This reference should be immutable and released at destruction */
-	new_parked_user->lot = lot;
-	ao2_ref(lot, +1);
-
-	new_parked_user->start = ast_tvnow();
-	new_parked_user->time_limit = (time_limit >= 0) ? time_limit : lot->cfg->parkingtime;
-	new_parked_user->parker = ast_channel_snapshot_create(parker);
-	if (!new_parked_user->parker) {
-		ao2_ref(new_parked_user, -1);
-		ao2_unlock(lot);
-		return NULL;
-	}
-
-	/* Insert into the parking lot's parked user list. We can unlock the lot now. */
-	ao2_link(lot->parked_users, new_parked_user);
-	ao2_unlock(lot);
-
-	return new_parked_user;
-}
-

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=386625&r1=386624&r2=386625
==============================================================================
--- team/jrose/bridge_projects/res/parking/res_parking.h (original)
+++ team/jrose/bridge_projects/res/parking/res_parking.h Fri Apr 26 15:12:55 2013
@@ -256,26 +256,6 @@
 
 /*!
  * \since 12
- * \brief Create a parked user within the specified parking lot and get a reference to it.
- *
- * \param lot The parking lot we are assigning the user to
- * \param parkee The channel being parked
- * \param parker The channel performing the park operation (may be the same channel)
- * \param use_random_space if true, prioritize using a random parking space instead
- *        of ${PARKINGEXTEN} and/or automatic assignment from the parking lot
- * \param time_limit If using a custom timeout, this should be supplied so that the
- *        parked_user struct can provide this information for manager events. If <0,
- *        use the parking lot limit instead.
- *
- * \retval NULL on failure
- * \retval reference to the parked user
- *
- * \note ao2_cleanup this reference when you are done using it or you'll cause leaks.
- */
-struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *parkee, struct ast_channel *parker, int use_random_space, int time_limit);
-
-/*!
- * \since 12
  * \brief Reset the start time of a parked user to now
  *
  * \param pu Parked user having the time reset
@@ -336,38 +316,30 @@
 
 /*!
  * \since 12
- * \brief This sets up a parked user for the channel being parked as well as prepares the parking bridge if necessary.
- *        it also handles the setup of all parking options available to the parking application.
- *
- * \param lot pointer to a parking lot struct pointer. This will be set to the necessary parking lot
- *            based on either app_data or channel variables.
- * \param parking_bridge pointer to an ast_bridge struct pointer. Set to the parking lot's parking bridge.
- * \param pu pointer to a parked user struct pointer. Set to the newly generated parked user.
- * \param silence_announcements pointer to an integer which holds whether announcements should be made or not.
- *
- * \param parker ast_channel struct pointer, the channel that is initiating the parking
- * \param parkee ast_channel struct pointer, the channel that is being parked
- * \param app_data string of application arguments, may be NULL.
- *
- * \retval 0 if successful
- * \retval -1 on failure
- *
- * \note lot, parking_bridge, and pu should be passed by address and will be initialized by this function.
- *       All three of them will need to be ao2_cleanup'd once they fall out of scope. See park_app_exec for
- *       a specific usage example.
- */
-int park_common_setup(struct parking_lot **lot, struct ast_bridge **parking_bridge, struct parked_user **pu,
-		int *silence_announcements, struct ast_channel *parker, struct ast_channel *parkee, const char *app_data);
-
-struct ast_bridge *park_common_setup_blargfish(struct ast_channel *parkee, const char *parker_uuid, const char *app_data);
+ * \brief Function to prepare a channel for parking by determining which parking bridge should
+ *        be used, setting up a park common datastore so that the parking bridge will have access
+ *        to necessary parking information when joining, and applying various bridge roles to the
+ *        channel.
+ *
+ * \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.
+ *
+ * \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 park_common_datastore {
 	char *parker_uuid;     /*!< Unique ID of the channel parking the call. */
 	int randomize;               /*!< Pick a parking space to enter on at random */
 	int time_limit;              /*!< time limit override. -1 values don't override, 0 for unlimited time, >0 for custom time limit in seconds */
-};
-
-int setup_park_common_datastore(struct ast_channel *parkee, const char *parker_uuid, int randomize, int time_limit);
+	int silence_announce;        /*!< Used when a call parks itself to keep it from hearing the parked call announcement */
+};
+
+void get_park_common_datastore_data(struct ast_channel *parkee, char **parker_uuid, int *randomize, int *time_limit, int *silence_announce);
 
 /*!
  * \since 12




More information about the asterisk-commits mailing list