Merge "res_stasis: Handle re-enter stasis bridge with swap channel."

changes/88/2688/1
zuul 9 years ago committed by Gerrit Code Review
commit ac50fdecdb

@ -903,11 +903,8 @@ static void bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason,
ast_bridge_after_cb_reason_string(reason)); ast_bridge_after_cb_reason_string(reason));
} }
int control_add_channel_to_bridge( int control_swap_channel_in_bridge(struct stasis_app_control *control, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap)
struct stasis_app_control *control,
struct ast_channel *chan, void *data)
{ {
struct ast_bridge *bridge = data;
int res; int res;
if (!control || !bridge) { if (!control || !bridge) {
@ -960,7 +957,7 @@ int control_add_channel_to_bridge(
res = ast_bridge_impart(bridge, res = ast_bridge_impart(bridge,
chan, chan,
NULL, /* swap channel */ swap,
NULL, /* features */ NULL, /* features */
AST_BRIDGE_IMPART_CHAN_DEPARTABLE); AST_BRIDGE_IMPART_CHAN_DEPARTABLE);
if (res != 0) { if (res != 0) {
@ -976,6 +973,11 @@ int control_add_channel_to_bridge(
return 0; return 0;
} }
int control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
{
return control_swap_channel_in_bridge(control, data, chan, NULL);
}
int stasis_app_control_add_channel_to_bridge( int stasis_app_control_add_channel_to_bridge(
struct stasis_app_control *control, struct ast_bridge *bridge) struct stasis_app_control *control, struct ast_bridge *bridge)
{ {

@ -111,12 +111,20 @@ struct stasis_app *control_app(struct stasis_app_control *control);
* \brief Command callback for adding a channel to a bridge * \brief Command callback for adding a channel to a bridge
* *
* \param control The control for chan * \param control The control for chan
* \param channel The channel on which commands should be executed * \param chan The channel on which commands should be executed
* \param bridge Data to be passed to the callback * \param data Bridge to be passed to the callback
*/
int control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data);
/*!
* \brief Command for swapping a channel in a bridge
*
* \param control The control for chan
* \param chan The channel on which commands should be executed
* \param bridge Bridge to be passed to the callback
* \param swap Channel to swap with when joining the bridge
*/ */
int control_add_channel_to_bridge( int control_swap_channel_in_bridge(struct stasis_app_control *control, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap);
struct stasis_app_control *control,
struct ast_channel *chan, void *obj);
/*! /*!
* \brief Stop playing silence to a channel right now. * \brief Stop playing silence to a channel right now.

@ -76,24 +76,54 @@ static void bridge_stasis_run_cb(struct ast_channel *chan, void *data)
pbx_exec(chan, app_stasis, app_name); pbx_exec(chan, app_stasis, app_name);
} }
static int add_channel_to_bridge( struct defer_bridge_add_obj {
/*! Bridge to join (has ref) */
struct ast_bridge *bridge;
/*!
* \brief Channel to swap with in the bridge. (has ref)
*
* \note NULL if not swapping with a channel.
*/
struct ast_channel *swap;
};
static void defer_bridge_add_dtor(void *obj)
{
struct defer_bridge_add_obj *defer = obj;
ao2_cleanup(defer->bridge);
ast_channel_cleanup(defer->swap);
}
static int defer_bridge_add(
struct stasis_app_control *control, struct stasis_app_control *control,
struct ast_channel *chan, void *obj) struct ast_channel *chan, void *obj)
{ {
struct ast_bridge *bridge = obj; struct defer_bridge_add_obj *defer = obj;
int res;
res = control_add_channel_to_bridge(control, return control_swap_channel_in_bridge(control, defer->bridge, chan, defer->swap);
chan, bridge);
return res;
} }
static void bridge_stasis_queue_join_action(struct ast_bridge *self, static void bridge_stasis_queue_join_action(struct ast_bridge *self,
struct ast_bridge_channel *bridge_channel) struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
{ {
struct defer_bridge_add_obj *defer;
defer = ao2_alloc_options(sizeof(*defer), defer_bridge_add_dtor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!defer) {
return;
}
ao2_ref(self, +1);
defer->bridge = self;
if (swap) {
ast_channel_ref(swap->chan);
defer->swap = swap->chan;
}
ast_channel_lock(bridge_channel->chan); ast_channel_lock(bridge_channel->chan);
command_prestart_queue_command(bridge_channel->chan, add_channel_to_bridge, command_prestart_queue_command(bridge_channel->chan, defer_bridge_add,
ao2_bump(self), __ao2_cleanup); defer, __ao2_cleanup);
ast_channel_unlock(bridge_channel->chan); ast_channel_unlock(bridge_channel->chan);
} }
@ -179,11 +209,7 @@ static int bridge_stasis_push(struct ast_bridge *self, struct ast_bridge_channel
return -1; return -1;
} }
bridge_stasis_queue_join_action(self, bridge_channel); bridge_stasis_queue_join_action(self, bridge_channel, swap);
if (swap) {
/* nudge the swap channel out of the bridge */
ast_bridge_channel_leave_bridge(swap, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, 0);
}
/* Return -1 so the push fails and the after-bridge callback gets called /* Return -1 so the push fails and the after-bridge callback gets called
* This keeps the bridging framework from putting the channel into the bridge * This keeps the bridging framework from putting the channel into the bridge

Loading…
Cancel
Save