mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-15 14:28:24 +00:00
Merge "res_stasis: Handle re-enter stasis bridge with swap channel."
This commit is contained in:
@@ -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(
|
int control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data);
|
||||||
struct stasis_app_control *control,
|
|
||||||
struct ast_channel *chan, void *obj);
|
/*!
|
||||||
|
* \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_swap_channel_in_bridge(struct stasis_app_control *control, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \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
|
||||||
|
|||||||
Reference in New Issue
Block a user