[asterisk-commits] jrose: branch jrose/bridge_projects r386442 - in /team/jrose/bridge_projects:...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Apr 24 14:39:43 CDT 2013
Author: jrose
Date: Wed Apr 24 14:39:39 2013
New Revision: 386442
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386442
Log:
asynchronous parking for bridge feature park
Modified:
team/jrose/bridge_projects/include/asterisk/bridging.h
team/jrose/bridge_projects/include/asterisk/parking.h
team/jrose/bridge_projects/main/bridging.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_manager.c
team/jrose/bridge_projects/res/parking/res_parking.h
Modified: team/jrose/bridge_projects/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/bridging.h?view=diff&rev=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/bridging.h (original)
+++ team/jrose/bridge_projects/include/asterisk/bridging.h Wed Apr 24 14:39:39 2013
@@ -219,6 +219,8 @@
AST_BRIDGE_ACTION_TALKING_STOP,
/*! Bridge channel is to play the indicated sound file. */
AST_BRIDGE_ACTION_PLAY_FILE,
+ /*! Bridge channel is to get parked. */
+ AST_BRIDGE_ACTION_PARK,
/*! Bridge channel is to run the indicated application. */
AST_BRIDGE_ACTION_RUN_APP,
@@ -1139,6 +1141,22 @@
void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
/*!
+ * \brief Have a bridge channel park a channel in the bridge
+ * \since 12.0.0
+ *
+ * \param bridge_channel Bridge channel performing the parking
+ * \param parkee_uuid Unique id of the channel we want to park
+ * \param parker_uuid Unique id of the channel parking the call
+ * \param app_data string indicating data used for park application (NULL allowed)
+ *
+ * \note This is intended to be called by bridge hooks.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid,
+ const char *parker_uuid, const char *app_data);
+
+/*!
* \brief Write a bridge action play file frame into the bridge.
* \since 12.0.0
*
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=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/parking.h (original)
+++ team/jrose/bridge_projects/include/asterisk/parking.h Wed Apr 24 14:39:39 2013
@@ -36,6 +36,7 @@
PARKED_CALL_TIMEOUT,
PARKED_CALL_GIVEUP,
PARKED_CALL_UNPARKED,
+ PARKED_CALL_FAILED,
};
/*!
@@ -107,6 +108,20 @@
struct stasis_message_type *ast_parked_call_type(void);
/*!
+ * \brief invoke an installable park callback to asynchronously park a bridge_channel in a bridge
+ * \since 12
+ *
+ * \param bridge_channel the bridge channel that initiated parking
+ * \parkee_uuid channel id of the channel being parked
+ * \parker_uuid channel id of the channel that initiated parking
+ * \param app_data string of application data that might be applied to parking
+ */
+void ast_bridge_channel_park(struct ast_bridge_channel *bridge_channel,
+ const char *parkee_uuid,
+ const char *parker_uuid,
+ const char *app_data);
+
+/*!
* \brief install a callback for handling blind transfers to a parking extension
* \since 12
*
@@ -136,6 +151,22 @@
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));
+
+/*!
+ * \brief Uninstall the ast_bridge_channel_park function callback
+ * \since 12
+ */
+void ast_uninstall_bridge_channel_park_func(void);
+
+
+/*!
* \brief Determines whether a certain extension is a park application extension or not.
* \since 12
*
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=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/main/bridging.c (original)
+++ team/jrose/bridge_projects/main/bridging.c Wed Apr 24 14:39:39 2013
@@ -58,6 +58,7 @@
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/cli.h"
+#include "asterisk/parking.h"
/*! All bridges container. */
static struct ao2_container *bridges;
@@ -919,6 +920,48 @@
{
payload_helper_playfile(ast_bridge_channel_queue_action_data,
bridge_channel, custom_play, playfile, moh_class);
+}
+
+struct bridge_park {
+ int parker_uuid_offset;
+ int app_data_offset;
+ /* buffer used for holding those strings */
+ char parkee_uuid[0];
+};
+
+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);
+}
+
+static void payload_helper_park(ast_bridge_channel_post_action_data post_it,
+ struct ast_bridge_channel *bridge_channel,
+ const char *parkee_uuid,
+ const char *parker_uuid,
+ const char *app_data)
+{
+ struct bridge_park *payload;
+ size_t len_parkee_uuid = strlen(parkee_uuid) + 1;
+ size_t len_parker_uuid = strlen(parker_uuid) + 1;
+ size_t len_app_data = !app_data ? 0 : strlen(app_data) + 1;
+ size_t len_payload = sizeof(*payload) + len_parker_uuid + len_parkee_uuid + len_app_data;
+
+ payload = alloca(len_payload);
+ payload->app_data_offset = len_app_data ? len_parkee_uuid + len_parker_uuid : 0;
+ payload->parker_uuid_offset = len_parkee_uuid;
+ strcpy(payload->parkee_uuid, parkee_uuid);
+ strcpy(&payload->parkee_uuid[payload->parker_uuid_offset], parker_uuid);
+ if (app_data) {
+ strcpy(&payload->parkee_uuid[payload->app_data_offset], app_data);
+ }
+
+ post_it(bridge_channel, AST_BRIDGE_ACTION_PARK, payload, len_payload);
+}
+
+void ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
+{
+ payload_helper_park(ast_bridge_channel_write_action_data,
+ bridge_channel, parkee_uuid, parker_uuid, app_data);
}
/*!
@@ -2026,6 +2069,13 @@
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
bridge_channel_unsuspend(bridge_channel);
break;
+ case AST_BRIDGE_ACTION_PARK:
+ bridge_channel_suspend(bridge_channel);
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+ bridge_channel_park(bridge_channel, action->data.ptr);
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+ bridge_channel_unsuspend(bridge_channel);
+ break;
case AST_BRIDGE_ACTION_RUN_APP:
bridge_channel_suspend(bridge_channel);
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
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=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/main/parking.c (original)
+++ team/jrose/bridge_projects/main/parking.c Wed Apr 24 14:39:39 2013
@@ -40,9 +40,13 @@
/*! \brief Topic for parking lots */
static struct stasis_topic *parking_topic;
-/*! \brief Funcion Callback for handling blind transfers to park applications */
+/*! \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,
const char *app_data) = 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;
void ast_parking_stasis_init(void)
{
@@ -100,15 +104,20 @@
ao2_ref(parkee_snapshot, +1);
payload->parkee = parkee_snapshot;
- ao2_ref(parker_snapshot, +1);
- payload->parker = parker_snapshot;
+ if (parker_snapshot) {
+ ao2_ref(parker_snapshot, +1);
+ payload->parker = parker_snapshot;
+ }
if (retriever_snapshot) {
ao2_ref(retriever_snapshot, +1);
payload->retriever = retriever_snapshot;
}
- ast_string_field_set(payload, parkinglot, parkinglot);
+ if (parkinglot) {
+ ast_string_field_set(payload, parkinglot, parkinglot);
+ }
+
payload->parkingspace = parkingspace;
payload->timeout = timeout;
payload->duration = duration;
@@ -124,9 +133,20 @@
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))
+{
+ ast_bridge_channel_park_func = bridge_channel_park_func;
+}
+
void ast_uninstall_park_blind_xfer_func(void)
{
ast_park_blind_xfer_func = NULL;
+}
+
+void ast_uninstall_bridge_channel_park_func(void)
+{
+ ast_bridge_channel_park_func = NULL;
}
int ast_park_blind_xfer(struct ast_bridge *bridge, struct ast_bridge_channel *parker,
@@ -165,3 +185,11 @@
return exten;
}
+
+void ast_bridge_channel_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
+{
+ /* Run installable function */
+ if (ast_bridge_channel_park_func) {
+ return ast_bridge_channel_park_func(bridge_channel, parkee_uuid, parker_uuid, app_data);
+ }
+}
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=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_applications.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_applications.c Wed Apr 24 14:39:39 2013
@@ -200,7 +200,9 @@
}
if (ast_test_flag(&flags, MUXFLAG_NOANNOUNCE)) {
- *disable_announce = 1;
+ if (disable_announce) {
+ *disable_announce = 1;
+ }
}
if (ast_test_flag(&flags, MUXFLAG_RINGING)) {
@@ -219,10 +221,10 @@
return 0;
}
-int park_common_setup(struct parking_lot **lot, struct ast_bridge **parking_bridge, struct parked_user **pu,
+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 silence_announcements = 0;
int use_ringing = 0;
int randomize = 0;
int time_limit = -1;
@@ -232,7 +234,7 @@
/* 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);
+ 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;
@@ -253,7 +255,6 @@
if (!*lot) {
ast_log(LOG_ERROR, "Could not find parking lot: '%s'\n", lot_name);
- ast_stream_and_wait(parker, "pbx-parkingfailed", "");
return -1;
}
@@ -263,21 +264,13 @@
if (!*parking_bridge) {
ast_log(LOG_ERROR, "Could not acquire holding bridge to park into\n");
- ast_stream_and_wait(parker, "pbx-parkingfailed", "");
return -1;
}
*pu = generate_parked_user(*lot, parkee, parker, randomize, time_limit);
if (!*pu) {
- ast_log(LOG_ERROR, "Failed to create parked user for channel %s, can not park.\n", ast_channel_name(parkee));
- ast_stream_and_wait(parker, "pbx-parkingfailed", "");
- return -1;
- }
-
- /* Announce parking space to the parking channel */
- if (!silence_announcements) {
- ast_say_digits(parker, (*pu)->parking_space, "", ast_channel_language(parker));
+ return -1;
}
/* Apply relevant bridge roles and such to the parking channel */
@@ -315,6 +308,7 @@
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;
@@ -325,8 +319,15 @@
}
/* Handle all the common aprking setup stuff */
- if (park_common_setup(&lot, &parking_bridge, &pu, chan, chan, data)) {
- return -1;
+ if (park_common_setup(&lot, &parking_bridge, &pu, &silence_announcements, chan, chan, data)) {
+ 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));
}
/* Initialize bridge features for the channel. */
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=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_bridge.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_bridge.c Wed Apr 24 14:39:39 2013
@@ -110,6 +110,7 @@
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);
return -1;
}
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=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_bridge_features.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_bridge_features.c Wed Apr 24 14:39:39 2013
@@ -35,47 +35,236 @@
#include "asterisk/bridging_features.h"
#include "asterisk/features.h"
#include "asterisk/say.h"
+#include "asterisk/datastore.h"
+#include "asterisk/stasis.h"
+
+struct parked_subscription_datastore {
+ struct stasis_subscription *parked_subscription;
+};
+
+struct parked_subscription_data {
+ const char *parker_uuid;
+ const char *parkee_uuid;
+};
+
+static void parked_subscription_datastore_destroy(void *data)
+{
+ struct parked_subscription_datastore *subscription_data = data;
+
+ stasis_unsubscribe(subscription_data->parked_subscription);
+ subscription_data->parked_subscription = NULL;
+}
+
+static const struct ast_datastore_info parked_subscription_info = {
+ .type = "park subscription",
+ .destroy = parked_subscription_datastore_destroy,
+};
+
+static void say_parking_space(struct ast_bridge_channel *bridge_channel, const char *playfile)
+{
+ int numeric_value;
+
+ if (sscanf(playfile, "%d", &numeric_value) != 1) {
+ /* If say_parking_space is called with a non-numeric string, we have a problem. */
+ ast_assert(0);
+ ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+ return;
+ }
+
+ ast_say_digits(bridge_channel->chan, numeric_value, "", ast_channel_language(bridge_channel->chan));
+
+ ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+}
+
+static void parker_parked_call_message_response(struct ast_parked_call_payload *message, struct parked_subscription_data *data,
+ struct stasis_subscription *sub)
+{
+ const char *parkee_to_act_on = data->parkee_uuid;
+ char saynum_buf[16];
+ struct ast_channel_snapshot *parkee_snapshot = message->parkee;
+ RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
+
+ if (strcmp(parkee_to_act_on, parkee_snapshot->uniqueid)) {
+ return;
+ }
+
+ if (message->event_type != PARKED_CALL && message->event_type != PARKED_CALL_FAILED) {
+ /* We only care about these two event types */
+ return;
+ }
+
+ parker = ast_channel_get_by_name(data->parker_uuid);
+ if (!parker) {
+ return;
+ }
+
+ ast_channel_lock(parker);
+
+ bridge_channel = ast_channel_internal_bridge_channel(parker);
+ if (!bridge_channel) {
+ ast_channel_unlock(parker);
+ return;
+ }
+
+ /* this reference will be freed by RAII_VAR */
+ ao2_ref(bridge_channel, +1);
+ ast_channel_unlock(parker);
+
+ if (message->event_type == PARKED_CALL) {
+ /* queue the saynum on the bridge channel and hangup */
+ snprintf(saynum_buf, sizeof(saynum_buf), "%u", message->parkingspace);
+
+ ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
+
+ /* toss the subscription */
+ stasis_unsubscribe(sub);
+ }
+
+ if (message->event_type == PARKED_CALL_FAILED) {
+ ast_bridge_channel_queue_playfile(bridge_channel, NULL, "pbx-parkingfailed", NULL);
+ stasis_unsubscribe(sub);
+ }
+}
+
+static void parker_update_cb(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
+{
+ if (stasis_message_type(message) == ast_parked_call_type()) {
+ struct ast_parked_call_payload *parked_call_message = stasis_message_data(message);
+ parker_parked_call_message_response(parked_call_message, data, sub);
+ }
+}
+
+static struct parked_subscription_datastore *fetch_parked_subscription_datastore(struct ast_channel *chan)
+{
+ struct ast_datastore *datastore = NULL;
+
+ ast_channel_lock(chan);
+ if (!(datastore = ast_channel_datastore_find(chan, &parked_subscription_info, NULL))) {
+ ast_channel_unlock(chan);
+ return NULL;
+ }
+ ast_channel_unlock(chan);
+ return datastore->data;
+}
+
+static int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid)
+{
+ struct ast_datastore *datastore = NULL;
+ struct parked_subscription_datastore *parked_datastore;
+ struct parked_subscription_data *subscription_data;
+
+ /* If there is already a subscription, get rid of it. */
+ if ((parked_datastore = fetch_parked_subscription_datastore(chan))) {
+ stasis_unsubscribe(parked_datastore->parked_subscription);
+ parked_datastore->parked_subscription = NULL;
+ goto datastore_exists;
+ }
+
+ if (!(datastore = ast_datastore_alloc(&parked_subscription_info, NULL))) {
+ return -1;
+ }
+
+ if (!(parked_datastore = ast_calloc(1, sizeof(*parked_datastore)))) {
+ ast_datastore_free(datastore);
+ return -1;
+ }
+
+datastore_exists:
+
+ if (!(subscription_data = ast_calloc(1, sizeof(*subscription_data))))
+ {
+ ast_datastore_free(datastore);
+ ast_free(parked_datastore);
+ }
+
+ subscription_data->parker_uuid = ast_strdup(ast_channel_uniqueid(chan));
+ subscription_data->parkee_uuid = ast_strdup(parkee_uuid);
+
+ if (!(parked_datastore->parked_subscription = stasis_subscribe(ast_parking_topic(), parker_update_cb, subscription_data)))
+
+ /* If the parked_datastore already exists, there is no need to relink it. */
+ if (datastore) {
+ datastore->data = parked_datastore;
+ ast_channel_datastore_add(chan, datastore);
+ }
+
+ return 0;
+}
static int park_feature_helper(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, const char *app_data)
{
- struct ast_bridge_channel *other;
-
+ RAII_VAR(struct ast_channel *, other, NULL, ao2_cleanup);
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);
-
- /* If this is the only channel in this bridge then this feature shouldn't be at all usable. */
- /* XXX Reaching accross the bridge no good */
- if (AST_LIST_FIRST(&bridge->channels) == AST_LIST_LAST(&bridge->channels)) {
+ RAII_VAR(struct ao2_container *, bridge_peers, NULL, ao2_cleanup);
+ struct ao2_iterator iter;
+
+ bridge_peers = ast_bridge_peers(bridge);
+
+ if (ao2_container_count(bridge_peers) < 2) {
+ /* Can't do anything with that. */
return 0;
}
- /* Find the channel we want to park */
- other = AST_LIST_FIRST(&bridge->channels);
- if (other == bridge_channel) {
- other = AST_LIST_LAST(&bridge->channels);
- }
-
- ast_channel_lock(other->chan);
-
- /* Handle all the common parking setup stuff */
- if (park_common_setup(&lot, &parking_bridge, &pu, bridge_channel->chan, other->chan, app_data)) {
+ if (ao2_container_count(bridge_peers) > 2) {
+ /* XXX Need to do the multiparty bridge park... which is a local channel to the parking lot */
return 0;
}
- /* Now for the fun part... park it! */
- if (ast_bridge_move(bridge, parking_bridge, other->chan)) {
+ 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. */
+ if (strcmp(ast_channel_uniqueid(other), ast_channel_uniqueid(bridge_channel->chan))) {
+ break;
+ }
+ }
+
+ if (!other) {
+ ast_assert(0);
+ return -1;
+ }
+
+ /* Subscribe to park messages with the other channel entering */
+ if (create_parked_subscription(bridge_channel->chan, ast_channel_uniqueid(other))) {
+ return -1;
+ }
+
+ /* Write the park frame with the intended recipient and other data out to the bridge. */
+ ast_bridge_channel_write_park(bridge_channel, ast_channel_uniqueid(other), ast_channel_uniqueid(bridge_channel->chan), app_data);
+
+ return 0;
+}
+
+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);
+
+ if (strcmp(ast_channel_uniqueid(bridge_channel->chan), uuid_parkee)) {
+ /* We aren't the parkee, so ignore this action. */
+ return;
+ }
+
+ parker = ast_channel_get_by_name(uuid_parker);
+
+ if (!parker) {
+ ast_log(LOG_NOTICE, "Channel with uuid %s left before we could start parking the call. Parking canceled.\n", uuid_parker);
+ }
+
+ /* 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)) {
+ 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(other->chan), lot->name);
- return 0;
- }
-
- ast_channel_unlock(other->chan);
-
- /* The parker parked the call successfully, so it leaves the bridge now. */
- ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
-
- return 0;
+ ast_channel_name(bridge_channel->chan), lot->name);
+ }
}
static int feature_park(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
@@ -162,11 +351,13 @@
{
ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_PARKCALL);
ast_uninstall_park_blind_xfer_func();
+ ast_uninstall_bridge_channel_park_func();
}
int load_parking_bridge_features(void)
{
ast_bridge_features_register(AST_BRIDGE_BUILTIN_PARKCALL, feature_park, NULL);
ast_install_park_blind_xfer_func(park_feature_helper);
+ ast_install_bridge_channel_park_func(park_bridge_channel);
return 0;
}
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=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_manager.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_manager.c Wed Apr 24 14:39:39 2013
@@ -226,6 +226,19 @@
/*! \brief subscription to the parking lot topic */
static struct stasis_subscription *parking_sub;
+static struct ast_parked_call_payload *parked_call_payload_from_failure(struct ast_channel *chan)
+{
+ RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
+
+ parkee_snapshot = ast_channel_snapshot_create(chan);
+ if (!parkee_snapshot) {
+ return NULL;
+ }
+
+ return ast_parked_call_payload_create(PARKED_CALL_FAILED, parkee_snapshot, NULL, NULL, NULL, 0, 0, 0);
+}
+
static struct ast_parked_call_payload *parked_call_payload_from_parked_user(struct parked_user *pu, enum ast_parked_call_event_type event_type)
{
RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
@@ -266,7 +279,11 @@
}
parkee_string = ast_manager_build_channel_state_string_suffix(payload->parkee, "Parkee");
- parker_string = ast_manager_build_channel_state_string_suffix(payload->parker, "Parker");
+
+ if (payload->parker) {
+ parker_string = ast_manager_build_channel_state_string_suffix(payload->parker, "Parker");
+ }
+
if (payload->retriever) {
retriever_string = ast_manager_build_channel_state_string_suffix(payload->retriever, "Retriever");
}
@@ -281,7 +298,7 @@
"ParkingDuration: %lu\r\n",
ast_str_buffer(parkee_string),
- ast_str_buffer(parker_string),
+ parker_string ? ast_str_buffer(parker_string) : "",
retriever_string ? ast_str_buffer(retriever_string) : "",
payload->parkinglot,
payload->parkingspace,
@@ -464,6 +481,24 @@
return RESULT_SUCCESS;
}
+void publish_parked_call_failure(struct ast_channel *parkee)
+{
+ RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+
+ payload = parked_call_payload_from_failure(parkee);
+ if (!payload) {
+ return;
+ }
+
+ msg = stasis_message_create(ast_parked_call_type(), payload);
+ if (!msg) {
+ return;
+ }
+
+ stasis_publish(ast_parking_topic(), msg);
+}
+
void publish_parked_call(struct parked_user *pu, enum ast_parked_call_event_type event_type)
{
RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
@@ -479,9 +514,7 @@
return;
}
- if (pu->chan) {
- stasis_publish(ast_parking_topic(), msg);
- }
+ stasis_publish(ast_parking_topic(), msg);
}
static void parked_call_message_response(struct ast_parked_call_payload *parked_call)
@@ -502,6 +535,9 @@
case PARKED_CALL_UNPARKED:
event_type = "UnParkedCall";
break;
+ case PARKED_CALL_FAILED:
+ /* PARKED_CALL_FAILED doesn't currently get a message and is used exclusively for bridging */
+ return;
}
parked_call_string = manager_build_parked_call_string(parked_call);
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=386442&r1=386441&r2=386442
==============================================================================
--- team/jrose/bridge_projects/res/parking/res_parking.h (original)
+++ team/jrose/bridge_projects/res/parking/res_parking.h Wed Apr 24 14:39:39 2013
@@ -319,6 +319,14 @@
/*!
* \since 12
+ * \brief Publish a stasis parked call message for the channel indicating failure to park.
+ *
+ * \param parkee channel belonging to the failed parkee
+ */
+void publish_parked_call_failure(struct ast_channel *parkee);
+
+/*!
+ * \since 12
* \brief Publish a stasis parked call message for a given parked user
*
* \param pu pointer to a parked_user that we are generating the message for
@@ -335,6 +343,7 @@
* 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
@@ -348,7 +357,7 @@
* a specific usage example.
*/
int park_common_setup(struct parking_lot **lot, struct ast_bridge **parking_bridge, struct parked_user **pu,
- struct ast_channel *parker, struct ast_channel *parkee, const char *app_data);
+ int *silence_announcements, struct ast_channel *parker, struct ast_channel *parkee, const char *app_data);
/*!
* \since 12
More information about the asterisk-commits
mailing list