Author: dlee
Date: Mon Jul 29 10:10:09 2013
New Revision: 395656

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=395656
Log:
Merged revisions 395367-395588 from http://svn.asterisk.org/svn/asterisk/trunk

Added:
    team/dlee/record-controls/include/asterisk/bridge.h
      - copied unchanged from r395588, trunk/include/asterisk/bridge.h
    team/dlee/record-controls/include/asterisk/bridge_after.h
      - copied unchanged from r395588, trunk/include/asterisk/bridge_after.h
    team/dlee/record-controls/include/asterisk/bridge_basic.h
      - copied unchanged from r395588, trunk/include/asterisk/bridge_basic.h
    team/dlee/record-controls/include/asterisk/bridge_channel.h
      - copied unchanged from r395588, trunk/include/asterisk/bridge_channel.h
    team/dlee/record-controls/include/asterisk/bridge_channel_internal.h
      - copied unchanged from r395588, 
trunk/include/asterisk/bridge_channel_internal.h
    team/dlee/record-controls/include/asterisk/bridge_features.h
      - copied unchanged from r395588, trunk/include/asterisk/bridge_features.h
    team/dlee/record-controls/include/asterisk/bridge_internal.h
      - copied unchanged from r395588, trunk/include/asterisk/bridge_internal.h
    team/dlee/record-controls/include/asterisk/bridge_roles.h
      - copied unchanged from r395588, trunk/include/asterisk/bridge_roles.h
    team/dlee/record-controls/include/asterisk/bridge_technology.h
      - copied unchanged from r395588, 
trunk/include/asterisk/bridge_technology.h
    team/dlee/record-controls/include/asterisk/stasis_bridges.h
      - copied unchanged from r395588, trunk/include/asterisk/stasis_bridges.h
    team/dlee/record-controls/main/bridge.c
      - copied unchanged from r395588, trunk/main/bridge.c
    team/dlee/record-controls/main/bridge_after.c
      - copied unchanged from r395588, trunk/main/bridge_after.c
    team/dlee/record-controls/main/bridge_basic.c
      - copied unchanged from r395588, trunk/main/bridge_basic.c
    team/dlee/record-controls/main/bridge_channel.c
      - copied unchanged from r395588, trunk/main/bridge_channel.c
    team/dlee/record-controls/main/bridge_roles.c
      - copied unchanged from r395588, trunk/main/bridge_roles.c
    team/dlee/record-controls/main/manager_bridges.c
      - copied unchanged from r395588, trunk/main/manager_bridges.c
    team/dlee/record-controls/main/stasis_bridges.c
      - copied unchanged from r395588, trunk/main/stasis_bridges.c
Removed:
    team/dlee/record-controls/include/asterisk/bridging.h
    team/dlee/record-controls/include/asterisk/bridging_basic.h
    team/dlee/record-controls/include/asterisk/bridging_channel.h
    team/dlee/record-controls/include/asterisk/bridging_channel_internal.h
    team/dlee/record-controls/include/asterisk/bridging_features.h
    team/dlee/record-controls/include/asterisk/bridging_internal.h
    team/dlee/record-controls/include/asterisk/bridging_roles.h
    team/dlee/record-controls/include/asterisk/bridging_technology.h
    team/dlee/record-controls/include/asterisk/stasis_bridging.h
    team/dlee/record-controls/main/bridging.c
    team/dlee/record-controls/main/bridging_basic.c
    team/dlee/record-controls/main/bridging_channel.c
    team/dlee/record-controls/main/bridging_roles.c
    team/dlee/record-controls/main/manager_bridging.c
    team/dlee/record-controls/main/stasis_bridging.c
Modified:
    team/dlee/record-controls/   (props changed)
    team/dlee/record-controls/apps/app_agent_pool.c
    team/dlee/record-controls/apps/app_bridgewait.c
    team/dlee/record-controls/apps/app_confbridge.c
    team/dlee/record-controls/apps/app_dial.c
    team/dlee/record-controls/apps/app_dumpchan.c
    team/dlee/record-controls/apps/app_queue.c
    team/dlee/record-controls/apps/confbridge/conf_chan_announce.c
    team/dlee/record-controls/apps/confbridge/conf_chan_record.c
    team/dlee/record-controls/apps/confbridge/conf_config_parser.c
    team/dlee/record-controls/apps/confbridge/confbridge_manager.c
    team/dlee/record-controls/apps/confbridge/include/confbridge.h
    team/dlee/record-controls/bridges/bridge_builtin_features.c
    team/dlee/record-controls/bridges/bridge_builtin_interval_features.c
    team/dlee/record-controls/bridges/bridge_holding.c
    team/dlee/record-controls/bridges/bridge_native_rtp.c
    team/dlee/record-controls/bridges/bridge_simple.c
    team/dlee/record-controls/bridges/bridge_softmix.c
    team/dlee/record-controls/channels/chan_bridge_media.c
    team/dlee/record-controls/channels/chan_dahdi.c
    team/dlee/record-controls/channels/chan_iax2.c
    team/dlee/record-controls/channels/chan_mgcp.c
    team/dlee/record-controls/channels/chan_misdn.c
    team/dlee/record-controls/channels/chan_sip.c
    team/dlee/record-controls/channels/chan_skinny.c
    team/dlee/record-controls/channels/chan_unistim.c
    team/dlee/record-controls/channels/dahdi/bridge_native_dahdi.c
    team/dlee/record-controls/channels/sig_analog.c
    team/dlee/record-controls/channels/sig_pri.c
    team/dlee/record-controls/funcs/func_channel.c
    team/dlee/record-controls/include/asterisk/core_unreal.h
    team/dlee/record-controls/include/asterisk/doxygen/architecture.h
    team/dlee/record-controls/include/asterisk/features.h
    team/dlee/record-controls/include/asterisk/parking.h
    team/dlee/record-controls/main/cdr.c
    team/dlee/record-controls/main/cel.c
    team/dlee/record-controls/main/channel.c
    team/dlee/record-controls/main/cli.c
    team/dlee/record-controls/main/core_local.c
    team/dlee/record-controls/main/core_unreal.c
    team/dlee/record-controls/main/features.c
    team/dlee/record-controls/main/manager.c
    team/dlee/record-controls/main/parking.c
    team/dlee/record-controls/main/stasis_channels.c
    team/dlee/record-controls/res/parking/parking_applications.c
    team/dlee/record-controls/res/parking/parking_bridge.c
    team/dlee/record-controls/res/parking/parking_bridge_features.c
    team/dlee/record-controls/res/parking/parking_controller.c
    team/dlee/record-controls/res/parking/parking_manager.c
    team/dlee/record-controls/res/parking/res_parking.h
    team/dlee/record-controls/res/res_sip.c
    team/dlee/record-controls/res/res_sip/sip_configuration.c
    team/dlee/record-controls/res/res_sip_refer.c
    team/dlee/record-controls/res/res_sip_session.c
    team/dlee/record-controls/res/res_stasis.c
    team/dlee/record-controls/res/res_stasis_bridge_add.c
    team/dlee/record-controls/res/stasis/app.c
    team/dlee/record-controls/res/stasis/control.c
    team/dlee/record-controls/res/stasis_http/resource_bridges.c
    team/dlee/record-controls/res/stasis_http/resource_channels.c
    team/dlee/record-controls/res/stasis_http/resource_events.c
    team/dlee/record-controls/tests/test_cdr.c
    team/dlee/record-controls/tests/test_cel.c

Propchange: team/dlee/record-controls/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Jul 29 10:10:09 2013
@@ -1,1 +1,1 @@
-/trunk:1-395355
+/trunk:1-395588

Modified: team/dlee/record-controls/apps/app_agent_pool.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/record-controls/apps/app_agent_pool.c?view=diff&rev=395656&r1=395655&r2=395656
==============================================================================
--- team/dlee/record-controls/apps/app_agent_pool.c (original)
+++ team/dlee/record-controls/apps/app_agent_pool.c Mon Jul 29 10:10:09 2013
@@ -40,9 +40,10 @@
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
 #include "asterisk/channel.h"
-#include "asterisk/bridging.h"
-#include "asterisk/bridging_internal.h"
-#include "asterisk/bridging_basic.h"
+#include "asterisk/bridge.h"
+#include "asterisk/bridge_internal.h"
+#include "asterisk/bridge_basic.h"
+#include "asterisk/bridge_after.h"
 #include "asterisk/config_options.h"
 #include "asterisk/features_config.h"
 #include "asterisk/astobj2.h"
@@ -1055,7 +1056,7 @@
 
        if (!caller_bridge) {
                /* Reset agent. */
-               ast_bridge_channel_leave_bridge(bridge_channel, 
AST_BRIDGE_CHANNEL_STATE_END);
+               ast_bridge_channel_leave_bridge(bridge_channel, 
BRIDGE_CHANNEL_STATE_END);
                return;
        }
        res = ast_bridge_move(caller_bridge, bridge_channel->bridge, 
bridge_channel->chan,
@@ -1063,7 +1064,7 @@
        if (res) {
                /* Reset agent. */
                ast_bridge_destroy(caller_bridge);
-               ast_bridge_channel_leave_bridge(bridge_channel, 
AST_BRIDGE_CHANNEL_STATE_END);
+               ast_bridge_channel_leave_bridge(bridge_channel, 
BRIDGE_CHANNEL_STATE_END);
                return;
        }
        ast_bridge_channel_write_control_data(bridge_channel, 
AST_CONTROL_ANSWER, NULL, 0);
@@ -1077,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;
 
@@ -1100,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;
@@ -1159,13 +1159,13 @@
 
        if (deferred_logoff) {
                ast_debug(1, "Agent %s: Deferred logoff.\n", agent->username);
-               ast_bridge_channel_leave_bridge(bridge_channel, 
AST_BRIDGE_CHANNEL_STATE_END);
+               ast_bridge_channel_leave_bridge(bridge_channel, 
BRIDGE_CHANNEL_STATE_END);
        } else if (probation_timedout) {
                ast_debug(1, "Agent %s: Login complete.\n", agent->username);
                agent_devstate_changed(agent->username);
        } else if (ack_timedout) {
                ast_debug(1, "Agent %s: Ack call timeout.\n", agent->username);
-               ast_bridge_channel_leave_bridge(bridge_channel, 
AST_BRIDGE_CHANNEL_STATE_END);
+               ast_bridge_channel_leave_bridge(bridge_channel, 
BRIDGE_CHANNEL_STATE_END);
        } else if (wrapup_timedout) {
                ast_debug(1, "Agent %s: Wrapup timeout. Ready for new call.\n", 
agent->username);
                agent_devstate_changed(agent->username);
@@ -1175,7 +1175,7 @@
 }
 
 static void agent_after_bridge_cb(struct ast_channel *chan, void *data);
-static void agent_after_bridge_cb_failed(enum ast_after_bridge_cb_reason 
reason, void *data);
+static void agent_after_bridge_cb_failed(enum ast_bridge_after_cb_reason 
reason, void *data);
 
 /*!
  * \internal
@@ -1252,7 +1252,7 @@
        }
 
        if (swap) {
-               res = ast_after_bridge_callback_set(chan, agent_after_bridge_cb,
+               res = ast_bridge_set_after_callback(chan, agent_after_bridge_cb,
                        agent_after_bridge_cb_failed, chan);
                if (res) {
                        ast_channel_remove_bridge_role(chan, 
"holding_participant");
@@ -1270,7 +1270,7 @@
                 * agent will have some slightly different behavior in corner
                 * cases.
                 */
-               ast_bridge_channel_leave_bridge(bridge_channel, 
AST_BRIDGE_CHANNEL_STATE_END);
+               ast_bridge_channel_leave_bridge(bridge_channel, 
BRIDGE_CHANNEL_STATE_END);
                return 0;
        }
 
@@ -1402,7 +1402,7 @@
        return bridge;
 }
 
-static void bridging_init_agent_hold(void)
+static void bridge_init_agent_hold(void)
 {
        /* Setup bridge agent_hold subclass v_table. */
        bridge_agent_hold_v_table = ast_bridge_base_v_table;
@@ -1620,7 +1620,7 @@
        ao2_ref(agent, -1);
 }
 
-static void agent_after_bridge_cb_failed(enum ast_after_bridge_cb_reason 
reason, void *data)
+static void agent_after_bridge_cb_failed(enum ast_bridge_after_cb_reason 
reason, void *data)
 {
        struct ast_channel *chan = data;
        struct agent_pvt *agent;
@@ -1631,7 +1631,7 @@
        }
        ast_log(LOG_WARNING, "Agent %s: Forced logout.  Lost control of %s 
because: %s\n",
                agent->username, ast_channel_name(chan),
-               ast_after_bridge_cb_reason_string(reason));
+               ast_bridge_after_cb_reason_string(reason));
        agent_lock(agent);
        agent_logout(agent);
        ao2_ref(agent, -1);
@@ -1704,17 +1704,17 @@
        }
 
        /* Kick the agent out of the holding bridge to reset it. */
-       ast_bridge_channel_leave_bridge_nolock(logged, 
AST_BRIDGE_CHANNEL_STATE_END);
+       ast_bridge_channel_leave_bridge_nolock(logged, 
BRIDGE_CHANNEL_STATE_END);
        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;
 
        if (agent->state == AGENT_STATE_CALL_PRESENT) {
                ast_verb(3, "Agent '%s' did not respond.  Safety timeout.\n", 
agent->username);
-               ast_bridge_channel_leave_bridge(bridge_channel, 
AST_BRIDGE_CHANNEL_STATE_END);
+               ast_bridge_channel_leave_bridge(bridge_channel, 
BRIDGE_CHANNEL_STATE_END);
                caller_abort_agent(agent);
        }
 
@@ -2555,7 +2555,7 @@
        }
 
        /* Init agent holding bridge v_table. */
-       bridging_init_agent_hold();
+       bridge_init_agent_hold();
 
        /* Setup to provide Agent:agent-id device state. */
        res |= ast_devstate_prov_add("Agent", agent_pvt_devstate_get);

Modified: team/dlee/record-controls/apps/app_bridgewait.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/record-controls/apps/app_bridgewait.c?view=diff&rev=395656&r1=395655&r2=395656
==============================================================================
--- team/dlee/record-controls/apps/app_bridgewait.c (original)
+++ team/dlee/record-controls/apps/app_bridgewait.c Mon Jul 29 10:10:09 2013
@@ -45,8 +45,9 @@
 #include "asterisk/lock.h"
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
-#include "asterisk/bridging.h"
+#include "asterisk/bridge.h"
 #include "asterisk/musiconhold.h"
+#include "asterisk/astobj2.h"
 
 /*** DOCUMENTATION
        <application name="BridgeWait" language="en_US">
@@ -54,6 +55,12 @@
                        Put a call into the holding bridge.
                </synopsis>
                <syntax>
+                       <parameter name="name">
+                               <para>Name of the holding bridge to join. This 
is a handle for <literal>BridgeWait</literal>
+                               only and does not affect the actual bridges 
that are created. If not provided,
+                               the reserved name <literal>default</literal> 
will be used.
+                               </para>
+                       </parameter>
                        <parameter name="role" required="false">
                                <para>Defines the channel's purpose for 
entering the holding bridge. Values are case sensitive.
                                </para>
@@ -99,19 +106,81 @@
                </syntax>
                <description>
                        <para>This application places the incoming channel into 
a holding bridge.
-                       The channel will then wait in the holding bridge until 
some
-                       event occurs which removes it from the holding 
bridge.</para>
+                       The channel will then wait in the holding bridge until 
some event occurs
+                       which removes it from the holding bridge.</para>
+                       <note><para>This application will answer calls which 
haven't already
+                       been answered.</para></note>
                </description>
        </application>
  ***/
-/* BUGBUG Add bridge name/id parameter to specify which holding bridge to join 
(required) */
-/* BUGBUG The channel may or may not be answered with the r option. */
-/* BUGBUG You should not place an announcer into a holding bridge with 
unanswered channels. */
-
-static char *app = "BridgeWait";
-static struct ast_bridge *holding_bridge;
-
-AST_MUTEX_DEFINE_STATIC(bridgewait_lock);
+
+#define APP_NAME "BridgeWait"
+#define DEFAULT_BRIDGE_NAME "default"
+
+static struct ao2_container *wait_bridge_wrappers;
+
+struct wait_bridge_wrapper {
+       struct ast_bridge *bridge;     /*!< Bridge being wrapped by this 
wrapper */
+       char name[0];                  /*!< Name of the holding bridge wrapper 
*/
+};
+
+static void wait_bridge_wrapper_destructor(void *obj)
+{
+       struct wait_bridge_wrapper *wrapper = obj;
+       if (wrapper->bridge) {
+               ast_bridge_destroy(wrapper->bridge);
+       }
+}
+
+static struct wait_bridge_wrapper *wait_bridge_wrapper_find_by_name(const char 
*bridge_name)
+{
+       return ao2_find(wait_bridge_wrappers, bridge_name, OBJ_KEY);
+}
+
+static int wait_bridge_hash_fn(const void *obj, const int flags)
+{
+       const struct wait_bridge_wrapper *entry;
+       const char *key;
+
+       switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+       case OBJ_KEY:
+               key = obj;
+               return ast_str_hash(key);
+       case OBJ_POINTER:
+               entry = obj;
+               return ast_str_hash(entry->name);
+       default:
+               /* Hash can only work on something with a full key. */
+               ast_assert(0);
+               return 0;
+       }
+}
+
+static int wait_bridge_sort_fn(const void *obj_left, const void *obj_right, 
const int flags)
+{
+       const struct wait_bridge_wrapper *left = obj_left;
+       const struct wait_bridge_wrapper *right = obj_right;
+       const char *right_key = obj_right;
+       int cmp;
+
+       switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+       case OBJ_POINTER:
+               right_key = right->name;
+               /* Fall through */
+       case OBJ_KEY:
+               cmp = strcmp(left->name, right_key);
+               break;
+       case OBJ_PARTIAL_KEY:
+               cmp = strncmp(left->name, right_key, strlen(right_key));
+               break;
+       default:
+               /* Sort can only work on something with a full or partial key. 
*/
+               ast_assert(0);
+               cmp = 0;
+               break;
+       }
+       return cmp;
+}
 
 enum bridgewait_flags {
        MUXFLAG_MOHCLASS = (1 << 0),
@@ -132,30 +201,33 @@
        AST_APP_OPTION_ARG('S', MUXFLAG_TIMEOUT, OPT_ARG_TIMEOUT),
 });
 
+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);
+       return -1;
+}
+
 static int apply_option_timeout(struct ast_bridge_features *features, char 
*duration_arg)
 {
-       struct ast_bridge_features_limits hold_limits;
+       unsigned int duration;
 
        if (ast_strlen_zero(duration_arg)) {
-               ast_log(LOG_ERROR, "No duration value provided for the timeout 
('S') option.\n");
-               return -1;
-       }
-
-       if (ast_bridge_features_limits_construct(&hold_limits)) {
-               ast_log(LOG_ERROR, "Could not construct duration limits. Bridge 
canceled.\n");
-               return -1;
-       }
-
-       if (sscanf(duration_arg, "%u", &(hold_limits.duration)) != 1 || 
hold_limits.duration == 0) {
-               ast_log(LOG_ERROR, "Duration value provided for the timeout 
('S') option must be greater than 0\n");
-               ast_bridge_features_limits_destroy(&hold_limits);
-               return -1;
-       }
-
-       /* Limits struct holds time as milliseconds, so muliply 1000x */
-       hold_limits.duration *= 1000;
-       ast_bridge_features_set_limits(features, &hold_limits, 
AST_BRIDGE_HOOK_REMOVE_ON_PULL);
-       ast_bridge_features_limits_destroy(&hold_limits);
+               ast_log(LOG_ERROR, "Timeout option 'S': No value provided.\n");
+               return -1;
+       }
+       if (sscanf(duration_arg, "%u", &duration) != 1 || duration == 0) {
+               ast_log(LOG_ERROR, "Timeout option 'S': Invalid value provided 
'%s'.\n",
+                       duration_arg);
+               return -1;
+       }
+
+       duration *= 1000;
+       if (ast_bridge_interval_hook(features, duration, 
bridgewait_timeout_callback,
+               NULL, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
+               ast_log(LOG_ERROR, "Timeout option 'S': Could not create 
timer.\n");
+               return -1;
+       }
 
        return 0;
 }
@@ -168,6 +240,7 @@
 static int apply_option_entertainment(struct ast_channel *chan, const char 
*entertainment_arg)
 {
        char entertainment = entertainment_arg[0];
+
        switch (entertainment) {
        case 'm':
                return ast_channel_set_bridge_role_option(chan, 
"holding_participant", "idle_mode", "musiconhold");
@@ -231,6 +304,98 @@
        return 0;
 }
 
+/*!
+ * \internal
+ * \since 12.0.0
+ * \brief Allocate a new holding bridge wrapper with the given bridge name and 
bridge ID.
+ *
+ * \param bridge_name name of the bridge wrapper
+ * \param bridge the bridge being wrapped
+ *
+ * \retval Pointer to the newly allocated holding bridge wrapper
+ * \retval NULL if allocation failed. The bridge will be destroyed if this 
function fails.
+ */
+static struct wait_bridge_wrapper *wait_bridge_wrapper_alloc(const char 
*bridge_name, struct ast_bridge *bridge)
+{
+       struct wait_bridge_wrapper *bridge_wrapper;
+
+       bridge_wrapper = ao2_alloc_options(sizeof(*bridge_wrapper) + 
strlen(bridge_name) + 1,
+               wait_bridge_wrapper_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
+
+       if (!bridge_wrapper) {
+               ast_bridge_destroy(bridge);
+               return NULL;
+       }
+
+       strcpy(bridge_wrapper->name, bridge_name);
+       bridge_wrapper->bridge = bridge;
+
+       if (!ao2_link(wait_bridge_wrappers, bridge_wrapper)) {
+               ao2_cleanup(bridge_wrapper);
+               return NULL;
+       }
+
+       return bridge_wrapper;
+}
+
+static struct wait_bridge_wrapper *get_wait_bridge_wrapper(const char 
*bridge_name)
+{
+       struct wait_bridge_wrapper * wrapper;
+       struct ast_bridge *bridge = NULL;
+
+       SCOPED_AO2LOCK(lock, wait_bridge_wrappers);
+
+       if ((wrapper = wait_bridge_wrapper_find_by_name(bridge_name))) {
+               return wrapper;
+       }
+
+       bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING,
+               AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | 
AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
+               | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | 
AST_BRIDGE_FLAG_TRANSFER_PROHIBITED
+               | AST_BRIDGE_FLAG_DISSOLVE_EMPTY);
+
+       if (!bridge) {
+               return NULL;
+       }
+
+       /* The bridge reference is unconditionally passed. */
+       return wait_bridge_wrapper_alloc(bridge_name, bridge);
+}
+
+/*!
+ * \internal
+ * \since 12.0.0
+ * \brief If we are down to the last reference of a wrapper and it's still 
contained within the list, remove it from the list.
+ *
+ * \param wrapper reference to wait bridge wrapper being checked for list 
culling - will be cleared on exit
+ */
+static void wait_wrapper_removal(struct wait_bridge_wrapper *wrapper)
+{
+       if (!wrapper) {
+               return;
+       }
+
+       ao2_lock(wait_bridge_wrappers);
+       if (ao2_ref(wrapper, 0) == 2) {
+               /* Either we have the only real reference or else wrapper isn't 
in the container anyway. */
+               ao2_unlink(wait_bridge_wrappers, wrapper);
+       }
+       ao2_unlock(wait_bridge_wrappers);
+
+       ao2_cleanup(wrapper);
+}
+
+/*!
+ * \internal
+ * \since 12.0.0
+ * \brief Application callback for the bridgewait application
+ *
+ * \param chan channel running the application
+ * \param data Arguments to the application
+ *
+ * \retval 0 Ran successfully and the call didn't hang up
+ * \retval -1 Failed or the call was hung up by the time the channel exited 
the holding bridge
+ */
 static enum wait_bridge_roles validate_role(const char *role)
 {
        if (!strcmp(role, "participant")) {
@@ -244,32 +409,27 @@
 
 static int bridgewait_exec(struct ast_channel *chan, const char *data)
 {
+       char *bridge_name = DEFAULT_BRIDGE_NAME;
        struct ast_bridge_features chan_features;
        struct ast_flags flags = { 0 };
        char *parse;
+       int bridge_join_failed = 0;
        enum wait_bridge_roles role = ROLE_PARTICIPANT;
        char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
 
        AST_DECLARE_APP_ARGS(args,
+               AST_APP_ARG(name);
                AST_APP_ARG(role);
                AST_APP_ARG(options);
                AST_APP_ARG(other);             /* Any remaining unused 
arguments */
        );
 
-       ast_mutex_lock(&bridgewait_lock);
-       if (!holding_bridge) {
-               holding_bridge = 
ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING,
-                       AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | 
AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
-                               | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | 
AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
-       }
-       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;
-       }
-
        parse = ast_strdupa(data);
        AST_STANDARD_APP_ARGS(args, parse);
+
+       if (!ast_strlen_zero(args.name)) {
+               bridge_name = args.name;
+       }
 
        if (!ast_strlen_zero(args.role)) {
                role = validate_role(args.role);
@@ -281,6 +441,8 @@
 
        if (ast_bridge_features_init(&chan_features)) {
                ast_bridge_features_cleanup(&chan_features);
+               ast_log(LOG_ERROR, "'%s' failed to enter the waiting bridge - 
could not set up channel features\n",
+                       ast_channel_name(chan));
                return -1;
        }
 
@@ -288,28 +450,66 @@
                ast_app_parse_options(bridgewait_opts, &flags, opts, 
args.options);
        }
 
+       /* Answer the channel if needed */
+       if (ast_channel_state(chan) != AST_STATE_UP) {
+               ast_answer(chan);
+       }
+
        if (process_options(chan, &flags, opts, &chan_features, role)) {
                ast_bridge_features_cleanup(&chan_features);
                return -1;
        }
 
-       ast_bridge_join(holding_bridge, chan, NULL, &chan_features, NULL, 0);
+       for (;;) {
+               RAII_VAR(struct wait_bridge_wrapper *, bridge_wrapper, 
get_wait_bridge_wrapper(bridge_name), wait_wrapper_removal);
+
+               if (!bridge_wrapper) {
+                       ast_log(LOG_WARNING, "Failed to find or create waiting 
bridge '%s' for '%s'.\n", bridge_name, ast_channel_name(chan));
+                       bridge_join_failed = 1;
+                       break;
+               }
+
+               ast_verb(3, "%s is entering waiting bridge %s:%s\n", 
ast_channel_name(chan), bridge_name, bridge_wrapper->bridge->uniqueid);
+
+               if (ast_bridge_join(bridge_wrapper->bridge, chan, NULL, 
&chan_features, NULL, 0)) {
+                       /* It's possible for a holding bridge to vanish out 
from under us since we can't lock it.
+                        * Unlink the wrapper and then loop if the bridge we 
try to enter is dissolved. */
+                       ast_verb(3, "Waiting bridge '%s:%s' is no longer 
joinable. Creating new bridge and trying again.\n",
+                               bridge_name, bridge_wrapper->bridge->uniqueid);
+                       ao2_unlink(wait_bridge_wrappers, bridge_wrapper);
+                       continue;
+               }
+
+               break;
+       }
 
        ast_bridge_features_cleanup(&chan_features);
+
+       if (bridge_join_failed) {
+               return -1;
+       }
+
        return ast_check_hangup_locked(chan) ? -1 : 0;
 }
 
 static int unload_module(void)
 {
-       ao2_cleanup(holding_bridge);
-       holding_bridge = NULL;
-
-       return ast_unregister_application(app);
+       ao2_cleanup(wait_bridge_wrappers);
+
+       return ast_unregister_application(APP_NAME);
 }
 
 static int load_module(void)
 {
-       return ast_register_application_xml(app, bridgewait_exec);
+       wait_bridge_wrappers = ao2_container_alloc_hash(
+               AO2_ALLOC_OPT_LOCK_MUTEX, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT,
+               37, wait_bridge_hash_fn, wait_bridge_sort_fn, NULL);
+
+       if (!wait_bridge_wrappers) {
+               return -1;
+       }
+
+       return ast_register_application_xml(APP_NAME, bridgewait_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Place the channel into a holding 
bridge application");

Modified: team/dlee/record-controls/apps/app_confbridge.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/record-controls/apps/app_confbridge.c?view=diff&rev=395656&r1=395655&r2=395656
==============================================================================
--- team/dlee/record-controls/apps/app_confbridge.c (original)
+++ team/dlee/record-controls/apps/app_confbridge.c Mon Jul 29 10:10:09 2013
@@ -32,7 +32,7 @@
  * \addtogroup configuration_file Configuration Files
  */
 
-/*! 
+/*!
  * \page confbridge.conf confbridge.conf
  * \verbinclude confbridge.conf.sample
  */
@@ -58,7 +58,7 @@
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
 #include "asterisk/lock.h"
-#include "asterisk/bridging.h"
+#include "asterisk/bridge.h"
 #include "asterisk/musiconhold.h"
 #include "asterisk/say.h"
 #include "asterisk/audiohook.h"
@@ -68,7 +68,7 @@
 #include "asterisk/manager.h"
 #include "asterisk/test.h"
 #include "asterisk/stasis.h"
-#include "asterisk/stasis_bridging.h"
+#include "asterisk/stasis_bridges.h"
 #include "asterisk/json.h"
 
 /*** DOCUMENTATION
@@ -128,13 +128,13 @@
                </syntax>
                <description>
                        <para>---- Example 1 ----</para>
-                       <para>In this example the custom set user profile on 
this channel will automatically be used by the ConfBridge app.</para> 
+                       <para>In this example the custom set user profile on 
this channel will automatically be used by the ConfBridge app.</para>
                        <para>exten => 1,1,Answer() </para>
                        <para>exten => 
1,n,Set(CONFBRIDGE(user,announce_join_leave)=yes)</para>
                        <para>exten => 
1,n,Set(CONFBRIDGE(user,startmuted)=yes)</para>
                        <para>exten => 1,n,ConfBridge(1) </para>
                        <para>---- Example 2 ----</para>
-                       <para>This example shows how to use a predefined user 
or bridge profile in confbridge.conf as a template for a dynamic profile. Here 
we make a admin/marked user out of the default_user profile that is already 
defined in confbridge.conf.</para> 
+                       <para>This example shows how to use a predefined user 
or bridge profile in confbridge.conf as a template for a dynamic profile. Here 
we make a admin/marked user out of the default_user profile that is already 
defined in confbridge.conf.</para>
                        <para>exten => 1,1,Answer() </para>
                        <para>exten => 
1,n,Set(CONFBRIDGE(user,template)=default_user)</para>
                        <para>exten => 
1,n,Set(CONFBRIDGE(user,admin)=yes)</para>
@@ -155,7 +155,7 @@
                        </parameter>
                </syntax>
                <description>
-                       <para>This function returns a non-negative integer for 
valid conference identifiers (0 or 1 for <literal>locked</literal>) and "" for 
invalid conference identifiers.</para> 
+                       <para>This function returns a non-negative integer for 
valid conference identifiers (0 or 1 for <literal>locked</literal>) and "" for 
invalid conference identifiers.</para>
                </description>
        </function>
        <manager name="ConfbridgeList" language="en_US">
@@ -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;
 
@@ -2240,7 +2240,7 @@
                        "       Lists all currently active conference bridges 
or a specific conference bridge.\n"
                        "\n"
                        "       When a conference bridge name is provided, 
flags may be shown for users. Below\n"
-                       "       are the flags and what they represent.\n" 
+                       "       are the flags and what they represent.\n"
                        "\n"
                        "       Flags:\n"
                        "         A - The user is an admin\n"
@@ -2710,7 +2710,7 @@
                conference->name,
                conference->activeusers + conference->waitingusers,
                conference->markedusers,
-               conference->locked ? "Yes" : "No"); 
+               conference->locked ? "Yes" : "No");
                ao2_unlock(conference);
 
                ao2_ref(conference, -1);
@@ -3147,8 +3147,8 @@
  * Module loading including tests for configuration or dependencies.
  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the 
- * configuration file or other non-critical problem return 
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
  */
 static int load_module(void)

Modified: team/dlee/record-controls/apps/app_dial.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/record-controls/apps/app_dial.c?view=diff&rev=395656&r1=395655&r2=395656
==============================================================================
--- team/dlee/record-controls/apps/app_dial.c (original)
+++ team/dlee/record-controls/apps/app_dial.c Mon Jul 29 10:10:09 2013
@@ -66,7 +66,7 @@
 #include "asterisk/framehook.h"
 #include "asterisk/dial.h"
 #include "asterisk/stasis_channels.h"
-#include "asterisk/bridging.h"
+#include "asterisk/bridge_after.h"
 #include "asterisk/features_config.h"
 
 /*** DOCUMENTATION
@@ -201,7 +201,7 @@
                                        <argument name="exten" required="false" 
/>
                                        <argument name="priority" 
required="true" />
                                        <para>If the call is answered, transfer 
the calling party to
-                                       the specified 
<replaceable>priority</replaceable> and the called party to the specified 
+                                       the specified 
<replaceable>priority</replaceable> and the called party to the specified
                                        <replaceable>priority</replaceable> 
plus one.</para>
                                        <note>
                                                <para>You cannot use any 
additional action post answer options in conjunction with this option.</para>
@@ -290,7 +290,7 @@
                                        <argument name="arg" multiple="true">
                                                <para>Macro arguments</para>
                                        </argument>
-                                       <para>Execute the specified 
<replaceable>macro</replaceable> for the <emphasis>called</emphasis> channel 
+                                       <para>Execute the specified 
<replaceable>macro</replaceable> for the <emphasis>called</emphasis> channel
                                        before connecting to the calling 
channel. Arguments can be specified to the Macro
                                        using <literal>^</literal> as a 
delimiter. The macro can set the variable
                                        <variable>MACRO_RESULT</variable> to 
specify the following actions after the macro is
@@ -332,7 +332,7 @@
                                                <para>With 
<replaceable>delete</replaceable> set to <literal>1</literal>, the introduction 
will
                                                always be deleted.</para>
                                        </argument>
-                                       <para>This option is a modifier for the 
call screening/privacy mode. (See the 
+                                       <para>This option is a modifier for the 
call screening/privacy mode. (See the
                                        <literal>p</literal> and 
<literal>P</literal> options.) It specifies
                                        that no introductions are to be saved 
in the <directory>priv-callerintros</directory>
                                        directory.</para>
@@ -353,7 +353,7 @@
                                        <argument name="mode">
                                                <para>With 
<replaceable>mode</replaceable> either not specified or set to 
<literal>1</literal>,
                                                the originator hanging up will 
cause the phone to ring back immediately.</para>
-                                               <para>With 
<replaceable>mode</replaceable> set to <literal>2</literal>, when the operator 
+                                               <para>With 
<replaceable>mode</replaceable> set to <literal>2</literal>, when the operator
                                                flashes the trunk, it will ring 
their phone back.</para>
                                        </argument>
                                        <para>Enables <emphasis>operator 
services</emphasis> mode.  This option only
@@ -1071,7 +1071,7 @@
                        /* If we are calling a single channel, and not 
providing ringback or music, */
                        /* then, make them compatible for in-band tone purpose 
*/
                        if (ast_channel_make_compatible(outgoing->chan, in) < 
0) {
-                               /* If these channels can not be made 
compatible, 
+                               /* If these channels can not be made compatible,
                                 * there is no point in continuing.  The bridge
                                 * will just fail if it gets that far.
                                 */
@@ -1765,7 +1765,7 @@
 
                /*! \page DialPrivacy Dial Privacy scripts
                 * \par priv-callee-options script:
-                * \li Dial 1 if you wish this caller to reach you directly in 
the future, 
+                * \li Dial 1 if you wish this caller to reach you directly in 
the future,
                 *      and immediately connect to their incoming call.
                 * \li Dial 2 if you wish to send this caller to voicemail now 
and forevermore.
                 * \li Dial 3 to send this caller to the torture menus, now and 
forevermore.
@@ -1891,7 +1891,7 @@
        } else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && 
strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
                ast_verb(3, "CallerID blank; N option set; Screening should 
happen; dbval is %d\n", pa->privdb_val);
        }
-       
+
        if (pa->privdb_val == AST_PRIVACY_DENY) {
                ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. 
Dial reports unavailable\n");
                ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
@@ -2021,14 +2021,14 @@
                ast_channel_lock(chan);
                context = ast_strdupa(ast_channel_context(chan));
                ast_channel_unlock(chan);
-               ast_after_bridge_set_h(peer, context);
+               ast_bridge_set_after_h(peer, context);
        } else if (ast_test_flag64(opts, OPT_CALLEE_GO_ON)) {
                ast_channel_lock(chan);
                context = ast_strdupa(ast_channel_context(chan));
                extension = ast_strdupa(ast_channel_exten(chan));
                priority = ast_channel_priority(chan);
                ast_channel_unlock(chan);
-               ast_after_bridge_set_go_on(peer, context, extension, priority,
+               ast_bridge_set_after_go_on(peer, context, extension, priority,
                        opt_args[OPT_ARG_CALLEE_GO_ON]);
        }
 }
@@ -2444,7 +2444,7 @@
                        /* We are on the only destination. */
                        ast_rtp_instance_early_bridge_make_compatible(tc, chan);
                }
-               
+
                /* Inherit specially named variables from parent channel */
                ast_channel_inherit_variables(chan, tc);
                ast_channel_datastore_inherit(chan, tc);
@@ -2698,7 +2698,7 @@
                /* If appropriate, log that we have a destination channel and 
set the answer time */
                if (ast_channel_name(peer))
                        pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", 
ast_channel_name(peer));
-               
+
                ast_channel_lock(peer);
                number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
                if (ast_strlen_zero(number)) {
@@ -2967,7 +2967,7 @@
                                ast_channel_hangupcause_set(chan, 
ast_channel_hangupcause(peer));
                        }
                        setup_peer_after_bridge_goto(chan, peer, &opts, 
opt_args);
-                       if (ast_after_bridge_goto_setup(peer)
+                       if (ast_bridge_setup_after_goto(peer)
                                || ast_pbx_start(peer)) {
                                ast_autoservice_chan_hangup_peer(chan, peer);
                        }
@@ -2997,7 +2997,7 @@
                        config.end_bridge_callback = end_bridge_callback;
                        config.end_bridge_callback_data = chan;
                        config.end_bridge_callback_data_fixup = 
end_bridge_callback_data_fixup;
-                       
+
                        if (moh) {
                                moh = 0;
                                ast_moh_stop(chan);

Modified: team/dlee/record-controls/apps/app_dumpchan.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/record-controls/apps/app_dumpchan.c?view=diff&rev=395656&r1=395655&r2=395656
==============================================================================
--- team/dlee/record-controls/apps/app_dumpchan.c (original)
+++ team/dlee/record-controls/apps/app_dumpchan.c Mon Jul 29 10:10:09 2013
@@ -41,7 +41,7 @@
 #include "asterisk/channel.h"
 #include "asterisk/app.h"
 #include "asterisk/translate.h"
-#include "asterisk/bridging.h"
+#include "asterisk/bridge.h"
 
 /*** DOCUMENTATION
        <application name="DumpChan" language="en_US">
@@ -139,10 +139,10 @@
                S_OR(ast_channel_dialed(c)->number.str, "(N/A)"),
                S_COR(ast_channel_redirecting(c)->from.number.valid, 
ast_channel_redirecting(c)->from.number.str, "(N/A)"),
                ast_channel_parkinglot(c),
-               ast_channel_language(c),        
+               ast_channel_language(c),
                ast_state2str(ast_channel_state(c)),
                ast_channel_state(c),
-               ast_channel_rings(c), 
+               ast_channel_rings(c),
                ast_getformatname_multiple(nf, sizeof(nf), 
ast_channel_nativeformats(c)),
                ast_getformatname(ast_channel_writeformat(c)),
                ast_getformatname(ast_channel_readformat(c)),

Modified: team/dlee/record-controls/apps/app_queue.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/record-controls/apps/app_queue.c?view=diff&rev=395656&r1=395655&r2=395656
==============================================================================
--- team/dlee/record-controls/apps/app_queue.c (original)
+++ team/dlee/record-controls/apps/app_queue.c Mon Jul 29 10:10:09 2013
@@ -108,7 +108,7 @@
 #include "asterisk/dial.h"
 #include "asterisk/stasis_channels.h"
 #include "asterisk/stasis_message_router.h"
-#include "asterisk/bridging.h"
+#include "asterisk/bridge_after.h"
 
 /* Define, to debug reference counts on queues, without debugging reference 
counts on queue members */
 /* #define REF_DEBUG_ONLY_QUEUES */
@@ -5293,7 +5293,7 @@
                extension = ast_strdupa(ast_channel_exten(chan));
                priority = ast_channel_priority(chan);
                ast_channel_unlock(chan);
-               ast_after_bridge_set_go_on(peer, context, extension, priority,
+               ast_bridge_set_after_go_on(peer, context, extension, priority,
                        opt_args[OPT_ARG_CALLEE_GO_ON]);
        }
 }

Modified: team/dlee/record-controls/apps/confbridge/conf_chan_announce.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/record-controls/apps/confbridge/conf_chan_announce.c?view=diff&rev=395656&r1=395655&r2=395656
==============================================================================
--- team/dlee/record-controls/apps/confbridge/conf_chan_announce.c (original)
+++ team/dlee/record-controls/apps/confbridge/conf_chan_announce.c Mon Jul 29 
10:10:09 2013
@@ -32,7 +32,7 @@
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/channel.h"
-#include "asterisk/bridging.h"
+#include "asterisk/bridge.h"
 #include "asterisk/core_unreal.h"
 #include "include/confbridge.h"
 


[... 5091 lines stripped ...]

--
_____________________________________________________________________
-- 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