[asterisk-commits] rmudgett: branch rmudgett/bridge_tasks r383515 - in /team/rmudgett/bridge_tas...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Mar 21 11:10:43 CDT 2013
Author: rmudgett
Date: Thu Mar 21 11:10:39 2013
New Revision: 383515
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383515
Log:
* Make DTMF, hangup, and interval hooks ao2 objects.
* Protect interval hooks from other threads adding/removing interval
hooks.
* Made callers of ast_bridge_features_init() check its return value.
Modified:
team/rmudgett/bridge_tasks/apps/app_bridgewait.c
team/rmudgett/bridge_tasks/apps/app_confbridge.c
team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c
team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c
team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h
team/rmudgett/bridge_tasks/main/bridging.c
team/rmudgett/bridge_tasks/main/features.c
Modified: team/rmudgett/bridge_tasks/apps/app_bridgewait.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/apps/app_bridgewait.c?view=diff&rev=383515&r1=383514&r2=383515
==============================================================================
--- team/rmudgett/bridge_tasks/apps/app_bridgewait.c (original)
+++ team/rmudgett/bridge_tasks/apps/app_bridgewait.c Thu Mar 21 11:10:39 2013
@@ -200,7 +200,6 @@
AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM, NULL);
}
ast_mutex_unlock(&bridgewait_lock);
-
if (!holding_bridge) {
ast_log(LOG_ERROR, "Could not create holding bridge for '%s'.\n", ast_channel_name(chan));
return -1;
@@ -209,7 +208,10 @@
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- ast_bridge_features_init(&chan_features);
+ if (ast_bridge_features_init(&chan_features)) {
+ ast_bridge_features_cleanup(&chan_features);
+ return -1;
+ }
if (args.options) {
char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
Modified: team/rmudgett/bridge_tasks/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/apps/app_confbridge.c?view=diff&rev=383515&r1=383514&r2=383515
==============================================================================
--- team/rmudgett/bridge_tasks/apps/app_confbridge.c (original)
+++ team/rmudgett/bridge_tasks/apps/app_confbridge.c Thu Mar 21 11:10:39 2013
@@ -1644,10 +1644,14 @@
AST_APP_ARG(u_profile_name);
AST_APP_ARG(menu_name);
);
- ast_bridge_features_init(&user.features);
if (ast_channel_state(chan) != AST_STATE_UP) {
ast_answer(chan);
+ }
+
+ if (ast_bridge_features_init(&user.features)) {
+ res = -1;
+ goto confbridge_cleanup;
}
if (ast_strlen_zero(data)) {
Modified: team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c?view=diff&rev=383515&r1=383514&r2=383515
==============================================================================
--- team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c (original)
+++ team/rmudgett/bridge_tasks/bridges/bridge_builtin_features.c Thu Mar 21 11:10:39 2013
@@ -269,16 +269,41 @@
/* Get a channel that is the destination we wish to call */
peer = dial_transfer(bridge_channel->chan, exten, context);
if (!peer) {
+/* BUGBUG beeperr needs to be configurable from features.conf */
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
return 0;
}
-/* BUGBUG we need to wait for Party C (peer) to answer before dumping into the transient B-C bridge. */
+/* BUGBUG bridging API features does not support features.conf featuremap */
+/* BUGBUG bridging API features does not support the features.conf atxfer bounce between C & B channels */
+ /* Setup a DTMF menu to control the transfer. */
+ if (ast_bridge_features_init(&caller_features)
+ || ast_bridge_hangup_hook(&caller_features,
+ attended_transfer_complete, &transfer_code, NULL)
+ || ast_bridge_dtmf_hook(&caller_features,
+ attended_transfer && !ast_strlen_zero(attended_transfer->abort)
+ ? attended_transfer->abort : "*1",
+ attended_transfer_abort, &transfer_code, NULL)
+ || ast_bridge_dtmf_hook(&caller_features,
+ attended_transfer && !ast_strlen_zero(attended_transfer->complete)
+ ? attended_transfer->complete : "*2",
+ attended_transfer_complete, &transfer_code, NULL)
+ || ast_bridge_dtmf_hook(&caller_features,
+ attended_transfer && !ast_strlen_zero(attended_transfer->threeway)
+ ? attended_transfer->threeway : "*3",
+ attended_transfer_threeway, &transfer_code, NULL)) {
+ ast_bridge_features_cleanup(&caller_features);
+ ast_hangup(peer);
+/* BUGBUG beeperr needs to be configurable from features.conf */
+ ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
+ return 0;
+ }
/* Create a bridge to use to talk to the person we are calling */
attended_bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX,
AST_BRIDGE_FLAG_DISSOLVE_HANGUP, NULL);
if (!attended_bridge) {
+ ast_bridge_features_cleanup(&caller_features);
ast_hangup(peer);
/* BUGBUG beeperr needs to be configurable from features.conf */
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
@@ -289,29 +314,12 @@
/* BUGBUG we should impart the peer as an independent and move it to the original bridge. */
if (ast_bridge_impart(attended_bridge, peer, NULL, NULL, 0)) {
ast_bridge_destroy(attended_bridge);
+ ast_bridge_features_cleanup(&caller_features);
ast_hangup(peer);
+/* BUGBUG beeperr needs to be configurable from features.conf */
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
return 0;
}
-
- /* Setup a DTMF menu to control the transfer. */
- ast_bridge_features_init(&caller_features);
-/* BUGBUG bridging API features does not support features.conf featuremap */
-/* BUGBUG bridging API features does not support the features.conf atxfer bounce between C & B channels */
- ast_bridge_hangup_hook(&caller_features,
- attended_transfer_complete, &transfer_code, NULL);
- ast_bridge_dtmf_hook(&caller_features,
- attended_transfer && !ast_strlen_zero(attended_transfer->abort)
- ? attended_transfer->abort : "*1",
- attended_transfer_abort, &transfer_code, NULL);
- ast_bridge_dtmf_hook(&caller_features,
- attended_transfer && !ast_strlen_zero(attended_transfer->complete)
- ? attended_transfer->complete : "*2",
- attended_transfer_complete, &transfer_code, NULL);
- ast_bridge_dtmf_hook(&caller_features,
- attended_transfer && !ast_strlen_zero(attended_transfer->threeway)
- ? attended_transfer->threeway : "*3",
- attended_transfer_threeway, &transfer_code, NULL);
/*
* For the caller we want to join the bridge in a blocking
@@ -329,8 +337,8 @@
}
/* Now that all channels are out of it we can destroy the bridge and the feature structures */
+ ast_bridge_destroy(attended_bridge);
ast_bridge_features_cleanup(&caller_features);
- ast_bridge_destroy(attended_bridge);
xfer_failed = -1;
switch (transfer_code) {
Modified: team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c?view=diff&rev=383515&r1=383514&r2=383515
==============================================================================
--- team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c (original)
+++ team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c Thu Mar 21 11:10:39 2013
@@ -125,11 +125,7 @@
limits_interval_playback(bridge, bridge_channel, limits, limits->warning_sound);
}
- if (limits->frequency) {
- ast_bridge_interval_hook_update(bridge_channel, limits->frequency);
- }
-
- return !limits->frequency ? -1 : 0;
+ return !limits->frequency ? -1 : limits->frequency;
}
static void copy_bridge_features_limits(struct ast_bridge_features_limits *dst, struct ast_bridge_features_limits *src)
@@ -169,6 +165,7 @@
copy_bridge_features_limits(feature_limits, limits);
features->limits = feature_limits;
+/* BUGBUG feature interval hooks need to be reimplemented to be more stand alone. */
if (ast_bridge_interval_hook(features, feature_limits->duration,
bridge_features_duration_callback, feature_limits, NULL)) {
ast_log(LOG_ERROR, "Failed to schedule the duration limiter to the bridge channel.\n");
Modified: team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h?view=diff&rev=383515&r1=383514&r2=383515
==============================================================================
--- team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h (original)
+++ team/rmudgett/bridge_tasks/include/asterisk/bridging_features.h Thu Mar 21 11:10:39 2013
@@ -106,6 +106,12 @@
* \param bridge_channel Channel executing the feature
* \param hook_pvt Private data passed in when the hook was created
*
+ * For interval hooks:
+ * \retval 0 Setup to fire again at the last interval.
+ * \retval positive Setup to fire again at the new interval returned.
+ * \retval -1 Remove the callback hook.
+ *
+ * For other hooks:
* \retval 0 Keep the callback hook.
* \retval -1 Remove the callback hook.
*/
@@ -152,7 +158,7 @@
/*! Time at which the hook should actually trip */
struct timeval trip_time;
/*! Heap index for interval hook */
- ssize_t __heap_index;
+ ssize_t heap_index;
/*! Interval that the hook should execute at in milliseconds */
unsigned int interval;
/*! Sequence number for the hook to ensure expiration ordering */
@@ -426,28 +432,6 @@
ast_bridge_hook_pvt_destructor destructor);
/*!
- * \brief Update the interval on an interval hook that is currently executing a callback
- *
- * \param bridge_channel The bridge channel that is executing the callback
- * \param interval The new interval value or 0 to remove the interval hook
- *
- * \retval 0 on success
- * \retval 1 on failure
- *
- * Example usage:
- *
- * \code
- * ast_bridge_interval_hook_update(bridge_channel, 10000);
- * \endcode
- *
- * This updates the executing interval hook so that it will be triggered next in 10 seconds.
- *
- * \note This can only be called from the context of the interval hook callback itself. If this
- * is called outside the callback then behavior is undefined.
- */
-int ast_bridge_interval_hook_update(struct ast_bridge_channel *bridge_channel, unsigned int interval);
-
-/*!
* \brief Set a callback on the features structure to receive talking notifications on.
*
* \param features Bridge features structure
Modified: team/rmudgett/bridge_tasks/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/main/bridging.c?view=diff&rev=383515&r1=383514&r2=383515
==============================================================================
--- team/rmudgett/bridge_tasks/main/bridging.c (original)
+++ team/rmudgett/bridge_tasks/main/bridging.c Thu Mar 21 11:10:39 2013
@@ -574,10 +574,7 @@
ast_debug(1, "Hangup hook %p is being removed from bridge channel %p(%s)\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
AST_LIST_REMOVE_CURRENT(entry);
- if (hook->destructor) {
- hook->destructor(hook->hook_pvt);
- }
- ast_free(hook);
+ ao2_ref(hook, -1);
}
}
AST_LIST_TRAVERSE_SAFE_END;
@@ -591,18 +588,19 @@
{
struct ast_bridge_features *features;
struct ast_bridge_hook *hook;
+ int ready;
features = bridge_channel->features;
if (!features || !features->interval_hooks) {
return 0;
}
+ ast_heap_wrlock(features->interval_hooks);
hook = ast_heap_peek(features->interval_hooks, 1);
- if (!hook || ast_tvdiff_ms(hook->parms.timer.trip_time, ast_tvnow()) > 0) {
- return 0;
- }
-
- return 1;
+ ready = hook && ast_tvdiff_ms(hook->parms.timer.trip_time, ast_tvnow()) <= 0;
+ ast_heap_unlock(features->interval_hooks);
+
+ return ready;
}
/*! \brief Internal function used to determine whether a control frame should be dropped or not */
@@ -1369,52 +1367,72 @@
static void bridge_channel_interval(struct ast_bridge_channel *bridge_channel)
{
struct ast_bridge_hook *hook;
-
+ struct timeval start;
+
+ ast_heap_wrlock(bridge_channel->features->interval_hooks);
+ start = ast_tvnow();
while ((hook = ast_heap_peek(bridge_channel->features->interval_hooks, 1))) {
- int res;
- struct timeval start = ast_tvnow();
- int execution_time = 0;
+ int interval;
+ unsigned int execution_time;
if (ast_tvdiff_ms(hook->parms.timer.trip_time, start) > 0) {
ast_debug(1, "Hook %p on bridge channel %p(%s) wants to happen in the future, stopping our traversal\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
break;
}
+ ao2_ref(hook, +1);
+ ast_heap_unlock(bridge_channel->features->interval_hooks);
ast_debug(1, "Executing hook %p on bridge channel %p(%s)\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
- res = hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
-
- /*
- * Must be popped after the callback. The callback could call
- * ast_bridge_interval_hook_update().
- */
- ast_heap_pop(bridge_channel->features->interval_hooks);
-
- if (res || !hook->parms.timer.interval) {
- ast_debug(1, "Interval hook %p is being removed from bridge channel %p(%s)\n",
+ interval = hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
+
+ ast_heap_wrlock(bridge_channel->features->interval_hooks);
+ if (ast_heap_peek(bridge_channel->features->interval_hooks,
+ hook->parms.timer.heap_index) != hook
+ || !ast_heap_remove(bridge_channel->features->interval_hooks, hook)) {
+ /* Interval hook is already removed from the bridge_channel. */
+ ao2_ref(hook, -1);
+ continue;
+ }
+ ao2_ref(hook, -1);
+
+ if (interval < 0) {
+ ast_debug(1, "Removed interval hook %p from bridge channel %p(%s)\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
- if (hook->destructor) {
- hook->destructor(hook->hook_pvt);
- }
- ast_free(hook);
+ ao2_ref(hook, -1);
continue;
+ }
+ if (interval) {
+ /* Set new interval for the hook. */
+ hook->parms.timer.interval = interval;
}
ast_debug(1, "Updating interval hook %p with interval %u on bridge channel %p(%s)\n",
hook, hook->parms.timer.interval, bridge_channel,
ast_channel_name(bridge_channel->chan));
- execution_time = ast_tvdiff_ms(ast_tvnow(), start);
-
/* resetting start */
start = ast_tvnow();
+ /*
+ * Resetup the interval hook for the next interval. We may need
+ * to skip over any missed intervals because the hook was
+ * delayed or took too long.
+ */
+ execution_time = ast_tvdiff_ms(start, hook->parms.timer.trip_time);
+ while (hook->parms.timer.interval < execution_time) {
+ execution_time -= hook->parms.timer.interval;
+ }
hook->parms.timer.trip_time = ast_tvadd(start, ast_samp2tv(hook->parms.timer.interval - execution_time, 1000));
-
hook->parms.timer.seqno = ast_atomic_fetchadd_int((int *) &bridge_channel->features->interval_sequence, +1);
- ast_heap_push(bridge_channel->features->interval_hooks, hook);
- }
+
+ if (ast_heap_push(bridge_channel->features->interval_hooks, hook)) {
+ /* Could not push the hook back onto the heap. */
+ ao2_ref(hook, -1);
+ }
+ }
+ ast_heap_unlock(bridge_channel->features->interval_hooks);
}
/*!
@@ -1504,10 +1522,7 @@
ast_debug(1, "DTMF hook %p is being removed from bridge channel %p(%s)\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
AST_LIST_REMOVE_CURRENT(entry);
- if (hook->destructor) {
- hook->destructor(hook->hook_pvt);
- }
- ast_free(hook);
+ ao2_ref(hook, -1);
break;
}
}
@@ -2610,6 +2625,52 @@
}
+/*!
+ * \internal
+ * \brief Bridge hook destructor.
+ * \since 12.0.0
+ *
+ * \param vhook Object to destroy.
+ *
+ * \return Nothing
+ */
+static void bridge_hook_destroy(void *vhook)
+{
+ struct ast_bridge_hook *hook = vhook;
+
+ if (hook->destructor) {
+ hook->destructor(hook->hook_pvt);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Allocate and setup a generic bridge hook.
+ * \since 12.0.0
+ *
+ * \param size How big an object to allocate.
+ * \param callback Function to execute upon activation
+ * \param hook_pvt Unique data
+ * \param destructor Optional destructor callback for hook_pvt data
+ *
+ * \retval hook on success.
+ * \retval NULL on error.
+ */
+static struct ast_bridge_hook *bridge_hook_generic(size_t size, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor)
+{
+ struct ast_bridge_hook *hook;
+
+ /* Allocate new hook and setup it's basic variables */
+ hook = ao2_alloc_options(size, bridge_hook_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (hook) {
+ hook->callback = callback;
+ hook->destructor = destructor;
+ hook->hook_pvt = hook_pvt;
+ }
+
+ return hook;
+}
+
int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
const char *dtmf,
ast_bridge_hook_callback callback,
@@ -2618,15 +2679,12 @@
{
struct ast_bridge_hook *hook;
- /* Allocate new memory and setup it's various variables */
- hook = ast_calloc(1, sizeof(*hook));
+ /* Allocate new hook and setup it's various variables */
+ hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor);
if (!hook) {
return -1;
}
ast_copy_string(hook->parms.dtmf.code, dtmf, sizeof(hook->parms.dtmf.code));
- hook->callback = callback;
- hook->destructor = destructor;
- hook->hook_pvt = hook_pvt;
/* Once done we add it onto the list. */
AST_LIST_INSERT_TAIL(&features->dtmf_hooks, hook, entry);
@@ -2641,14 +2699,11 @@
{
struct ast_bridge_hook *hook;
- /* Allocate new memory and setup it's various variables */
- hook = ast_calloc(1, sizeof(*hook));
+ /* Allocate new hook and setup it's various variables */
+ hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor);
if (!hook) {
return -1;
}
- hook->callback = callback;
- hook->destructor = destructor;
- hook->hook_pvt = hook_pvt;
/* Once done we add it onto the list. */
AST_LIST_INSERT_TAIL(&features->hangup_hooks, hook, entry);
@@ -2672,49 +2727,36 @@
void *hook_pvt,
ast_bridge_hook_pvt_destructor destructor)
{
- struct ast_bridge_hook *hook = NULL;
-
- if (!interval || !callback || !features || !features->interval_hooks
- || !(hook = ast_calloc(1, sizeof(*hook)))) {
+ struct ast_bridge_hook *hook;
+
+ if (!interval || !callback || !features || !features->interval_hooks) {
return -1;
}
if (!features->interval_timer) {
if (!(features->interval_timer = ast_timer_open())) {
ast_log(LOG_ERROR, "Failed to open a timer when adding a timed bridging feature.\n");
- ast_free(hook);
return -1;
}
ast_timer_set_rate(features->interval_timer, BRIDGE_FEATURES_INTERVAL_RATE);
}
+ /* Allocate new hook and setup it's various variables */
+ hook = bridge_hook_generic(sizeof(*hook), callback, hook_pvt, destructor);
+ if (!hook) {
+ return -1;
+ }
hook->parms.timer.interval = interval;
- hook->callback = callback;
- hook->destructor = destructor;
- hook->hook_pvt = hook_pvt;
+ hook->parms.timer.trip_time = ast_tvadd(ast_tvnow(), ast_samp2tv(hook->parms.timer.interval, 1000));
+ hook->parms.timer.seqno = ast_atomic_fetchadd_int((int *) &features->interval_sequence, +1);
ast_debug(1, "Putting interval hook %p with interval %u in the heap on features %p\n",
hook, hook->parms.timer.interval, features);
- hook->parms.timer.trip_time = ast_tvadd(ast_tvnow(), ast_samp2tv(hook->parms.timer.interval, 1000));
- hook->parms.timer.seqno = ast_atomic_fetchadd_int((int *) &features->interval_sequence, +1);
- ast_heap_push(features->interval_hooks, hook);
-
- return 0;
-}
-
-int ast_bridge_interval_hook_update(struct ast_bridge_channel *bridge_channel, unsigned int interval)
-{
- struct ast_bridge_hook *hook;
-
- if (!bridge_channel->features || !bridge_channel->features->interval_hooks) {
- return -1;
- }
-
- hook = ast_heap_peek(bridge_channel->features->interval_hooks, 1);
- if (!hook) {
- return -1;
- }
- hook->parms.timer.interval = interval;
+ ast_heap_wrlock(features->interval_hooks);
+ if (ast_heap_push(features->interval_hooks, hook)) {
+ ao2_ref(hook, -1);
+ }
+ ast_heap_unlock(features->interval_hooks);
return 0;
}
@@ -2809,7 +2851,10 @@
/* Initialize the interval hook heap */
features->interval_hooks = ast_heap_create(8, interval_hook_time_cmp,
- offsetof(struct ast_bridge_hook, parms.timer.__heap_index));
+ offsetof(struct ast_bridge_hook, parms.timer.heap_index));
+ if (features->interval_hooks) {
+ return -1;
+ }
return 0;
}
@@ -2822,12 +2867,8 @@
/* Destroy each interval hook. */
if (features->interval_hooks) {
while ((hook = ast_heap_pop(features->interval_hooks))) {
- if (hook->destructor) {
- hook->destructor(hook->hook_pvt);
- }
- ast_free(hook);
- }
-
+ ao2_ref(hook, -1);
+ }
features->interval_hooks = ast_heap_destroy(features->interval_hooks);
}
if (features->interval_timer) {
@@ -2849,19 +2890,22 @@
/* Destroy each hangup hook. */
while ((hook = AST_LIST_REMOVE_HEAD(&features->hangup_hooks, entry))) {
- if (hook->destructor) {
- hook->destructor(hook->hook_pvt);
- }
- ast_free(hook);
+ ao2_ref(hook, -1);
}
/* Destroy each DTMF feature hook. */
while ((hook = AST_LIST_REMOVE_HEAD(&features->dtmf_hooks, entry))) {
- if (hook->destructor) {
- hook->destructor(hook->hook_pvt);
- }
- ast_free(hook);
- }
+ ao2_ref(hook, -1);
+ }
+}
+
+void ast_bridge_features_destroy(struct ast_bridge_features *features)
+{
+ if (!features) {
+ return;
+ }
+ ast_bridge_features_cleanup(features);
+ ast_free(features);
}
struct ast_bridge_features *ast_bridge_features_new(void)
@@ -2870,19 +2914,13 @@
features = ast_malloc(sizeof(*features));
if (features) {
- ast_bridge_features_init(features);
+ if (ast_bridge_features_init(features)) {
+ ast_bridge_features_destroy(features);
+ features = NULL;
+ }
}
return features;
-}
-
-void ast_bridge_features_destroy(struct ast_bridge_features *features)
-{
- if (!features) {
- return;
- }
- ast_bridge_features_cleanup(features);
- ast_free(features);
}
int ast_bridge_dtmf_stream(struct ast_bridge *bridge, const char *dtmf, struct ast_channel *chan)
Modified: team/rmudgett/bridge_tasks/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/main/features.c?view=diff&rev=383515&r1=383514&r2=383515
==============================================================================
--- team/rmudgett/bridge_tasks/main/features.c (original)
+++ team/rmudgett/bridge_tasks/main/features.c Thu Mar 21 11:10:39 2013
@@ -4428,6 +4428,7 @@
pbx_builtin_setvar_helper(chan, "BRIDGEPEER", ast_channel_name(peer));
pbx_builtin_setvar_helper(peer, "BRIDGEPEER", ast_channel_name(chan));
+/* BUGBUG revisit how BLINDTRANSFER operates with the new bridging model. */
/* Clear any BLINDTRANSFER since the transfer has completed. */
pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", NULL);
@@ -4477,9 +4478,9 @@
clear_dialed_interfaces(peer);
/* Setup DTMF features. */
- ast_bridge_features_init(&chan_features);
+ res = ast_bridge_features_init(&chan_features);
peer_features = ast_bridge_features_new();
- if (!peer_features
+ if (res || !peer_features
|| setup_bridge_channel_features(peer_features, &config->features_callee)
|| setup_bridge_channel_features(&chan_features, &config->features_caller)) {
ast_bridge_features_destroy(peer_features);
More information about the asterisk-commits
mailing list