return 0;
}
+/*!
+ * \internal
+ * \brief ast_bridge base push_peek method.
+ * \since 13.2.0
+ *
+ * \param self Bridge to operate upon.
+ * \param bridge_channel Bridge channel to push.
+ * \param swap Bridge channel to swap places with if not NULL.
+ *
+ * \note On entry, self is already locked.
+ * \note Stub because of nothing to do.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+static int bridge_base_push_peek(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
+{
+ return 0;
+}
+
struct ast_bridge_methods ast_bridge_base_v_table = {
.name = "base",
.destroy = bridge_base_destroy,
.pull = bridge_base_pull,
.notify_masquerade = bridge_base_notify_masquerade,
.get_merge_priority = bridge_base_get_merge_priority,
+ .push_peek = bridge_base_push_peek,
};
struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
bridge_channel->features = features;
bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP);
+ /* allow subclass to peek at upcoming push operation */
+ if (bridge->v_table->push_peek && !res) {
+ struct ast_bridge_channel *bcswap = NULL;
+
+ ast_bridge_lock(bridge);
+ if (bridge_channel->swap) {
+ bcswap = bridge_find_channel(bridge, bridge_channel->swap);
+ }
+ res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
+ ast_bridge_unlock(bridge);
+ }
+
if (!res) {
res = bridge_channel_internal_join(bridge_channel);
}
(flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_DEPARTABLE;
bridge_channel->callid = ast_read_threadstorage_callid();
+ /* allow subclass to peek at swap channel before it can hangup */
+ if (bridge->v_table->push_peek && !res) {
+ struct ast_bridge_channel *bcswap = NULL;
+
+ ast_bridge_lock(bridge);
+ if (bridge_channel->swap) {
+ bcswap = bridge_find_channel(bridge, bridge_channel->swap);
+ }
+ res = bridge->v_table->push_peek(bridge, bridge_channel, bcswap);
+ ast_bridge_unlock(bridge);
+ }
+
/* Actually create the thread that will handle the channel */
if (!res) {
if ((flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_INDEPENDENT) {
ast_channel_unlock(bridge_channel->chan);
}
+/*!
+ * \internal
+ * \brief Peek at channel before it is pushed into bridge
+ * \since 13.2.0
+ *
+ * \param self Bridge to operate upon.
+ * \param bridge_channel Bridge channel to push.
+ * \param swap Bridge channel to swap places with if not NULL.
+ *
+ * \note On entry, self is already locked.
+ *
+ * \retval 0 on success.
+ * \retval -1 on failure. The channel should not be pushed.
+ */
+static int bridge_stasis_push_peek(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
+{
+ struct stasis_app_control *swap_control;
+ struct ast_channel_snapshot *to_be_replaced;
+
+ if (!swap) {
+ goto done;
+ }
+
+ swap_control = stasis_app_control_find_by_channel(swap->chan);
+ if (!swap_control) {
+ ast_log(LOG_ERROR,"Failed to find stasis app control for swapped channel %s\n", ast_channel_name(swap->chan));
+ return -1;
+ }
+ to_be_replaced = ast_channel_snapshot_get_latest(ast_channel_uniqueid(swap->chan));
+
+ ast_debug(3, "Copying stasis app name %s from %s to %s\n", app_name(control_app(swap_control)),
+ ast_channel_name(swap->chan), ast_channel_name(bridge_channel->chan));
+
+ ast_channel_lock(bridge_channel->chan);
+
+ /* copy the app name from the swap channel */
+ app_set_replace_channel_app(bridge_channel->chan, app_name(control_app(swap_control)));
+
+ /* set the replace channel snapshot */
+ app_set_replace_channel_snapshot(bridge_channel->chan, to_be_replaced);
+
+ ast_channel_unlock(bridge_channel->chan);
+
+ ao2_ref(swap_control, -1);
+ ao2_cleanup(to_be_replaced);
+
+done:
+ return ast_bridge_base_v_table.push_peek(self, bridge_channel, swap);
+}
+
/*!
* \internal
* \brief Push this channel into the Stasis bridge.
{
struct stasis_app_control *control = stasis_app_control_find_by_channel(bridge_channel->chan);
- if (swap) {
- struct ast_channel_snapshot *to_be_replaced = ast_channel_snapshot_get_latest(ast_channel_uniqueid(swap->chan));
- struct stasis_app_control *swap_control = stasis_app_control_find_by_channel(swap->chan);
-
- /* set the replace channel snapshot */
- ast_channel_lock(bridge_channel->chan);
- app_set_replace_channel_snapshot(bridge_channel->chan, to_be_replaced);
-
- /* copy the app name from the swap channel */
- if (swap_control) {
- ast_debug(3, "Copying stasis app name %s from %s to %s\n",
- app_name(control_app(swap_control)),
- ast_channel_name(swap->chan),
- ast_channel_name(bridge_channel->chan));
- app_set_replace_channel_app(bridge_channel->chan, app_name(control_app(swap_control)));
- }
- ast_channel_unlock(bridge_channel->chan);
- ao2_cleanup(to_be_replaced);
- ao2_cleanup(swap_control);
- }
-
if (!control && !stasis_app_channel_is_internal(bridge_channel->chan)) {
/* channel not in Stasis(), get it there */
/* Attach after-bridge callback and pass ownership of swap_app to it */
bridge_stasis_v_table.name = "stasis";
bridge_stasis_v_table.push = bridge_stasis_push;
bridge_stasis_v_table.pull = bridge_stasis_pull;
+ bridge_stasis_v_table.push_peek = bridge_stasis_push_peek;
}