Author: rmudgett
Date: Fri Jul 26 16:34:23 2013
New Revision: 395574

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=395574
Log:
Remove the unsafe bridge parameter from ast_bridge_hook_callback's.

Most hook callbacks did not need the bridge parameter.  The pointer value
could become invalid if the channel is moved to another bridge while it is
executing.

* Fixed some issues in feature_attended_transfer() as a result.

* Reduce the bridge inhibit count in
attended_transfer_properties_shutdown() after it has restored the bridge
channel hooks.

* Removed basic bridge requirement on feature_blind_transfer().  It does
not require the basic bridge like feature_attended_transfer().

Modified:
    trunk/apps/app_agent_pool.c
    trunk/apps/app_bridgewait.c
    trunk/apps/app_confbridge.c
    trunk/apps/confbridge/conf_config_parser.c
    trunk/bridges/bridge_builtin_features.c
    trunk/bridges/bridge_builtin_interval_features.c
    trunk/include/asterisk/bridge_features.h
    trunk/include/asterisk/parking.h
    trunk/main/bridge.c
    trunk/main/bridge_basic.c
    trunk/main/bridge_channel.c
    trunk/main/features.c
    trunk/main/parking.c
    trunk/res/parking/parking_bridge_features.c

Modified: trunk/apps/app_agent_pool.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/apps/app_agent_pool.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/apps/app_agent_pool.c (original)
+++ trunk/apps/app_agent_pool.c Fri Jul 26 16:34:23 2013
@@ -1078,12 +1078,11 @@
                 * The agent is in the new bridge so we can invoke the
                 * mixmonitor hook to only start recording.
                 */
-               ast_bridge_features_do(AST_BRIDGE_BUILTIN_AUTOMIXMON, 
caller_bridge,
-                       bridge_channel, &options);
-       }
-}
-
-static int bridge_agent_hold_ack(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+               ast_bridge_features_do(AST_BRIDGE_BUILTIN_AUTOMIXMON, 
bridge_channel, &options);
+       }
+}
+
+static int bridge_agent_hold_ack(struct ast_bridge_channel *bridge_channel, 
void *hook_pvt)
 {
        struct agent_pvt *agent = hook_pvt;
 
@@ -1101,7 +1100,7 @@
        return 0;
 }
 
-static int bridge_agent_hold_heartbeat(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int bridge_agent_hold_heartbeat(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
 {
        struct agent_pvt *agent = hook_pvt;
        int probation_timedout = 0;
@@ -1709,7 +1708,7 @@
        ast_bridge_channel_unlock(logged);
 }
 
-static int caller_safety_timeout(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int caller_safety_timeout(struct ast_bridge_channel *bridge_channel, 
void *hook_pvt)
 {
        struct agent_pvt *agent = hook_pvt;
 

Modified: trunk/apps/app_bridgewait.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/apps/app_bridgewait.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/apps/app_bridgewait.c (original)
+++ trunk/apps/app_bridgewait.c Fri Jul 26 16:34:23 2013
@@ -201,7 +201,7 @@
        AST_APP_OPTION_ARG('S', MUXFLAG_TIMEOUT, OPT_ARG_TIMEOUT),
 });
 
-static int bridgewait_timeout_callback(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int bridgewait_timeout_callback(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
 {
        ast_verb(3, "Channel %s timed out.\n", 
ast_channel_name(bridge_channel->chan));
        ast_bridge_channel_leave_bridge(bridge_channel, 
BRIDGE_CHANNEL_STATE_END);

Modified: trunk/apps/app_confbridge.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/apps/app_confbridge.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/apps/app_confbridge.c (original)
+++ trunk/apps/app_confbridge.c Fri Jul 26 16:34:23 2013
@@ -1402,9 +1402,9 @@
        ast_free(pvt_data);
 }
 
-static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, 
void *pvt_data, int talking)
-{
-       const char *conf_name = pvt_data;
+static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, 
void *hook_pvt, int talking)
+{
+       const char *conf_name = hook_pvt;
        struct confbridge_conference *conference = ao2_find(conference_bridges, 
conf_name, OBJ_KEY);
        struct ast_json *talking_extras;
 

Modified: trunk/apps/confbridge/conf_config_parser.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/apps/confbridge/conf_config_parser.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/apps/confbridge/conf_config_parser.c (original)
+++ trunk/apps/confbridge/conf_config_parser.c Fri Jul 26 16:34:23 2013
@@ -2080,9 +2080,10 @@
        ast_free(pvt);
 }
 
-static int menu_hook_callback(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int menu_hook_callback(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
 {
        struct dtmf_menu_hook_pvt *pvt = hook_pvt;
+
        return conf_handle_dtmf(bridge_channel, pvt->user, &pvt->menu_entry, 
pvt->menu);
 }
 

Modified: trunk/bridges/bridge_builtin_features.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/bridges/bridge_builtin_features.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/bridges/bridge_builtin_features.c (original)
+++ trunk/bridges/bridge_builtin_features.c Fri Jul 26 16:34:23 2013
@@ -214,7 +214,7 @@
        pbx_builtin_setvar_helper(peer_chan, "TOUCH_MONITOR_OUTPUT", 
touch_filename);
 }
 
-static int feature_automonitor(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int feature_automonitor(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
 {
        const char *start_message;
        const char *stop_message;
@@ -226,7 +226,9 @@
        RAII_VAR(struct ast_features_general_config *, features_cfg, NULL, 
ao2_cleanup);
 
        features_cfg = 
ast_get_chan_features_general_config(bridge_channel->chan);
-       peer_chan = ast_bridge_peer(bridge, bridge_channel->chan);
+       ast_bridge_channel_lock_bridge(bridge_channel);
+       peer_chan = ast_bridge_peer_nolock(bridge_channel->bridge, 
bridge_channel->chan);
+       ast_bridge_unlock(bridge_channel->bridge);
 
        if (!peer_chan) {
                ast_verb(3, "Cannot start AutoMonitor for %s - can not 
determine peer in bridge.\n",
@@ -397,7 +399,7 @@
        pbx_builtin_setvar_helper(peer_chan, "TOUCH_MIXMONITOR_OUTPUT", 
touch_filename);
 }
 
-static int feature_automixmonitor(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int feature_automixmonitor(struct ast_bridge_channel *bridge_channel, 
void *hook_pvt)
 {
        static const char *mixmonitor_spy_type = "MixMonitor";
        const char *stop_message;
@@ -410,7 +412,9 @@
        RAII_VAR(struct ast_features_general_config *, features_cfg, NULL, 
ao2_cleanup);
 
        features_cfg = 
ast_get_chan_features_general_config(bridge_channel->chan);
-       peer_chan = ast_bridge_peer(bridge, bridge_channel->chan);
+       ast_bridge_channel_lock_bridge(bridge_channel);
+       peer_chan = ast_bridge_peer_nolock(bridge_channel->bridge, 
bridge_channel->chan);
+       ast_bridge_unlock(bridge_channel->bridge);
 
        if (!peer_chan) {
                ast_verb(3, "Cannot do AutoMixMonitor for %s - cannot determine 
peer in bridge.\n",
@@ -476,7 +480,7 @@
 }
 
 /*! \brief Internal built in feature for hangup */
-static int feature_hangup(struct ast_bridge *bridge, struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
+static int feature_hangup(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
 {
        /*
         * This is very simple, we simply change the state on the

Modified: trunk/bridges/bridge_builtin_interval_features.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/bridges/bridge_builtin_interval_features.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/bridges/bridge_builtin_interval_features.c (original)
+++ trunk/bridges/bridge_builtin_interval_features.c Fri Jul 26 16:34:23 2013
@@ -50,7 +50,7 @@
 #include "asterisk/stringfields.h"
 #include "asterisk/musiconhold.h"
 
-static int bridge_features_duration_callback(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int bridge_features_duration_callback(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
 {
        struct ast_bridge_features_limits *limits = hook_pvt;
 
@@ -110,7 +110,7 @@
        }
 }
 
-static int bridge_features_connect_callback(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int bridge_features_connect_callback(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
 {
        struct ast_bridge_features_limits *limits = hook_pvt;
 
@@ -118,7 +118,7 @@
        return -1;
 }
 
-static int bridge_features_warning_callback(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int bridge_features_warning_callback(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
 {
        struct ast_bridge_features_limits *limits = hook_pvt;
 

Modified: trunk/include/asterisk/bridge_features.h
URL: 
http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridge_features.h?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/include/asterisk/bridge_features.h (original)
+++ trunk/include/asterisk/bridge_features.h Fri Jul 26 16:34:23 2013
@@ -118,7 +118,6 @@
 /*!
  * \brief Hook callback type
  *
- * \param bridge The bridge that the channel is part of
  * \param bridge_channel Channel executing the feature
  * \param hook_pvt Private data passed in when the hook was created
  *
@@ -131,7 +130,7 @@
  * \retval 0 Keep the callback hook.
  * \retval -1 Remove the callback hook.
  */
-typedef int (*ast_bridge_hook_callback)(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt);
+typedef int (*ast_bridge_hook_callback)(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt);
 
 /*!
  * \brief Hook pvt destructor callback
@@ -143,17 +142,19 @@
 /*!
  * \brief Talking indicator callback
  *
- * \details This callback can be registered with the bridge in order
- * to receive updates on when a bridge_channel has started and stopped
- * talking
+ * \details
+ * This callback can be registered with the bridge channel in
+ * order to receive updates when the bridge_channel has started
+ * and stopped talking.
  *
  * \param bridge_channel Channel executing the feature
+ * \param hook_pvt Private data passed in when the hook was created
  * \param talking TRUE if the channel is now talking
  *
  * \retval 0 Keep the callback hook.
  * \retval -1 Remove the callback hook.
  */
-typedef int (*ast_bridge_talking_indicate_callback)(struct ast_bridge_channel 
*bridge_channel, void *pvt_data, int talking);
+typedef int (*ast_bridge_talking_indicate_callback)(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt, int talking);
 
 enum ast_bridge_hook_remove_flags {
        /*! The hook is removed when the channel is pulled from the bridge. */
@@ -357,6 +358,8 @@
  * \brief Invoke a built in feature hook now.
  *
  * \param feature The feature to invoke
+ * \param bridge_channel Channel executing the feature
+ * \param hook_pvt Private data passed in when the hook was created
  *
  * \note This API call is only meant to be used by bridge
  * subclasses and hook callbacks to request a builtin feature
@@ -368,10 +371,10 @@
  * Example usage:
  *
  * \code
- * ast_bridge_features_do(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, bridge, 
bridge_channel, hook_pvt);
- * \endcode
- */
-int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct 
ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt);
+ * ast_bridge_features_do(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, 
bridge_channel, hook_pvt);
+ * \endcode
+ */
+int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt);
 
 /*!
  * \brief Attach interval hooks to a bridge features structure

Modified: trunk/include/asterisk/parking.h
URL: 
http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/parking.h?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/include/asterisk/parking.h (original)
+++ trunk/include/asterisk/parking.h Fri Jul 26 16:34:23 2013
@@ -111,8 +111,7 @@
        const char *parker_uuid,
        const char *app_data);
 
-typedef int (*ast_park_blind_xfer_fn)(struct ast_bridge *bridge, struct 
ast_bridge_channel *parker,
-       struct ast_exten *park_exten);
+typedef int (*ast_park_blind_xfer_fn)(struct ast_bridge_channel *parker, 
struct ast_exten *park_exten);
 
 /*!
  * \brief install a callback for handling blind transfers to a parking 
extension
@@ -132,15 +131,13 @@
  * \brief use the installed park blind xfer func
  * \since 12
  *
- * \param bridge Bridge being transferred from
- * \param bridge_channel Bridge channel initiating the transfer
- * \param app_data arguments to the park application
+ * \param parker Bridge channel initiating the park
+ * \param park_exten Exten to blind transfer part to.
  *
  * \retval 0 on success
  * \retval -1 on failure
  */
-int ast_park_blind_xfer(struct ast_bridge *bridge, struct ast_bridge_channel 
*parker,
-               struct ast_exten *park_exten);
+int ast_park_blind_xfer(struct ast_bridge_channel *parker, struct ast_exten 
*park_exten);
 
 typedef void (*ast_bridge_channel_park_fn)(struct ast_bridge_channel *parkee, 
const char *parkee_uuid,
        const char *parker_uuid, const char *app_data);

Modified: trunk/main/bridge.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/main/bridge.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/main/bridge.c (original)
+++ trunk/main/bridge.c Fri Jul 26 16:34:23 2013
@@ -2675,7 +2675,7 @@
        return 0;
 }
 
-int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct 
ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
+int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
 {
        ast_bridge_hook_callback callback;
 
@@ -2687,7 +2687,7 @@
        if (!callback) {
                return -1;
        }
-       callback(bridge, bridge_channel, hook_pvt);
+       callback(bridge_channel, hook_pvt);
 
        return 0;
 }
@@ -3777,8 +3777,7 @@
        PARKING_NOT_APPLICABLE,
 };
 
-static enum try_parking_result try_parking(struct ast_bridge *bridge, struct 
ast_channel *transferer,
-               const char *exten, const char *context)
+static enum try_parking_result try_parking(struct ast_channel *transferer, 
const char *exten, const char *context)
 {
        RAII_VAR(struct ast_bridge_channel *, transferer_bridge_channel, NULL, 
ao2_cleanup);
        struct ast_exten *parking_exten;
@@ -3793,7 +3792,7 @@
 
        parking_exten = ast_get_parking_exten(exten, NULL, context);
        if (parking_exten) {
-               return ast_park_blind_xfer(bridge, transferer_bridge_channel, 
parking_exten) == 0 ?
+               return ast_park_blind_xfer(transferer_bridge_channel, 
parking_exten) == 0 ?
                        PARKING_SUCCESS : PARKING_FAILURE;
        }
 
@@ -3871,7 +3870,7 @@
        RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
        RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, 
ao2_cleanup);
        RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup);
-       RAII_VAR(struct ast_channel *, transferee, NULL, ao2_cleanup);
+       RAII_VAR(struct ast_channel *, transferee, NULL, ast_channel_cleanup);
        int do_bridge_transfer;
        int transfer_prohibited;
        enum try_parking_result parking_result;
@@ -3893,7 +3892,7 @@
        /* Take off hold if they are on hold. */
        ast_bridge_channel_write_unhold(bridge_channel);
 
-       parking_result = try_parking(bridge, transferer, exten, context);
+       parking_result = try_parking(transferer, exten, context);
        switch (parking_result) {
        case PARKING_SUCCESS:
                transfer_result = AST_BRIDGE_TRANSFER_SUCCESS;

Modified: trunk/main/bridge_basic.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/main/bridge_basic.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/main/bridge_basic.c (original)
+++ trunk/main/bridge_basic.c Fri Jul 26 16:34:23 2013
@@ -265,20 +265,19 @@
  * \brief Determine if we should dissolve the bridge from a hangup.
  * \since 12.0.0
  *
- * \param bridge The bridge that the channel is part of
  * \param bridge_channel Channel executing the feature
  * \param hook_pvt Private data passed in when the hook was created
  *
  * \retval 0 Keep the callback hook.
  * \retval -1 Remove the callback hook.
  */
-static int basic_hangup_hook(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int basic_hangup_hook(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
 {
        int bridge_count = 0;
        struct ast_bridge_channel *iter;
 
        ast_bridge_channel_lock_bridge(bridge_channel);
-       AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
+       AST_LIST_TRAVERSE(&bridge_channel->bridge->channels, iter, entry) {
                if (iter != bridge_channel && iter->state == 
BRIDGE_CHANNEL_STATE_WAIT) {
                        ++bridge_count;
                }
@@ -1069,7 +1068,6 @@
 /*!
  * \brief Allocate and initialize attended transfer properties
  *
- * \param transferee_bridge The bridge where the transfer was initiated
  * \param transferer The channel performing the attended transfer
  * \param context Suggestion for what context the transfer target extension 
can be found in
  *
@@ -1077,8 +1075,7 @@
  * \retval non-NULL Newly allocated properties
  */
 static struct attended_transfer_properties *attended_transfer_properties_alloc(
-               struct ast_bridge *transferee_bridge, struct ast_channel 
*transferer,
-               const char *context)
+       struct ast_channel *transferer, const char *context)
 {
        struct attended_transfer_properties *props;
        char *tech;
@@ -1162,9 +1159,9 @@
        ast_debug(1, "Shutting down attended transfer %p\n", props);
 
        if (props->transferee_bridge) {
-               ast_bridge_merge_inhibit(props->transferee_bridge, -1);
                bridge_basic_change_personality(props->transferee_bridge,
                                BRIDGE_BASIC_PERSONALITY_NORMAL, NULL);
+               ast_bridge_merge_inhibit(props->transferee_bridge, -1);
        }
 
        if (props->target_bridge) {
@@ -2145,7 +2142,7 @@
  *
  * Sends a stimulus to the attended transfer monitor thread that the abort 
sequence has been pressed
  */
-static int atxfer_abort(struct ast_bridge *bridge, struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
+static int atxfer_abort(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
 {
        struct attended_transfer_properties *props = hook_pvt;
 
@@ -2159,7 +2156,7 @@
  *
  * Sends a stimulus to the attended transfer monitor thread that the complete 
sequence has been pressed
  */
-static int atxfer_complete(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int atxfer_complete(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
 {
        struct attended_transfer_properties *props = hook_pvt;
 
@@ -2173,7 +2170,7 @@
  *
  * Sends a stimulus to the attended transfer monitor thread that the threeway 
sequence has been pressed
  */
-static int atxfer_threeway(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int atxfer_threeway(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
 {
        struct attended_transfer_properties *props = hook_pvt;
 
@@ -2187,7 +2184,7 @@
  *
  * Sends a stimulus to the attended transfer monitor thread that the swap 
sequence has been pressed
  */
-static int atxfer_swap(struct ast_bridge *bridge, struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
+static int atxfer_swap(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
 {
        struct attended_transfer_properties *props = hook_pvt;
 
@@ -2201,7 +2198,7 @@
  *
  * Sends a stimulus to the attended transfer monitor thread that the 
transferer has hung up.
  */
-static int atxfer_transferer_hangup(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int atxfer_transferer_hangup(struct ast_bridge_channel *bridge_channel, 
void *hook_pvt)
 {
        struct attended_transfer_properties *props = hook_pvt;
 
@@ -2622,48 +2619,64 @@
  * an attended transfer. For more information about attended transfer
  * progress, see documentation on the transfer state machine.
  *
- * \param bridge Bridge where attended transfer DTMF sequence was entered
  * \param bridge_channel The channel that pressed the attended transfer DTMF 
sequence
  * \param hook_pvt Structure with further information about the attended 
transfer
  */
-static int feature_attended_transfer(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int feature_attended_transfer(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
 {
        struct ast_bridge_features_attended_transfer *attended_transfer = 
hook_pvt;
        struct attended_transfer_properties *props;
+       struct ast_bridge *bridge;
        char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
        char exten[AST_MAX_EXTENSION] = "";
        pthread_t thread;
 
+       /* Inhibit the bridge before we do anything else. */
+       bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
+
        if (strcmp(bridge->v_table->name, "basic")) {
-               ast_log(LOG_ERROR, "Attended transfer attempted on unsupported 
bridge type '%s'\n", bridge->v_table->name);
+               ast_log(LOG_ERROR, "Attended transfer attempted on unsupported 
bridge type '%s'.\n",
+                       bridge->v_table->name);
+               ast_bridge_merge_inhibit(bridge, -1);
+               ao2_ref(bridge, -1);
                return 0;
        }
 
-       if (bridge->inhibit_merge) {
-               ast_log(LOG_ERROR, "Unable to perform attended transfer since 
bridge '%s' does not permit merging.\n", bridge->uniqueid);
+       /* Was the bridge inhibited before we inhibited it? */
+       if (1 < bridge->inhibit_merge) {
+               /*
+                * The peer likely initiated attended transfer at the same time
+                * and we lost the race.
+                */
+               ast_verb(3, "Channel %s: Bridge '%s' does not permit merging at 
this time.\n",
+                       ast_channel_name(bridge_channel->chan), 
bridge->uniqueid);
+               ast_bridge_merge_inhibit(bridge, -1);
+               ao2_ref(bridge, -1);
                return 0;
        }
 
-       props = attended_transfer_properties_alloc(bridge, bridge_channel->chan,
-                       attended_transfer ? attended_transfer->context : NULL);
-
+       props = attended_transfer_properties_alloc(bridge_channel->chan,
+               attended_transfer ? attended_transfer->context : NULL);
        if (!props) {
-               ast_log(LOG_ERROR, "Unable to allocate control structure for 
performing attended transfer\n");
+               ast_log(LOG_ERROR, "Unable to allocate control structure for 
performing attended transfer.\n");
+               ast_bridge_merge_inhibit(bridge, -1);
+               ao2_ref(bridge, -1);
                return 0;
        }
 
+       props->transferee_bridge = bridge;
+
        if (add_transferer_role(props->transferer, attended_transfer)) {
-               ast_log(LOG_ERROR, "Unable to set transferer bridge role 
properly\n");
+               ast_log(LOG_ERROR, "Unable to set transferrer bridge role.\n");
                attended_transfer_properties_shutdown(props);
                return 0;
        }
 
        ast_bridge_channel_write_hold(bridge_channel, NULL);
-       props->transferee_bridge = 
ast_bridge_channel_merge_inhibit(bridge_channel, +1);
 
        /* Grab the extension to transfer to */
        if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), 
props->context)) {
-               ast_log(LOG_WARNING, "Unable to acquire target extension for 
attended transfer\n");
+               ast_log(LOG_WARNING, "Unable to acquire target extension for 
attended transfer.\n");
                ast_bridge_channel_write_unhold(bridge_channel);
                attended_transfer_properties_shutdown(props);
                return 0;
@@ -2679,7 +2692,7 @@
        /* Get a channel that is the destination we wish to call */
        props->transfer_target = dial_transfer(bridge_channel->chan, 
destination);
        if (!props->transfer_target) {
-               ast_log(LOG_ERROR, "Unable to request outbound channel for 
attended transfer target\n");
+               ast_log(LOG_ERROR, "Unable to request outbound channel for 
attended transfer target.\n");
                ast_stream_and_wait(props->transferer, props->failsound, 
AST_DIGIT_NONE);
                ast_bridge_channel_write_unhold(bridge_channel);
                attended_transfer_properties_shutdown(props);
@@ -2690,7 +2703,7 @@
        /* Create a bridge to use to talk to the person we are calling */
        props->target_bridge = ast_bridge_basic_new();
        if (!props->target_bridge) {
-               ast_log(LOG_ERROR, "Unable to create bridge for attended 
transfer target\n");
+               ast_log(LOG_ERROR, "Unable to create bridge for attended 
transfer target.\n");
                ast_stream_and_wait(props->transferer, props->failsound, 
AST_DIGIT_NONE);
                ast_bridge_channel_write_unhold(bridge_channel);
                ast_hangup(props->transfer_target);
@@ -2701,7 +2714,7 @@
        ast_bridge_merge_inhibit(props->target_bridge, +1);
 
        if (attach_framehook(props, props->transfer_target)) {
-               ast_log(LOG_ERROR, "Unable to attach framehook to transfer 
target\n");
+               ast_log(LOG_ERROR, "Unable to attach framehook to transfer 
target.\n");
                ast_stream_and_wait(props->transferer, props->failsound, 
AST_DIGIT_NONE);
                ast_bridge_channel_write_unhold(bridge_channel);
                ast_hangup(props->transfer_target);
@@ -2716,7 +2729,7 @@
                        BRIDGE_BASIC_PERSONALITY_ATXFER, props);
 
        if (ast_call(props->transfer_target, destination, 0)) {
-               ast_log(LOG_ERROR, "Unable to place outbound call to transfer 
target\n");
+               ast_log(LOG_ERROR, "Unable to place outbound call to transfer 
target.\n");
                ast_stream_and_wait(bridge_channel->chan, props->failsound, 
AST_DIGIT_NONE);
                ast_bridge_channel_write_unhold(bridge_channel);
                ast_hangup(props->transfer_target);
@@ -2731,16 +2744,17 @@
         */
        ast_channel_ref(props->transfer_target);
        if (ast_bridge_impart(props->target_bridge, props->transfer_target, 
NULL, NULL, 1)) {
-               ast_log(LOG_ERROR, "Unable to place transfer target into 
bridge\n");
+               ast_log(LOG_ERROR, "Unable to place transfer target into 
bridge.\n");
                ast_stream_and_wait(bridge_channel->chan, props->failsound, 
AST_DIGIT_NONE);
                ast_bridge_channel_write_unhold(bridge_channel);
                ast_hangup(props->transfer_target);
+               props->transfer_target = NULL;
                attended_transfer_properties_shutdown(props);
                return 0;
        }
 
        if (ast_pthread_create_detached(&thread, NULL, 
attended_transfer_monitor_thread, props)) {
-               ast_log(LOG_ERROR, "Unable to create monitoring thread for 
attended transfer\n");
+               ast_log(LOG_ERROR, "Unable to create monitoring thread for 
attended transfer.\n");
                ast_stream_and_wait(bridge_channel->chan, props->failsound, 
AST_DIGIT_NONE);
                ast_bridge_channel_write_unhold(bridge_channel);
                attended_transfer_properties_shutdown(props);
@@ -2764,17 +2778,12 @@
 }
 
 /*! \brief Internal built in feature for blind transfers */
-static int feature_blind_transfer(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int feature_blind_transfer(struct ast_bridge_channel *bridge_channel, 
void *hook_pvt)
 {
        char exten[AST_MAX_EXTENSION] = "";
        struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
        const char *context;
        char *goto_on_blindxfr;
-
-       if (strcmp(bridge->v_table->name, "basic")) {
-               ast_log(LOG_ERROR, "Blind transfer attempted on unsupported 
bridge type '%s'\n", bridge->v_table->name);
-               return 0;
-       }
 
        ast_bridge_channel_write_hold(bridge_channel, NULL);
 

Modified: trunk/main/bridge_channel.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/main/bridge_channel.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/main/bridge_channel.c (original)
+++ trunk/main/bridge_channel.c Fri Jul 26 16:34:23 2013
@@ -283,7 +283,7 @@
                if (hook->type != AST_BRIDGE_HOOK_TYPE_HANGUP) {
                        continue;
                }
-               remove_me = hook->callback(bridge_channel->bridge, 
bridge_channel, hook->hook_pvt);
+               remove_me = hook->callback(bridge_channel, hook->hook_pvt);
                if (remove_me) {
                        ast_debug(1, "Hangup hook %p is being removed from 
%p(%s)\n",
                                hook, bridge_channel, 
ast_channel_name(bridge_channel->chan));
@@ -916,8 +916,7 @@
 
                ast_debug(1, "Executing hook %p on %p(%s)\n",
                        hook, bridge_channel, 
ast_channel_name(bridge_channel->chan));
-               interval = hook->generic.callback(bridge_channel->bridge, 
bridge_channel,
-                       hook->generic.hook_pvt);
+               interval = hook->generic.callback(bridge_channel, 
hook->generic.hook_pvt);
 
                ast_heap_wrlock(interval_hooks);
                if (ast_heap_peek(interval_hooks, hook->timer.heap_index) != 
hook
@@ -1053,8 +1052,7 @@
        if (hook) {
                int remove_me;
 
-               remove_me = hook->generic.callback(bridge_channel->bridge, 
bridge_channel,
-                       hook->generic.hook_pvt);
+               remove_me = hook->generic.callback(bridge_channel, 
hook->generic.hook_pvt);
                if (remove_me) {
                        ast_debug(1, "DTMF hook %p is being removed from 
%p(%s)\n",
                                hook, bridge_channel, 
ast_channel_name(bridge_channel->chan));
@@ -1782,7 +1780,7 @@
                ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
                do {
                        if (hook->type == type) {
-                               hook->callback(bridge_channel->bridge, 
bridge_channel, hook->hook_pvt);
+                               hook->callback(bridge_channel, hook->hook_pvt);
                                ao2_unlink(features->other_hooks, hook);
                        }
                        ao2_ref(hook, -1);

Modified: trunk/main/features.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/main/features.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/main/features.c (original)
+++ trunk/main/features.c Fri Jul 26 16:34:23 2013
@@ -1842,14 +1842,13 @@
  * \brief Activated dynamic DTMF feature hook.
  * \since 12.0.0
  *
- * \param bridge The bridge that the channel is part of
  * \param bridge_channel Channel executing the feature
  * \param hook_pvt Private data passed in when the hook was created
  *
  * \retval 0 Keep the callback hook.
  * \retval -1 Remove the callback hook.
  */
-static int dynamic_dtmf_hook_trip(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int dynamic_dtmf_hook_trip(struct ast_bridge_channel *bridge_channel, 
void *hook_pvt)
 {
        struct dynamic_dtmf_hook_data *pvt = hook_pvt;
        int (*run_it)(struct ast_bridge_channel *bridge_channel, 
ast_bridge_custom_callback_fn callback, const void *payload, size_t 
payload_size);

Modified: trunk/main/parking.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/main/parking.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/main/parking.c (original)
+++ trunk/main/parking.c Fri Jul 26 16:34:23 2013
@@ -147,12 +147,12 @@
        ast_bridge_channel_park_func = NULL;
 }
 
-int ast_park_blind_xfer(struct ast_bridge *bridge, struct ast_bridge_channel 
*parker,
-               struct ast_exten *park_exten)
+int ast_park_blind_xfer(struct ast_bridge_channel *parker, struct ast_exten 
*park_exten)
 {
        static int warned = 0;
+
        if (ast_park_blind_xfer_func) {
-               return ast_park_blind_xfer_func(bridge, parker, park_exten);
+               return ast_park_blind_xfer_func(parker, park_exten);
        }
 
        if (warned++ % 10 == 0) {

Modified: trunk/res/parking/parking_bridge_features.c
URL: 
http://svnview.digium.com/svn/asterisk/trunk/res/parking/parking_bridge_features.c?view=diff&rev=395574&r1=395573&r2=395574
==============================================================================
--- trunk/res/parking/parking_bridge_features.c (original)
+++ trunk/res/parking/parking_bridge_features.c Fri Jul 26 16:34:23 2013
@@ -183,7 +183,7 @@
 /*!
  * \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
+ *        identical to the dial_transfer function in bridge_basic.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)
@@ -242,7 +242,7 @@
        return parkee;
 }
 
-static int park_feature_helper(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, struct ast_exten *park_exten)
+static int park_feature_helper(struct ast_bridge_channel *bridge_channel, 
struct ast_exten *park_exten)
 {
        RAII_VAR(struct ast_channel *, other, NULL, ao2_cleanup);
        RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
@@ -251,7 +251,9 @@
        RAII_VAR(struct ao2_container *, bridge_peers, NULL, ao2_cleanup);
        struct ao2_iterator iter;
 
-       bridge_peers = ast_bridge_peers(bridge);
+       ast_bridge_channel_lock_bridge(bridge_channel);
+       bridge_peers = ast_bridge_peers_nolock(bridge_channel->bridge);
+       ast_bridge_unlock(bridge_channel->bridge);
 
        if (ao2_container_count(bridge_peers) < 2) {
                /* There is nothing to do if there is no one to park. */
@@ -357,20 +359,19 @@
        }
 }
 
-static int feature_park(struct ast_bridge *bridge, struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
-{
-       park_feature_helper(bridge, bridge_channel, NULL);
+static int feature_park(struct ast_bridge_channel *bridge_channel, void 
*hook_pvt)
+{
+       park_feature_helper(bridge_channel, NULL);
        return 0;
 }
 
 /*! \internal
  * \brief Interval hook. Pulls a parked call from the parking bridge after the 
timeout is passed and sets the resolution to timeout.
  *
- * \param bridge Which bridge the channel was parked in
  * \param bridge_channel bridge channel this interval hook is being executed on
  * \param hook_pvt A pointer to the parked_user struct associated with the 
channel is stuffed in here
  */
-static int parking_duration_callback(struct ast_bridge *bridge, struct 
ast_bridge_channel *bridge_channel, void *hook_pvt)
+static int parking_duration_callback(struct ast_bridge_channel 
*bridge_channel, void *hook_pvt)
 {
        struct parked_user *user = hook_pvt;
        struct ast_channel *chan = user->chan;


--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to