diff options
Diffstat (limited to 'res/res_stasis.c')
-rw-r--r-- | res/res_stasis.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/res/res_stasis.c b/res/res_stasis.c index d9542cd21..0184d209c 100644 --- a/res/res_stasis.c +++ b/res/res_stasis.c @@ -61,6 +61,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/stasis_app_impl.h" #include "asterisk/stasis_channels.h" #include "asterisk/stasis_bridges.h" +#include "asterisk/stasis_endpoints.h" #include "asterisk/stasis_message_router.h" #include "asterisk/strings.h" #include "stasis/app.h" @@ -1310,6 +1311,89 @@ enum stasis_app_subscribe_res stasis_app_unsubscribe(const char *app_name, json, app_unsubscribe); } +enum stasis_app_user_event_res stasis_app_user_event(const char *app_name, + const char *event_name, + const char **source_uris, int sources_count, + struct ast_json *json_variables) +{ + RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup); + RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + RAII_VAR(struct ast_multi_object_blob *, multi, NULL, ao2_cleanup); + RAII_VAR(void *, obj, NULL, ao2_cleanup); + RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + enum stasis_app_subscribe_res res = STASIS_APP_USER_INTERNAL_ERROR; + struct ast_json *json_value; + int have_channel = 0; + int i; + + if (!app) { + ast_log(LOG_WARNING, "App %s not found\n", app_name); + return STASIS_APP_USER_APP_NOT_FOUND; + } + + blob = json_variables; + if (!blob) { + blob = ast_json_pack("{}"); + } + json_value = ast_json_string_create(event_name); + if (!json_value) { + ast_log(LOG_ERROR, "unable to create json string\n"); + return res; + } + if (ast_json_object_set(blob, "eventname", json_value)) { + ast_log(LOG_ERROR, "unable to set eventname to blob\n"); + return res; + } + + multi = ast_multi_object_blob_create(blob); + + for (i = 0; i < sources_count; ++i) { + const char *uri = source_uris[i]; + void *snapshot=NULL; + enum stasis_user_multi_object_snapshot_type type; + + if (ast_begins_with(uri, "channel:")) { + type = STASIS_UMOS_CHANNEL; + snapshot = ast_channel_snapshot_get_latest(uri + 8); + have_channel = 1; + } else if (ast_begins_with(uri, "bridge:")) { + type = STASIS_UMOS_BRIDGE; + snapshot = ast_bridge_snapshot_get_latest(uri + 7); + } else if (ast_begins_with(uri, "endpoint:")) { + type = STASIS_UMOS_ENDPOINT; + snapshot = ast_endpoint_latest_snapshot(uri + 9, NULL); + } else { + ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri); + return STASIS_APP_USER_EVENT_SOURCE_BAD_SCHEME; + } + if (!snapshot) { + ast_log(LOG_ERROR, "Unable to get snapshot for %s\n", uri); + return STASIS_APP_USER_EVENT_SOURCE_NOT_FOUND; + } + ast_multi_object_blob_add(multi, type, snapshot); + } + + message = stasis_message_create(ast_multi_user_event_type(), multi); + if (!message) { + ast_log(LOG_ERROR, "Unable to create stasis user event message\n"); + return res; + } + + /* + * Publishing to two different topics is normally to be avoided -- except + * in this case both are final destinations with no forwards (only listeners). + * The message has to be delivered to the application topic for ARI, but a + * copy is also delivered directly to the manager for AMI if there is a channel. + */ + stasis_publish(ast_app_get_topic(app), message); + + if (have_channel) { + stasis_publish(ast_manager_get_topic(), message); + } + + return STASIS_APP_USER_OK; +} + void stasis_app_ref(void) { ast_module_ref(ast_module_info->self); |