Stasis: Allow internal channels directly into bridges

The patch to catch channels being shoehorned into Stasis() via external
mechanisms also happens to catch Announcer and Recorder channels
because they aren't known to be stasis-controlled channels in the usual
sense. This marks those channels as Stasis()-internal channels and
allows them directly into bridges.

Review: https://reviewboard.asterisk.org/r/3903/
........

Merged revisions 420795 from http://svn.asterisk.org/svn/asterisk/branches/12
........

Merged revisions 420796 from http://svn.asterisk.org/svn/asterisk/branches/13


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@420797 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kinsey Moore
2014-08-11 18:38:15 +00:00
parent db0a97f8ce
commit 6f735288b0
4 changed files with 110 additions and 2 deletions

View File

@@ -821,6 +821,36 @@ void stasis_app_channel_set_stasis_end_published(struct ast_channel *chan);
*/
int stasis_app_channel_is_stasis_end_published(struct ast_channel *chan);
/*!
* \brief Is this channel internal to Stasis?
*
* \param chan The channel to check.
*
* \retval 0 No
* \retval 1 Yes
*/
int stasis_app_channel_is_internal(struct ast_channel *chan);
/*!
* \brief Mark this unreal channel and it's other half as being internal to Stasis.
*
* \param chan The channel to mark.
*
* \retval zero Success
* \retval non-zero Failure
*/
int stasis_app_channel_unreal_set_internal(struct ast_channel *chan);
/*!
* \brief Mark this channel as being internal to Stasis.
*
* \param chan The channel to mark.
*
* \retval zero Success
* \retval non-zero Failure
*/
int stasis_app_channel_set_internal(struct ast_channel *chan);
/*! @} */
#endif /* _ASTERISK_STASIS_APP_H */

View File

@@ -305,6 +305,7 @@ static void *bridge_channel_control_thread(void *data)
static struct ast_channel *prepare_bridge_media_channel(const char *type)
{
RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
struct ast_channel *chan;
cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
@@ -313,7 +314,16 @@ static struct ast_channel *prepare_bridge_media_channel(const char *type)
ast_format_cap_append(cap, ast_format_slin, 0);
return ast_request(type, cap, NULL, NULL, "ARI", NULL);
chan = ast_request(type, cap, NULL, NULL, "ARI", NULL);
if (!chan) {
return NULL;
}
if (stasis_app_channel_unreal_set_internal(chan)) {
ast_channel_cleanup(chan);
return NULL;
}
return chan;
}
/*!

View File

@@ -1901,6 +1901,74 @@ static void check_for_stasis_end(void *data, struct stasis_subscription *sub,
remove_masquerade_store_by_name(snapshot->name);
}
static const struct ast_datastore_info stasis_internal_channel_info = {
.type = "stasis-internal-channel",
};
static int set_internal_datastore(struct ast_channel *chan)
{
struct ast_datastore *datastore;
datastore = ast_channel_datastore_find(chan, &stasis_internal_channel_info, NULL);
if (!datastore) {
datastore = ast_datastore_alloc(&stasis_internal_channel_info, NULL);
if (!datastore) {
return -1;
}
ast_channel_datastore_add(chan, datastore);
}
return 0;
}
int stasis_app_channel_unreal_set_internal(struct ast_channel *chan)
{
struct ast_channel *outchan = NULL, *outowner = NULL;
int res = 0;
struct ast_unreal_pvt *unreal_pvt = ast_channel_tech_pvt(chan);
ao2_ref(unreal_pvt, +1);
ast_unreal_lock_all(unreal_pvt, &outowner, &outchan);
if (outowner) {
res |= set_internal_datastore(outowner);
ast_channel_unlock(outowner);
ast_channel_unref(outowner);
}
if (outchan) {
res |= set_internal_datastore(outchan);
ast_channel_unlock(outchan);
ast_channel_unref(outchan);
}
ao2_unlock(unreal_pvt);
ao2_ref(unreal_pvt, -1);
return 0;
}
int stasis_app_channel_set_internal(struct ast_channel *chan)
{
int res;
ast_channel_lock(chan);
res = set_internal_datastore(chan);
ast_channel_unlock(chan);
return res;
}
int stasis_app_channel_is_internal(struct ast_channel *chan)
{
struct ast_datastore *datastore;
int res = 0;
ast_channel_lock(chan);
datastore = ast_channel_datastore_find(chan, &stasis_internal_channel_info, NULL);
if (datastore) {
res = 1;
}
ast_channel_unlock(chan);
return res;
}
static int load_module(void)
{
if (STASIS_MESSAGE_TYPE_INIT(ast_stasis_end_message_type) != 0) {

View File

@@ -117,7 +117,7 @@ static int bridge_stasis_push(struct ast_bridge *self, struct ast_bridge_channel
{
struct stasis_app_control *control = stasis_app_control_find_by_channel(bridge_channel->chan);
if (!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 */
if (ast_bridge_set_after_callback(bridge_channel->chan,