[svn-commits] jrose: branch jrose/bridge_projects r386625 - /team/jrose/bridge_projects/res...
SVN commits to the Digium repositories
svn-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 svn-commits
mailing list