From: Kinsey Moore Date: Mon, 11 Aug 2014 18:38:15 +0000 (+0000) Subject: Stasis: Allow internal channels directly into bridges X-Git-Tag: 14.0.0-beta1~1764 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f735288b0d4cb6c0347873174a19e40c6e8a277;p=thirdparty%2Fasterisk.git 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 --- diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h index e06e68ed26..5a7593d677 100644 --- a/include/asterisk/stasis_app.h +++ b/include/asterisk/stasis_app.h @@ -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 */ diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c index 93ecd14b78..45fa09d13d 100644 --- a/res/ari/resource_bridges.c +++ b/res/ari/resource_bridges.c @@ -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; } /*! diff --git a/res/res_stasis.c b/res/res_stasis.c index 3480c9e237..0ef3d6e40f 100644 --- a/res/res_stasis.c +++ b/res/res_stasis.c @@ -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) { diff --git a/res/stasis/stasis_bridge.c b/res/stasis/stasis_bridge.c index be7836d35c..93542812f3 100644 --- a/res/stasis/stasis_bridge.c +++ b/res/stasis/stasis_bridge.c @@ -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,