summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/stasis_app.h30
-rw-r--r--res/ari/resource_bridges.c12
-rw-r--r--res/res_stasis.c68
-rw-r--r--res/stasis/stasis_bridge.c2
4 files changed, 110 insertions, 2 deletions
diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h
index e06e68ed2..5a7593d67 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 93ecd14b7..45fa09d13 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 3480c9e23..0ef3d6e40 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 be7836d35..93542812f 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,