Asterisk - The Open Source Telephony Project GIT-master-20e40a9
Loading...
Searching...
No Matches
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
app.c File Reference

Stasis application support. More...

#include "asterisk.h"
#include "app.h"
#include "control.h"
#include "messaging.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/stasis_app.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stasis_message_router.h"
Include dependency graph for res/stasis/app.c:

Go to the source code of this file.

Data Structures

struct  app_forwards
 
struct  stasis_app
 

Macros

#define BRIDGE_ALL   "__AST_BRIDGE_ALL_TOPIC"
 
#define CHANNEL_ALL   "__AST_CHANNEL_ALL_TOPIC"
 
#define ENDPOINT_ALL   "__AST_ENDPOINT_ALL_TOPIC"
 

Typedefs

typedef struct ast_json *(* channel_snapshot_monitor) (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)
 Typedef for callbacks that get called on channel snapshot updates.
 

Enumerations

enum  forward_type { FORWARD_CHANNEL , FORWARD_BRIDGE , FORWARD_ENDPOINT }
 

Functions

struct stasis_appapp_create (const char *name, stasis_app_cb handler, void *data, enum stasis_app_subscription_model subscription_model)
 Create a res_stasis application.
 
void app_deactivate (struct stasis_app *app)
 Deactivates an application.
 
static void app_dtor (void *obj)
 
static int app_event_filter_matched (struct ast_json *array, struct ast_json *event, int empty)
 
static int app_event_filter_set (struct stasis_app *app, struct ast_json **member, struct ast_json *filter, const char *filter_type)
 
static int app_events_allowed_set (struct stasis_app *app, struct ast_json *filter)
 
static int app_events_disallowed_set (struct stasis_app *app, struct ast_json *filter)
 
int app_is_active (struct stasis_app *app)
 Checks whether an app is active.
 
int app_is_finished (struct stasis_app *app)
 Checks whether a deactivated app has no channels.
 
int app_is_subscribed_bridge_id (struct stasis_app *app, const char *bridge_id)
 Test if an app is subscribed to a bridge.
 
int app_is_subscribed_channel_id (struct stasis_app *app, const char *channel_id)
 Test if an app is subscribed to a channel.
 
int app_is_subscribed_endpoint_id (struct stasis_app *app, const char *endpoint_id)
 Test if an app is subscribed to a endpoint.
 
void app_send (struct stasis_app *app, struct ast_json *message)
 Send a message to an application.
 
void app_shutdown (struct stasis_app *app)
 Tears down an application.
 
int app_subscribe_bridge (struct stasis_app *app, struct ast_bridge *bridge)
 Add a bridge subscription to an existing channel subscription.
 
int app_subscribe_channel (struct stasis_app *app, struct ast_channel *chan)
 Subscribes an application to a channel.
 
int app_subscribe_endpoint (struct stasis_app *app, struct ast_endpoint *endpoint)
 Subscribes an application to a endpoint.
 
struct ast_jsonapp_to_json (const struct stasis_app *app)
 Create a JSON representation of a stasis_app.
 
int app_unsubscribe_bridge (struct stasis_app *app, struct ast_bridge *bridge)
 Cancel the bridge subscription for an application.
 
int app_unsubscribe_bridge_id (struct stasis_app *app, const char *bridge_id)
 Cancel the subscription an app has for a bridge.
 
int app_unsubscribe_channel (struct stasis_app *app, struct ast_channel *chan)
 Cancel the subscription an app has for a channel.
 
int app_unsubscribe_channel_id (struct stasis_app *app, const char *channel_id)
 Cancel the subscription an app has for a channel.
 
int app_unsubscribe_endpoint_id (struct stasis_app *app, const char *endpoint_id)
 Cancel the subscription an app has for a endpoint.
 
void app_update (struct stasis_app *app, stasis_app_cb handler, void *data)
 Update the handler and data for a res_stasis application.
 
struct stasis_topicast_app_get_topic (struct stasis_app *app)
 Returns the stasis topic for an app.
 
static int bridge_app_subscribed (struct stasis_app *app, const char *uniqueid)
 Helper function for determining if the application is subscribed to a given entity.
 
static int bridge_app_subscribed_involved (struct stasis_app *app, struct ast_bridge_snapshot *snapshot)
 Callback function for checking if channels in a bridge are subscribed to.
 
static void bridge_attended_transfer_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void bridge_blind_transfer_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void * bridge_find (const struct stasis_app *app, const char *id)
 
static void bridge_merge_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void bridge_subscription_change_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void call_forwarded_handler (struct stasis_app *app, struct stasis_message *message)
 
static struct ast_jsonchannel_callerid (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)
 
static struct ast_jsonchannel_connected_line (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)
 
static struct ast_jsonchannel_created_event (struct ast_channel_snapshot *snapshot, const struct timeval *tv)
 
static struct ast_jsonchannel_destroyed_event (struct ast_channel_snapshot *snapshot, const struct timeval *tv)
 
static struct ast_jsonchannel_dialplan (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)
 
static void * channel_find (const struct stasis_app *app, const char *id)
 
static struct ast_jsonchannel_state (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)
 Handle channel state changes.
 
static struct ast_jsonchannel_state_change_event (struct ast_channel_snapshot *snapshot, const struct timeval *tv)
 
static void * endpoint_find (const struct stasis_app *app, const char *id)
 
static void endpoint_state_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static struct app_forwardsforwards_create (struct stasis_app *app, const char *id)
 
static struct app_forwardsforwards_create_bridge (struct stasis_app *app, struct ast_bridge *bridge)
 
static struct app_forwardsforwards_create_channel (struct stasis_app *app, struct ast_channel *chan)
 
static struct app_forwardsforwards_create_endpoint (struct stasis_app *app, struct ast_endpoint *endpoint)
 
static void forwards_dtor (void *obj)
 
static int forwards_filter_by_type (void *obj, void *arg, int flags)
 
static int forwards_sort (const void *obj_left, const void *obj_right, int flags)
 
static void forwards_unsubscribe (struct app_forwards *forwards)
 
static int message_received_handler (const char *endpoint_id, struct ast_json *json_msg, void *pvt)
 
static struct ast_jsonsimple_bridge_event (const char *type, struct ast_bridge_snapshot *snapshot, const struct timeval *tv)
 
static struct ast_jsonsimple_channel_event (const char *type, struct ast_channel_snapshot *snapshot, const struct timeval *tv)
 
static struct ast_jsonsimple_endpoint_event (const char *type, struct ast_endpoint_snapshot *snapshot, const struct timeval *tv)
 
int stasis_app_event_allowed (const char *app_name, struct ast_json *event)
 Check if the given event should be filtered.
 
int stasis_app_event_filter_set (struct stasis_app *app, struct ast_json *filter)
 Set the application's event type filter.
 
struct ast_jsonstasis_app_event_filter_to_json (struct stasis_app *app, struct ast_json *json)
 Convert and add the app's event type filter(s) to the given json object.
 
int stasis_app_get_debug (struct stasis_app *app)
 Get debug status of an application.
 
int stasis_app_get_debug_by_name (const char *app_name)
 Get debug status of an application.
 
const char * stasis_app_name (const struct stasis_app *app)
 Retrieve an application's name.
 
void stasis_app_register_event_sources (void)
 Register core event sources.
 
void stasis_app_set_debug (struct stasis_app *app, int debug)
 Enable/disable request/response and event logging on an application.
 
void stasis_app_set_debug_by_name (const char *app_name, int debug)
 Enable/disable request/response and event logging on an application.
 
void stasis_app_set_global_debug (int debug)
 Enable/disable request/response and event logging on all applications.
 
void stasis_app_to_cli (const struct stasis_app *app, struct ast_cli_args *a)
 Dump properties of a stasis_app to the CLI.
 
void stasis_app_unregister_event_sources (void)
 Unregister core event sources.
 
static void sub_bridge_update_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void sub_channel_update_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void sub_default_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void sub_endpoint_update_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void sub_subscription_change_handler (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static int subscribe_bridge (struct stasis_app *app, void *obj)
 
static int subscribe_channel (struct stasis_app *app, void *obj)
 
static int subscribe_endpoint (struct stasis_app *app, void *obj)
 
static int unsubscribe (struct stasis_app *app, const char *kind, const char *id, int terminate)
 

Variables

struct stasis_app_event_source bridge_event_source
 
struct stasis_app_event_source channel_event_source
 
static channel_snapshot_monitor channel_monitors []
 
struct stasis_app_event_source endpoint_event_source
 
int global_debug
 

Detailed Description

Stasis application support.

Author
David M. Lee, II dlee@.nosp@m.digi.nosp@m.um.co.nosp@m.m

Definition in file res/stasis/app.c.

Macro Definition Documentation

◆ BRIDGE_ALL

#define BRIDGE_ALL   "__AST_BRIDGE_ALL_TOPIC"

Definition at line 40 of file res/stasis/app.c.

◆ CHANNEL_ALL

#define CHANNEL_ALL   "__AST_CHANNEL_ALL_TOPIC"

Definition at line 41 of file res/stasis/app.c.

◆ ENDPOINT_ALL

#define ENDPOINT_ALL   "__AST_ENDPOINT_ALL_TOPIC"

Definition at line 42 of file res/stasis/app.c.

Typedef Documentation

◆ channel_snapshot_monitor

typedef struct ast_json *(* channel_snapshot_monitor) (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)

Typedef for callbacks that get called on channel snapshot updates.

Definition at line 347 of file res/stasis/app.c.

Enumeration Type Documentation

◆ forward_type

Enumerator
FORWARD_CHANNEL 
FORWARD_BRIDGE 
FORWARD_ENDPOINT 

Definition at line 76 of file res/stasis/app.c.

76 {
80};
@ FORWARD_CHANNEL
@ FORWARD_ENDPOINT
@ FORWARD_BRIDGE

Function Documentation

◆ app_create()

struct stasis_app * app_create ( const char *  name,
stasis_app_cb  handler,
void *  data,
enum stasis_app_subscription_model  subscription_model 
)

Create a res_stasis application.

Parameters
nameName of the application.
handlerCallback for messages sent to the application.
dataData pointer provided to the callback.
subscription_model
Returns
New res_stasis application.
Return values
NULLon error.

Definition at line 932 of file res/stasis/app.c.

933{
935 size_t size;
936 int res = 0;
937 size_t context_size = strlen("stasis-") + strlen(name) + 1;
938 char context_name[context_size];
939 char *topic_name;
940 int ret;
941
942 ast_assert(name != NULL);
944
945 ast_verb(1, "Creating Stasis app '%s'\n", name);
946
947 size = sizeof(*app) + strlen(name) + 1;
949 if (!app) {
950 return NULL;
951 }
952 app->subscription_model = subscription_model;
953
957 if (!app->forwards) {
958 return NULL;
959 }
960
961 ret = ast_asprintf(&topic_name, "ari:application/%s", name);
962 if (ret < 0) {
963 return NULL;
964 }
965
966 app->topic = stasis_topic_create(topic_name);
967 ast_free(topic_name);
968 if (!app->topic) {
969 return NULL;
970 }
971
973 if (!app->bridge_router) {
974 return NULL;
975 }
976
977 res |= stasis_message_router_add(app->bridge_router,
979
980 res |= stasis_message_router_add(app->bridge_router,
982
983 res |= stasis_message_router_add(app->bridge_router,
985
986 res |= stasis_message_router_add(app->bridge_router,
988
989 if (res != 0) {
990 return NULL;
991 }
992 /* Bridge router holds a reference */
993 ao2_ref(app, +1);
994
995 app->router = stasis_message_router_create(app->topic);
996 if (!app->router) {
997 return NULL;
998 }
999
1000 res |= stasis_message_router_add(app->router,
1002
1003 res |= stasis_message_router_add(app->router,
1005
1008
1009 res |= stasis_message_router_add(app->router,
1011
1014
1015 if (res != 0) {
1016 return NULL;
1017 }
1018 /* Router holds a reference */
1019 ao2_ref(app, +1);
1020
1021 strncpy(app->name, name, size - sizeof(*app));
1022 app->handler = handler;
1023 app->data = ao2_bump(data);
1024
1025 /* Create a context, a match-all extension, and a 'h' extension for this application. Note that
1026 * this should only be done if a context does not already exist. */
1027 strcpy(context_name, "stasis-");
1028 strcat(context_name, name);
1030 if (!ast_context_find_or_create(NULL, NULL, context_name, "res_stasis")) {
1031 ast_log(LOG_WARNING, "Could not create context '%s' for Stasis application '%s'\n", context_name, name);
1032 } else {
1033 ast_add_extension(context_name, 0, "_.", 1, NULL, NULL, "Stasis", ast_strdup(name), ast_free_ptr, "res_stasis");
1034 ast_add_extension(context_name, 0, "h", 1, NULL, NULL, "NoOp", NULL, NULL, "res_stasis");
1035 }
1036 } else {
1037 ast_log(LOG_WARNING, "Not creating context '%s' for Stasis application '%s' because it already exists\n",
1039 }
1040
1041 ao2_ref(app, +1);
1042 return app;
1043}
static const char app[]
#define ast_free(a)
Definition astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
void ast_free_ptr(void *ptr)
free() wrapper
Definition astmm.c:1739
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition astmm.h:267
#define ast_log
Definition astobj2.c:42
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition astobj2.h:363
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
Definition astobj2.h:1349
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition astobj2.h:404
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
@ AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT
Reject duplicate objects in container.
Definition astobj2.h:1201
static const char name[]
Definition format_mp3.c:68
static const char context_name[]
struct stasis_message_type * ast_endpoint_snapshot_type(void)
Message type for ast_endpoint_snapshot.
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
#define ast_verb(level,...)
#define LOG_WARNING
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition pbx.c:6953
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition extconf.c:4170
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition pbx.c:6170
static void sub_endpoint_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void app_dtor(void *obj)
static void sub_subscription_change_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void sub_default_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void bridge_subscription_change_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void bridge_blind_transfer_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void bridge_attended_transfer_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void bridge_merge_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void sub_bridge_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void sub_channel_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int forwards_sort(const void *obj_left, const void *obj_right, int flags)
#define NULL
Definition resample.c:96
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition stasis.c:684
@ STASIS_SUBSCRIPTION_FORMATTER_JSON
Definition stasis.h:310
struct stasis_message_type * ast_bridge_snapshot_type(void)
Message type for ast_bridge_snapshot.
struct stasis_message_type * ast_blind_transfer_type(void)
Message type for ast_blind_transfer_message.
struct stasis_message_type * ast_attended_transfer_type(void)
Message type for ast_attended_transfer_message.
struct stasis_message_type * ast_bridge_merge_message_type(void)
Message type for ast_bridge_merge_message.
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
#define stasis_message_router_create(topic)
Create a new message router object.
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
int stasis_message_router_add_cache_update(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route for stasis_cache_update messages to a message router.
void stasis_message_router_set_formatters_default(struct stasis_message_router *router, stasis_subscription_cb callback, void *data, enum stasis_subscription_message_formatters formatters)
Sets the default route of a router with formatters.
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition test_ari.c:59
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981
#define ast_assert(a)
Definition utils.h:779

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_alloc_options, ao2_bump, ao2_cleanup, AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT, ao2_container_alloc_rbtree, ao2_ref, app, app_dtor(), ast_add_extension(), ast_asprintf, ast_assert, ast_attended_transfer_type(), ast_blind_transfer_type(), ast_bridge_merge_message_type(), ast_bridge_snapshot_type(), ast_bridge_topic_all(), ast_channel_snapshot_type(), ast_context_find(), ast_context_find_or_create(), ast_endpoint_snapshot_type(), ast_free, ast_free_ptr(), ast_log, ast_strdup, ast_verb, bridge_attended_transfer_handler(), bridge_blind_transfer_handler(), bridge_merge_handler(), bridge_subscription_change_handler(), context_name, stasis_app::data, forwards_sort(), handler(), LOG_WARNING, name, NULL, RAII_VAR, stasis_message_router_add(), stasis_message_router_add_cache_update(), stasis_message_router_create, stasis_message_router_set_formatters_default(), stasis_subscription_change_type(), STASIS_SUBSCRIPTION_FORMATTER_JSON, stasis_topic_create(), sub_bridge_update_handler(), sub_channel_update_handler(), sub_default_handler(), sub_endpoint_update_handler(), sub_subscription_change_handler(), and stasis_app::subscription_model.

Referenced by __stasis_app_register().

◆ app_deactivate()

void app_deactivate ( struct stasis_app app)

Deactivates an application.

Any channels currently in the application remain active (since the app might come back), but new channels are rejected.

Parameters
appApplication to deactivate.

Definition at line 1078 of file res/stasis/app.c.

1079{
1080 ao2_lock(app);
1081
1082 ast_verb(1, "Deactivating Stasis app '%s'\n", app->name);
1083 app->handler = NULL;
1084 ao2_cleanup(app->data);
1085 app->data = NULL;
1086
1087 ao2_unlock(app);
1088}
#define ao2_unlock(a)
Definition astobj2.h:729
#define ao2_lock(a)
Definition astobj2.h:717

References ao2_cleanup, ao2_lock, ao2_unlock, app, ast_verb, and NULL.

Referenced by stasis_app_unregister().

◆ app_dtor()

static void app_dtor ( void *  obj)
static

Definition at line 287 of file res/stasis/app.c.

288{
289 struct stasis_app *app = obj;
290 size_t size = strlen("stasis-") + strlen(app->name) + 1;
291 char context_name[size];
292
293 ast_verb(1, "Destroying Stasis app %s\n", app->name);
294
295 ast_assert(app->router == NULL);
296 ast_assert(app->bridge_router == NULL);
297 ast_assert(app->endpoint_router == NULL);
298
299 /* If we created a context for this application, remove it */
300 strcpy(context_name, "stasis-");
301 strcat(context_name, app->name);
303
304 ao2_cleanup(app->topic);
305 app->topic = NULL;
306 ao2_cleanup(app->forwards);
307 app->forwards = NULL;
308 ao2_cleanup(app->data);
309 app->data = NULL;
310
311 ast_json_unref(app->events_allowed);
312 app->events_allowed = NULL;
313 ast_json_unref(app->events_disallowed);
314 app->events_disallowed = NULL;
315
316}
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
int ast_context_destroy_by_name(const char *context, const char *registrar)
Destroy a context by name.
Definition pbx.c:8234

References ao2_cleanup, app, ast_assert, ast_context_destroy_by_name(), ast_json_unref(), ast_verb, context_name, and NULL.

Referenced by app_create().

◆ app_event_filter_matched()

static int app_event_filter_matched ( struct ast_json array,
struct ast_json event,
int  empty 
)
static

Definition at line 1730 of file res/stasis/app.c.

1731{
1732 struct ast_json *obj;
1733 int i;
1734
1735 if (!array || !ast_json_array_size(array)) {
1736 return empty;
1737 }
1738
1739 for (i = 0; i < ast_json_array_size(array) &&
1740 (obj = ast_json_array_get(array, i)); ++i) {
1741
1744 return 1;
1745 }
1746 }
1747
1748 return 0;
1749}
static int array(struct ast_channel *chan, const char *cmd, char *var, const char *value)
#define ast_json_object_string_get(object, key)
Get a string field from a JSON object.
Definition json.h:600
struct ast_json * ast_json_array_get(const struct ast_json *array, size_t index)
Get an element from an array.
Definition json.c:370
size_t ast_json_array_size(const struct ast_json *array)
Get the size of a JSON array.
Definition json.c:366
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition strings.c:238
Abstract JSON element (object, array, string, int, ...).

References array(), ast_json_array_get(), ast_json_array_size(), ast_json_object_string_get, and ast_strings_equal().

Referenced by stasis_app_event_allowed().

◆ app_event_filter_set()

static int app_event_filter_set ( struct stasis_app app,
struct ast_json **  member,
struct ast_json filter,
const char *  filter_type 
)
static

Definition at line 1667 of file res/stasis/app.c.

1669{
1672 /* If no filters are specified then reset this filter type */
1673 filter = NULL;
1674 } else {
1675 /* Otherwise try to get the filter array for this type */
1676 filter = ast_json_object_get(filter, filter_type);
1677 if (!filter) {
1678 /* A filter type exists, but not this one, so don't update */
1679 return 0;
1680 }
1681 }
1682 }
1683
1684 /* At this point the filter object should be an array */
1686 ast_log(LOG_ERROR, "Invalid json type event filter - app: %s, filter: %s\n",
1687 app->name, filter_type);
1688 return -1;
1689 }
1690
1691 if (filter) {
1692 /* Confirm that at least the type names are specified */
1693 struct ast_json *obj;
1694 int i;
1695
1696 for (i = 0; i < ast_json_array_size(filter) &&
1697 (obj = ast_json_array_get(filter, i)); ++i) {
1698
1699 if (ast_strlen_zero(ast_json_object_string_get(obj, "type"))) {
1700 ast_log(LOG_ERROR, "Filter event must have a type - app: %s, "
1701 "filter: %s\n", app->name, filter_type);
1702 return -1;
1703 }
1704 }
1705 }
1706
1707 ao2_lock(app);
1710 ao2_unlock(app);
1711
1712 return 0;
1713}
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
#define LOG_ERROR
enum ast_json_type ast_json_typeof(const struct ast_json *value)
Get the type of value.
Definition json.c:78
size_t ast_json_object_size(struct ast_json *object)
Get size of JSON object.
Definition json.c:403
@ AST_JSON_ARRAY
Definition json.h:165
@ AST_JSON_OBJECT
Definition json.h:164
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition json.c:67
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition json.c:407
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65

References ao2_lock, ao2_unlock, app, AST_JSON_ARRAY, ast_json_array_get(), ast_json_array_size(), AST_JSON_OBJECT, ast_json_object_get(), ast_json_object_size(), ast_json_object_string_get, ast_json_ref(), ast_json_typeof(), ast_json_unref(), ast_log, ast_strlen_zero(), filter(), LOG_ERROR, and NULL.

Referenced by app_events_allowed_set(), and app_events_disallowed_set().

◆ app_events_allowed_set()

static int app_events_allowed_set ( struct stasis_app app,
struct ast_json filter 
)
static

Definition at line 1715 of file res/stasis/app.c.

1716{
1717 return app_event_filter_set(app, &app->events_allowed, filter, "allowed");
1718}
static int app_event_filter_set(struct stasis_app *app, struct ast_json **member, struct ast_json *filter, const char *filter_type)

References app, app_event_filter_set(), and filter().

Referenced by stasis_app_event_filter_set().

◆ app_events_disallowed_set()

static int app_events_disallowed_set ( struct stasis_app app,
struct ast_json filter 
)
static

Definition at line 1720 of file res/stasis/app.c.

1721{
1722 return app_event_filter_set(app, &app->events_disallowed, filter, "disallowed");
1723}

References app, app_event_filter_set(), and filter().

Referenced by stasis_app_event_filter_set().

◆ app_is_active()

int app_is_active ( struct stasis_app app)

Checks whether an app is active.

Parameters
appApplication to check.
Return values
True(non-zero) if app is active.
False(zero) if app has been deactivated.

Definition at line 1106 of file res/stasis/app.c.

1107{
1108 int ret;
1109
1110 ao2_lock(app);
1111 ret = app->handler != NULL;
1112 ao2_unlock(app);
1113
1114 return ret;
1115}

References ao2_lock, ao2_unlock, app, and NULL.

Referenced by stasis_app_exec().

◆ app_is_finished()

int app_is_finished ( struct stasis_app app)

Checks whether a deactivated app has no channels.

Parameters
appApplication to check.
Return values
True(non-zero) if app is deactivated, and has no associated channels.
False(zero) otherwise.

Definition at line 1117 of file res/stasis/app.c.

1118{
1119 int ret;
1120
1121 ao2_lock(app);
1122 ret = app->handler == NULL && ao2_container_count(app->forwards) == 0;
1123 ao2_unlock(app);
1124
1125 return ret;
1126}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.

References ao2_container_count(), ao2_lock, ao2_unlock, app, and NULL.

Referenced by app_shutdown(), and cleanup_cb().

◆ app_is_subscribed_bridge_id()

int app_is_subscribed_bridge_id ( struct stasis_app app,
const char *  bridge_id 
)

Test if an app is subscribed to a bridge.

Parameters
appSubscribing application.
bridge_idId of bridge to check.
Return values
True(non-zero) if bridge is subscribed to app.
False(zero) if bridge is not subscribed.

Definition at line 1516 of file res/stasis/app.c.

1517{
1518 struct app_forwards *forwards;
1519
1520 if (ast_strlen_zero(bridge_id)) {
1521 bridge_id = BRIDGE_ALL;
1522 }
1523
1524 forwards = ao2_find(app->forwards, bridge_id, OBJ_SEARCH_KEY);
1525 ao2_cleanup(forwards);
1526
1527 return forwards != NULL;
1528}
#define ao2_find(container, arg, flags)
Definition astobj2.h:1736
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition astobj2.h:1101
#define BRIDGE_ALL

References ao2_cleanup, ao2_find, app, ast_strlen_zero(), BRIDGE_ALL, NULL, and OBJ_SEARCH_KEY.

◆ app_is_subscribed_channel_id()

int app_is_subscribed_channel_id ( struct stasis_app app,
const char *  channel_id 
)

Test if an app is subscribed to a channel.

Parameters
appSubscribing application.
channel_idId of channel to check.
Return values
True(non-zero) if channel is subscribed to app.
False(zero) if channel is not subscribed.

Definition at line 1414 of file res/stasis/app.c.

1415{
1416 struct app_forwards *forwards;
1417
1418 if (ast_strlen_zero(channel_id)) {
1419 channel_id = CHANNEL_ALL;
1420 }
1421 forwards = ao2_find(app->forwards, channel_id, OBJ_SEARCH_KEY);
1422 ao2_cleanup(forwards);
1423
1424 return forwards != NULL;
1425}
#define CHANNEL_ALL

References ao2_cleanup, ao2_find, app, ast_strlen_zero(), CHANNEL_ALL, NULL, and OBJ_SEARCH_KEY.

◆ app_is_subscribed_endpoint_id()

int app_is_subscribed_endpoint_id ( struct stasis_app app,
const char *  endpoint_id 
)

Test if an app is subscribed to a endpoint.

Parameters
appSubscribing application.
endpoint_idId of endpoint to check.
Return values
True(non-zero) if endpoint is subscribed to app.
False(zero) if endpoint is not subscribed.

Definition at line 1613 of file res/stasis/app.c.

1614{
1615 struct app_forwards *forwards;
1616
1617 if (ast_strlen_zero(endpoint_id)) {
1618 endpoint_id = ENDPOINT_ALL;
1619 }
1620 forwards = ao2_find(app->forwards, endpoint_id, OBJ_SEARCH_KEY);
1621 ao2_cleanup(forwards);
1622
1623 return forwards != NULL;
1624}
#define ENDPOINT_ALL

References ao2_cleanup, ao2_find, app, ast_strlen_zero(), ENDPOINT_ALL, NULL, and OBJ_SEARCH_KEY.

◆ app_send()

void app_send ( struct stasis_app app,
struct ast_json message 
)

Send a message to an application.

Parameters
appApp to send the message to.
messageMessage to send.

Definition at line 1050 of file res/stasis/app.c.

1051{
1053 char eid[20];
1054 void *data;
1055
1057 ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) {
1058 ast_log(AST_LOG_WARNING, "Failed to append EID to outgoing event %s\n",
1060 }
1061
1062 /* Copy off mutable state with lock held */
1063 ao2_lock(app);
1064 handler = app->handler;
1065 data = ao2_bump(app->data);
1066 ao2_unlock(app);
1067 /* Name is immutable; no need to copy */
1068
1069 if (handler) {
1070 handler(data, app->name, message);
1071 } else {
1072 ast_verb(3,
1073 "Inactive Stasis app '%s' missed message\n", app->name);
1074 }
1075 ao2_cleanup(data);
1076}
#define AST_LOG_WARNING
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition json.c:278
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition json.c:414
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition json.c:283
void(* stasis_app_cb)(void *data, const char *app_name, struct ast_json *message)
Callback for Stasis application handler.
Definition stasis_app.h:67
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition utils.c:2875
struct ast_eid ast_eid_default
Global EID.
Definition options.c:94

References ao2_bump, ao2_cleanup, ao2_lock, ao2_unlock, app, ast_eid_default, ast_eid_to_str(), ast_json_object_get(), ast_json_object_set(), ast_json_string_create(), ast_json_string_get(), ast_log, AST_LOG_WARNING, ast_verb, and handler().

Referenced by app_update(), message_received_handler(), stasis_app_exec(), stasis_app_send(), sub_bridge_update_handler(), sub_channel_update_handler(), and sub_endpoint_update_handler().

◆ app_shutdown()

void app_shutdown ( struct stasis_app app)

Tears down an application.

It should be finished before calling this.

Parameters
appApplication to unsubscribe.

Definition at line 1090 of file res/stasis/app.c.

1091{
1092 ao2_lock(app);
1093
1095
1097 app->router = NULL;
1098 stasis_message_router_unsubscribe(app->bridge_router);
1099 app->bridge_router = NULL;
1100 stasis_message_router_unsubscribe(app->endpoint_router);
1101 app->endpoint_router = NULL;
1102
1103 ao2_unlock(app);
1104}
int app_is_finished(struct stasis_app *app)
Checks whether a deactivated app has no channels.
void stasis_message_router_unsubscribe(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic.

References ao2_lock, ao2_unlock, app, app_is_finished(), ast_assert, NULL, and stasis_message_router_unsubscribe().

Referenced by cleanup_cb().

◆ app_subscribe_bridge()

int app_subscribe_bridge ( struct stasis_app app,
struct ast_bridge bridge 
)

Add a bridge subscription to an existing channel subscription.

Parameters
appApplication.
bridgeBridge to subscribe to.
Return values
0on success.
Non-zeroon error.

Definition at line 1440 of file res/stasis/app.c.

1441{
1442 struct app_forwards *forwards;
1443
1444 if (!app) {
1445 return -1;
1446 }
1447
1448 ao2_lock(app->forwards);
1449 /* If subscribed to all, don't subscribe again */
1450 forwards = ao2_find(app->forwards, BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1451 if (forwards) {
1452 ao2_unlock(app->forwards);
1453 ao2_ref(forwards, -1);
1454
1455 return 0;
1456 }
1457
1458 forwards = ao2_find(app->forwards,
1459 bridge ? bridge->uniqueid : BRIDGE_ALL,
1461 if (!forwards) {
1462 int res;
1463
1464 /* Forwards not found, create one */
1465 forwards = forwards_create_bridge(app, bridge);
1466 if (!forwards) {
1467 ao2_unlock(app->forwards);
1468
1469 return -1;
1470 }
1471
1472 res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
1473 if (!res) {
1474 ao2_unlock(app->forwards);
1475 ao2_ref(forwards, -1);
1476
1477 return -1;
1478 }
1479 }
1480
1481 ++forwards->interested;
1482 ast_debug(3, "Bridge '%s' is %d interested in %s\n",
1483 bridge ? bridge->uniqueid : "ALL",
1484 forwards->interested,
1485 app->name);
1486
1487 ao2_unlock(app->forwards);
1488 ao2_ref(forwards, -1);
1489
1490 return 0;
1491}
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition astobj2.h:1554
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition astobj2.h:1063
#define ast_debug(level,...)
Log a DEBUG message.
static struct app_forwards * forwards_create_bridge(struct stasis_app *app, struct ast_bridge *bridge)
const ast_string_field uniqueid
Definition bridge.h:405

References ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, app, ast_debug, BRIDGE_ALL, forwards_create_bridge(), app_forwards::interested, OBJ_NOLOCK, OBJ_SEARCH_KEY, and ast_bridge::uniqueid.

Referenced by control_swap_channel_in_bridge(), stasis_app_exec(), and subscribe_bridge().

◆ app_subscribe_channel()

int app_subscribe_channel ( struct stasis_app app,
struct ast_channel chan 
)

Subscribes an application to a channel.

Parameters
appApplication.
chanChannel to subscribe to.
Return values
0on success.
Non-zeroon error.

Definition at line 1293 of file res/stasis/app.c.

1294{
1295 struct app_forwards *forwards;
1296
1297 if (!app) {
1298 return -1;
1299 }
1300
1301 ao2_lock(app->forwards);
1302 /* If subscribed to all, don't subscribe again */
1303 forwards = ao2_find(app->forwards, CHANNEL_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1304 if (forwards) {
1305 ao2_unlock(app->forwards);
1306 ao2_ref(forwards, -1);
1307
1308 return 0;
1309 }
1310
1311 forwards = ao2_find(app->forwards,
1312 chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL,
1314 if (!forwards) {
1315 int res;
1316
1317 /* Forwards not found, create one */
1318 forwards = forwards_create_channel(app, chan);
1319 if (!forwards) {
1320 ao2_unlock(app->forwards);
1321
1322 return -1;
1323 }
1324
1325 res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
1326 if (!res) {
1327 ao2_unlock(app->forwards);
1328 ao2_ref(forwards, -1);
1329
1330 return -1;
1331 }
1332 }
1333
1334 ++forwards->interested;
1335 ast_debug(3, "Channel '%s' is %d interested in %s\n",
1336 chan ? ast_channel_uniqueid(chan) : "ALL",
1337 forwards->interested,
1338 app->name);
1339
1340 ao2_unlock(app->forwards);
1341 ao2_ref(forwards, -1);
1342
1343 return 0;
1344}
const char * ast_channel_uniqueid(const struct ast_channel *chan)
static struct app_forwards * forwards_create_channel(struct stasis_app *app, struct ast_channel *chan)

References ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, app, ast_channel_uniqueid(), ast_debug, CHANNEL_ALL, forwards_create_channel(), app_forwards::interested, OBJ_NOLOCK, and OBJ_SEARCH_KEY.

Referenced by call_forwarded_handler(), send_start_msg_snapshots(), stasis_app_subscribe_channel(), and subscribe_channel().

◆ app_subscribe_endpoint()

int app_subscribe_endpoint ( struct stasis_app app,
struct ast_endpoint endpoint 
)

Subscribes an application to a endpoint.

Parameters
appApplication.
endpointEndpoint to subscribe to.
Return values
0on success.
Non-zeroon error.

Definition at line 1543 of file res/stasis/app.c.

1544{
1545 struct app_forwards *forwards;
1546
1547 if (!app) {
1548 return -1;
1549 }
1550
1551 ao2_lock(app->forwards);
1552 /* If subscribed to all, don't subscribe again */
1553 forwards = ao2_find(app->forwards, ENDPOINT_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1554 if (forwards) {
1555 ao2_unlock(app->forwards);
1556 ao2_ref(forwards, -1);
1557
1558 return 0;
1559 }
1560
1561 forwards = ao2_find(app->forwards,
1562 endpoint ? ast_endpoint_get_id(endpoint) : ENDPOINT_ALL,
1564 if (!forwards) {
1565 int res;
1566
1567 /* Forwards not found, create one */
1568 forwards = forwards_create_endpoint(app, endpoint);
1569 if (!forwards) {
1570 ao2_unlock(app->forwards);
1571
1572 return -1;
1573 }
1574
1575 res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
1576 if (!res) {
1577 ao2_unlock(app->forwards);
1578 ao2_ref(forwards, -1);
1579
1580 return -1;
1581 }
1582
1583 /* Subscribe for messages */
1585 }
1586
1587 ++forwards->interested;
1588 ast_debug(3, "Endpoint '%s' is %d interested in %s\n",
1589 endpoint ? ast_endpoint_get_id(endpoint) : "ALL",
1590 forwards->interested,
1591 app->name);
1592
1593 ao2_unlock(app->forwards);
1594 ao2_ref(forwards, -1);
1595
1596 return 0;
1597}
const char * ast_endpoint_get_id(const struct ast_endpoint *endpoint)
Gets the tech/resource id of the given endpoint.
int messaging_app_subscribe_endpoint(const char *app_name, struct ast_endpoint *endpoint, message_received_cb callback, void *pvt)
Subscribe an application to an endpoint for messages.
Definition messaging.c:493
static int message_received_handler(const char *endpoint_id, struct ast_json *json_msg, void *pvt)
static struct app_forwards * forwards_create_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint)

References ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, app, ast_debug, ast_endpoint_get_id(), ENDPOINT_ALL, forwards_create_endpoint(), app_forwards::interested, message_received_handler(), messaging_app_subscribe_endpoint(), OBJ_NOLOCK, and OBJ_SEARCH_KEY.

Referenced by subscribe_endpoint().

◆ app_to_json()

struct ast_json * app_to_json ( const struct stasis_app app)

Create a JSON representation of a stasis_app.

Parameters
appThe application
Returns
JSON blob on success
Return values
NULLon error

Definition at line 1240 of file res/stasis/app.c.

1241{
1242 struct ast_json *json;
1243 struct ast_json *channels;
1244 struct ast_json *bridges;
1245 struct ast_json *endpoints;
1246 struct ao2_iterator i;
1247 struct app_forwards *forwards;
1248
1249 json = ast_json_pack("{s: s, s: [], s: [], s: []}",
1250 "name", app->name,
1251 "channel_ids", "bridge_ids", "endpoint_ids");
1252 if (!json) {
1253 return NULL;
1254 }
1255 channels = ast_json_object_get(json, "channel_ids");
1256 bridges = ast_json_object_get(json, "bridge_ids");
1257 endpoints = ast_json_object_get(json, "endpoint_ids");
1258
1259 i = ao2_iterator_init(app->forwards, 0);
1260 while ((forwards = ao2_iterator_next(&i))) {
1261 struct ast_json *array = NULL;
1262 int append_res;
1263
1264 switch (forwards->forward_type) {
1265 case FORWARD_CHANNEL:
1266 array = channels;
1267 break;
1268 case FORWARD_BRIDGE:
1269 array = bridges;
1270 break;
1271 case FORWARD_ENDPOINT:
1272 array = endpoints;
1273 break;
1274 }
1275
1276 /* If forward_type value is unexpected this will safely return an error. */
1277 append_res = ast_json_array_append(array, ast_json_string_create(forwards->id));
1278 ao2_ref(forwards, -1);
1279
1280 if (append_res != 0) {
1281 ast_log(LOG_ERROR, "Error building response\n");
1283 ast_json_unref(json);
1284
1285 return NULL;
1286 }
1287 }
1289
1290 return json;
1291}
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static struct ao2_container * bridges
Definition bridge.c:132
static struct channel_usage channels
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition json.c:378
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
static struct ao2_container * endpoints
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821
enum forward_type forward_type

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, app, array(), ast_json_array_append(), ast_json_object_get(), ast_json_pack(), ast_json_string_create(), ast_json_unref(), ast_log, bridges, channels, endpoints, FORWARD_BRIDGE, FORWARD_CHANNEL, FORWARD_ENDPOINT, app_forwards::forward_type, app_forwards::id, LOG_ERROR, and NULL.

Referenced by stasis_app_object_to_json().

◆ app_unsubscribe_bridge()

int app_unsubscribe_bridge ( struct stasis_app app,
struct ast_bridge bridge 
)

Cancel the bridge subscription for an application.

Parameters
appSubscribing application.
bridgeBridge to subscribe to.
Return values
0on success.
Non-zeroon error.

Definition at line 1498 of file res/stasis/app.c.

1499{
1500 if (!app) {
1501 return -1;
1502 }
1503
1504 return app_unsubscribe_bridge_id(app, bridge ? bridge->uniqueid : BRIDGE_ALL);
1505}
int app_unsubscribe_bridge_id(struct stasis_app *app, const char *bridge_id)
Cancel the subscription an app has for a bridge.

References app, app_unsubscribe_bridge_id(), BRIDGE_ALL, and ast_bridge::uniqueid.

Referenced by internal_bridge_after_cb(), and stasis_app_exec().

◆ app_unsubscribe_bridge_id()

int app_unsubscribe_bridge_id ( struct stasis_app app,
const char *  bridge_id 
)

Cancel the subscription an app has for a bridge.

Parameters
appSubscribing application.
bridge_idId of bridge to unsubscribe from.
Return values
0on success.
Non-zeroon error.

Definition at line 1507 of file res/stasis/app.c.

1508{
1509 if (!app) {
1510 return -1;
1511 }
1512
1513 return unsubscribe(app, "bridge", bridge_id, 0);
1514}
static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate)

References app, and unsubscribe().

Referenced by app_unsubscribe_bridge().

◆ app_unsubscribe_channel()

int app_unsubscribe_channel ( struct stasis_app app,
struct ast_channel chan 
)

Cancel the subscription an app has for a channel.

Parameters
appSubscribing application.
chanChannel to unsubscribe from.
Return values
0on success.
Non-zeroon error.

Definition at line 1396 of file res/stasis/app.c.

1397{
1398 if (!app) {
1399 return -1;
1400 }
1401
1403}
int app_unsubscribe_channel_id(struct stasis_app *app, const char *channel_id)
Cancel the subscription an app has for a channel.

References app, app_unsubscribe_channel_id(), ast_channel_uniqueid(), and CHANNEL_ALL.

Referenced by app_send_end_msg().

◆ app_unsubscribe_channel_id()

int app_unsubscribe_channel_id ( struct stasis_app app,
const char *  channel_id 
)

Cancel the subscription an app has for a channel.

Parameters
appSubscribing application.
channel_idId of channel to unsubscribe from.
Return values
0on success.
Non-zeroon error.

Definition at line 1405 of file res/stasis/app.c.

1406{
1407 if (!app) {
1408 return -1;
1409 }
1410
1411 return unsubscribe(app, "channel", channel_id, 0);
1412}

References app, and unsubscribe().

Referenced by app_unsubscribe_channel(), and send_start_msg_snapshots().

◆ app_unsubscribe_endpoint_id()

int app_unsubscribe_endpoint_id ( struct stasis_app app,
const char *  endpoint_id 
)

Cancel the subscription an app has for a endpoint.

Parameters
appSubscribing application.
endpoint_idId of endpoint to unsubscribe from.
Return values
0on success.
Non-zeroon error.

Definition at line 1604 of file res/stasis/app.c.

1605{
1606 if (!app) {
1607 return -1;
1608 }
1609
1610 return unsubscribe(app, "endpoint", endpoint_id, 0);
1611}

References app, and unsubscribe().

◆ app_update()

void app_update ( struct stasis_app app,
stasis_app_cb  handler,
void *  data 
)

Update the handler and data for a res_stasis application.

If app has been deactivated, this will reactivate it.

Parameters
appApplication to update.
handlerNew application callback.
dataNew data pointer for the callback.

Definition at line 1128 of file res/stasis/app.c.

1129{
1130 ao2_lock(app);
1131 if (app->handler && app->data) {
1132 struct ast_json *msg;
1133
1134 ast_verb(1, "Replacing Stasis app '%s'\n", app->name);
1135
1136 msg = ast_json_pack("{s: s, s: o?, s: s}",
1137 "type", "ApplicationReplaced",
1138 "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1139 "application", app->name);
1140 if (msg) {
1141 /*
1142 * The app must be unlocked before calling 'send' since a handler may
1143 * subsequently attempt to grab the app lock after first obtaining a
1144 * lock for another object, thus causing a deadlock.
1145 */
1146 ao2_unlock(app);
1147 app_send(app, msg);
1148 ao2_lock(app);
1149 ast_json_unref(msg);
1150 if (!app->handler) {
1151 /*
1152 * If the handler disappeared then the app was deactivated. In that
1153 * case don't replace. Re-activation will reset the handler later.
1154 */
1155 ao2_unlock(app);
1156 return;
1157 }
1158 }
1159 } else {
1160 ast_verb(1, "Activating Stasis app '%s'\n", app->name);
1161 }
1162
1163 app->handler = handler;
1164 ao2_replace(app->data, data);
1165 ao2_unlock(app);
1166}
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition astobj2.h:501
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition json.c:670
void app_send(struct stasis_app *app, struct ast_json *message)
Send a message to an application.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159

References ao2_lock, ao2_replace, ao2_unlock, app, app_send(), ast_json_pack(), ast_json_timeval(), ast_json_unref(), ast_tvnow(), ast_verb, handler(), and NULL.

Referenced by __stasis_app_register().

◆ ast_app_get_topic()

struct stasis_topic * ast_app_get_topic ( struct stasis_app app)

Returns the stasis topic for an app.

Parameters
appStasis app to get topic of

Definition at line 1045 of file res/stasis/app.c.

1046{
1047 return app->topic;
1048}

References app.

Referenced by app_send_end_msg(), send_start_msg_snapshots(), and stasis_app_user_event().

◆ bridge_app_subscribed()

static int bridge_app_subscribed ( struct stasis_app app,
const char *  uniqueid 
)
static

Helper function for determining if the application is subscribed to a given entity.

Definition at line 737 of file res/stasis/app.c.

738{
739 struct app_forwards *forwards = NULL;
740
741 forwards = ao2_find(app->forwards, uniqueid, OBJ_SEARCH_KEY);
742 if (!forwards) {
743 return 0;
744 }
745
746 ao2_ref(forwards, -1);
747 return 1;
748}

References ao2_find, ao2_ref, app, NULL, and OBJ_SEARCH_KEY.

Referenced by bridge_app_subscribed_involved(), bridge_attended_transfer_handler(), bridge_blind_transfer_handler(), and bridge_merge_handler().

◆ bridge_app_subscribed_involved()

static int bridge_app_subscribed_involved ( struct stasis_app app,
struct ast_bridge_snapshot snapshot 
)
static

Callback function for checking if channels in a bridge are subscribed to.

Definition at line 767 of file res/stasis/app.c.

768{
769 int subscribed = 0;
770 struct ao2_iterator iter;
771 char *uniqueid;
772
773 if (bridge_app_subscribed(app, snapshot->uniqueid)) {
774 return 1;
775 }
776
777 iter = ao2_iterator_init(snapshot->channels, 0);
778 for (; (uniqueid = ao2_iterator_next(&iter)); ao2_ref(uniqueid, -1)) {
779 if (bridge_app_subscribed(app, uniqueid)) {
780 subscribed = 1;
781 ao2_ref(uniqueid, -1);
782 break;
783 }
784 }
786
787 return subscribed;
788}
static int subscribed
Definition manager.c:167
static int bridge_app_subscribed(struct stasis_app *app, const char *uniqueid)
Helper function for determining if the application is subscribed to a given entity.
const ast_string_field uniqueid
Definition bridge.h:332
struct ao2_container * channels
Definition bridge.h:335

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, app, bridge_app_subscribed(), ast_bridge_snapshot::channels, subscribed, and ast_bridge_snapshot::uniqueid.

Referenced by bridge_attended_transfer_handler(), and bridge_blind_transfer_handler().

◆ bridge_attended_transfer_handler()

static void bridge_attended_transfer_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 803 of file res/stasis/app.c.

805{
806 struct stasis_app *app = data;
808 int subscribed = 0;
809
811 if (!subscribed) {
813 }
814 if (!subscribed && transfer_msg->to_transferee.bridge_snapshot) {
816 }
817 if (!subscribed && transfer_msg->to_transfer_target.bridge_snapshot) {
819 }
820
821 if (!subscribed) {
822 switch (transfer_msg->dest_type) {
825 break;
828 if (!subscribed) {
830 }
831 break;
832 break;
835 if (!subscribed) {
837 }
838 break;
839 default:
840 break;
841 }
842 }
843
844 if (subscribed) {
845 stasis_publish(app->topic, message);
846 }
847}
static int bridge_app_subscribed_involved(struct stasis_app *app, struct ast_bridge_snapshot *snapshot)
Callback function for checking if channels in a bridge are subscribed to.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1578
@ AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE
@ AST_ATTENDED_TRANSFER_DEST_LINK
@ AST_ATTENDED_TRANSFER_DEST_THREEWAY
Message representing attended transfer.
enum ast_attended_transfer_dest_type dest_type
struct ast_channel_snapshot * links[2]
struct ast_bridge_channel_snapshot_pair to_transfer_target
struct ast_bridge_channel_snapshot_pair threeway
union ast_attended_transfer_message::@305 dest
struct ast_bridge_channel_snapshot_pair to_transferee
char bridge[AST_UUID_STR_LEN]
struct ast_bridge_snapshot * bridge_snapshot
struct ast_channel_snapshot * channel_snapshot
const ast_string_field uniqueid
struct ast_channel_snapshot_base * base

References app, AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE, AST_ATTENDED_TRANSFER_DEST_LINK, AST_ATTENDED_TRANSFER_DEST_THREEWAY, ast_channel_snapshot::base, ast_attended_transfer_message::bridge, bridge_app_subscribed(), bridge_app_subscribed_involved(), ast_bridge_channel_snapshot_pair::bridge_snapshot, ast_bridge_channel_snapshot_pair::channel_snapshot, stasis_app::data, ast_attended_transfer_message::dest, ast_attended_transfer_message::dest_type, ast_attended_transfer_message::links, stasis_message_data(), stasis_publish(), subscribed, ast_attended_transfer_message::threeway, ast_attended_transfer_message::to_transfer_target, ast_attended_transfer_message::to_transferee, and ast_channel_snapshot_base::uniqueid.

Referenced by app_create().

◆ bridge_blind_transfer_handler()

static void bridge_blind_transfer_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 790 of file res/stasis/app.c.

792{
793 struct stasis_app *app = data;
795 struct ast_bridge_snapshot *bridge = transfer_msg->bridge;
796
797 if (bridge_app_subscribed(app, transfer_msg->transferer->base->uniqueid) ||
798 (bridge && bridge_app_subscribed_involved(app, bridge))) {
799 stasis_publish(app->topic, message);
800 }
801}
Message published during a blind transfer.
struct ast_bridge_snapshot * bridge
struct ast_channel_snapshot * transferer
Structure that contains a snapshot of information about a bridge.
Definition bridge.h:318

References app, ast_channel_snapshot::base, ast_blind_transfer_message::bridge, bridge_app_subscribed(), bridge_app_subscribed_involved(), stasis_app::data, stasis_message_data(), stasis_publish(), ast_blind_transfer_message::transferer, and ast_channel_snapshot_base::uniqueid.

Referenced by app_create().

◆ bridge_find()

static void * bridge_find ( const struct stasis_app app,
const char *  id 
)
static

Definition at line 1530 of file res/stasis/app.c.

1531{
1533}
struct ast_bridge * stasis_app_bridge_find_by_id(const char *bridge_id)
Returns the bridge with the given id.
Definition res_stasis.c:800

References stasis_app_bridge_find_by_id().

◆ bridge_merge_handler()

static void bridge_merge_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 750 of file res/stasis/app.c.

752{
753 struct stasis_app *app = data;
754 struct ast_bridge_merge_message *merge;
755
757
758 /* Find out if we're subscribed to either bridge */
759 if (bridge_app_subscribed(app, merge->from->uniqueid) ||
761 /* Forward the message to the app */
762 stasis_publish(app->topic, message);
763 }
764}
Message representing the merge of two bridges.
struct ast_bridge_snapshot * from
struct ast_bridge_snapshot * to

References app, bridge_app_subscribed(), stasis_app::data, ast_bridge_merge_message::from, stasis_message_data(), stasis_publish(), ast_bridge_merge_message::to, and ast_bridge_snapshot::uniqueid.

Referenced by app_create().

◆ bridge_subscription_change_handler()

static void bridge_subscription_change_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 849 of file res/stasis/app.c.

851{
852 struct stasis_app *app = data;
853
856 }
857}
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition stasis.c:1241

References ao2_cleanup, app, stasis_app::data, stasis_subscription_final_message(), and sub.

Referenced by app_create().

◆ call_forwarded_handler()

static void call_forwarded_handler ( struct stasis_app app,
struct stasis_message message 
)
static

Definition at line 318 of file res/stasis/app.c.

319{
321 struct ast_channel_snapshot *snapshot = ast_multi_channel_blob_get_channel(payload, "forwarded");
322 struct ast_channel *chan;
323
324 if (!snapshot) {
325 return;
326 }
327
329 if (!chan) {
330 return;
331 }
332
334 ast_channel_unref(chan);
335}
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition channel.c:1416
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3018
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan)
Subscribes an application to a channel.
Structure representing a snapshot of channel state.
Main Channel structure associated with a channel.
struct ast_channel_snapshot * snapshot
A multi channel blob data structure for multi_channel_blob stasis messages.

References app, app_subscribe_channel(), ast_channel_get_by_name(), ast_channel_unref, ast_multi_channel_blob_get_channel(), ast_channel_snapshot::base, ast_channel::snapshot, stasis_message_data(), and ast_channel_snapshot_base::uniqueid.

◆ channel_callerid()

static struct ast_json * channel_callerid ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot,
const struct timeval *  tv 
)
static

Definition at line 496 of file res/stasis/app.c.

500{
501 struct ast_json *json_channel;
502
503 /* No NewCallerid event on first channel snapshot */
504 if (!old_snapshot) {
505 return NULL;
506 }
507
508 if (ast_channel_snapshot_caller_id_equal(old_snapshot, new_snapshot)) {
509 return NULL;
510 }
511
512 json_channel = ast_channel_snapshot_to_json(new_snapshot, stasis_app_get_sanitizer());
513 if (!json_channel) {
514 return NULL;
515 }
516
517 return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
518 "type", "ChannelCallerId",
519 "timestamp", ast_json_timeval(*tv, NULL),
520 "caller_presentation", new_snapshot->caller->pres,
521 "caller_presentation_txt", ast_describe_caller_presentation(
522 new_snapshot->caller->pres),
523 "channel", json_channel);
524}
const char * ast_describe_caller_presentation(int data)
Convert caller ID pres value to explanatory string.
Definition callerid.c:1364
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
int ast_channel_snapshot_caller_id_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the callerid info of two snapshots.
struct ast_channel_snapshot_caller * caller

References ast_channel_snapshot_caller_id_equal(), ast_channel_snapshot_to_json(), ast_describe_caller_presentation(), ast_json_pack(), ast_json_timeval(), ast_channel_snapshot::caller, NULL, ast_channel_snapshot_caller::pres, and stasis_app_get_sanitizer().

◆ channel_connected_line()

static struct ast_json * channel_connected_line ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot,
const struct timeval *  tv 
)
static

Definition at line 526 of file res/stasis/app.c.

530{
531 struct ast_json *json_channel;
532
533 /* No ChannelConnectedLine event on first channel snapshot */
534 if (!old_snapshot) {
535 return NULL;
536 }
537
538 if (ast_channel_snapshot_connected_line_equal(old_snapshot, new_snapshot)) {
539 return NULL;
540 }
541
542 json_channel = ast_channel_snapshot_to_json(new_snapshot, stasis_app_get_sanitizer());
543 if (!json_channel) {
544 return NULL;
545 }
546
547 return ast_json_pack("{s: s, s: o, s: o}",
548 "type", "ChannelConnectedLine",
549 "timestamp", ast_json_timeval(*tv, NULL),
550 "channel", json_channel);
551}
int ast_channel_snapshot_connected_line_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the connected line info of two snapshots.

References ast_channel_snapshot_connected_line_equal(), ast_channel_snapshot_to_json(), ast_json_pack(), ast_json_timeval(), NULL, and stasis_app_get_sanitizer().

◆ channel_created_event()

static struct ast_json * channel_created_event ( struct ast_channel_snapshot snapshot,
const struct timeval *  tv 
)
static

Definition at line 393 of file res/stasis/app.c.

396{
397 return simple_channel_event("ChannelCreated", snapshot, tv);
398}
static struct ast_json * simple_channel_event(const char *type, struct ast_channel_snapshot *snapshot, const struct timeval *tv)

References simple_channel_event().

Referenced by channel_state().

◆ channel_destroyed_event()

static struct ast_json * channel_destroyed_event ( struct ast_channel_snapshot snapshot,
const struct timeval *  tv 
)
static

Definition at line 400 of file res/stasis/app.c.

403{
404 struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
405 struct ast_json *blob;
406
407 if (!json_channel) {
408 return NULL;
409 }
410
411 blob = ast_json_pack("{s: s, s: o, s: i, s: s}",
412 "type", "ChannelDestroyed",
413 "timestamp", ast_json_timeval(*tv, NULL),
414 "cause", snapshot->hangup->cause,
415 "cause_txt", ast_cause2str(snapshot->hangup->cause));
416
417 if (!blob) {
418 return NULL;
419 }
420
421 if (snapshot->hangup->tech_cause) {
422 ast_json_object_set(blob, "tech_cause",
424 }
425
426 ast_json_object_set(blob, "channel", json_channel);
427
428 return blob;
429}
const char * ast_cause2str(int cause) attribute_pure
Gives the string form of a given cause code.
Definition channel.c:612
struct ast_json * ast_json_integer_create(intmax_t value)
Create a JSON integer.
Definition json.c:327
struct ast_channel_snapshot_hangup * hangup

References ast_cause2str(), ast_channel_snapshot_to_json(), ast_json_integer_create(), ast_json_object_set(), ast_json_pack(), ast_json_timeval(), ast_channel_snapshot_hangup::cause, ast_channel_snapshot::hangup, NULL, stasis_app_get_sanitizer(), and ast_channel_snapshot_hangup::tech_cause.

Referenced by channel_state().

◆ channel_dialplan()

static struct ast_json * channel_dialplan ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot,
const struct timeval *  tv 
)
static

Definition at line 462 of file res/stasis/app.c.

466{
467 struct ast_json *json_channel;
468
469 /* No Newexten event on first channel snapshot */
470 if (!old_snapshot) {
471 return NULL;
472 }
473
474 /* Empty application is not valid for a Newexten event */
475 if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
476 return NULL;
477 }
478
479 if (ast_channel_snapshot_cep_equal(old_snapshot, new_snapshot)) {
480 return NULL;
481 }
482
483 json_channel = ast_channel_snapshot_to_json(new_snapshot, stasis_app_get_sanitizer());
484 if (!json_channel) {
485 return NULL;
486 }
487
488 return ast_json_pack("{s: s, s: o, s: s, s: s, s: o}",
489 "type", "ChannelDialplan",
490 "timestamp", ast_json_timeval(*tv, NULL),
491 "dialplan_app", new_snapshot->dialplan->appl,
492 "dialplan_app_data", AST_JSON_UTF8_VALIDATE(new_snapshot->dialplan->data),
493 "channel", json_channel);
494}
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
Definition json.h:224
int ast_channel_snapshot_cep_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the context, exten and priority of two snapshots.
const ast_string_field data
const ast_string_field appl
struct ast_channel_snapshot_dialplan * dialplan

References ast_channel_snapshot_dialplan::appl, ast_channel_snapshot_cep_equal(), ast_channel_snapshot_to_json(), ast_json_pack(), ast_json_timeval(), AST_JSON_UTF8_VALIDATE, ast_strlen_zero(), ast_channel_snapshot_dialplan::data, ast_channel_snapshot::dialplan, NULL, and stasis_app_get_sanitizer().

◆ channel_find()

static void * channel_find ( const struct stasis_app app,
const char *  id 
)
static

Definition at line 1427 of file res/stasis/app.c.

1428{
1429 return ast_channel_get_by_name(id);
1430}

References ast_channel_get_by_name().

◆ channel_state()

static struct ast_json * channel_state ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot,
const struct timeval *  tv 
)
static

Handle channel state changes.

Note
For channel snapshot updates, new_snapshot is guaranteed to be non-NULL. A channel going away is indicated by AST_FLAG_DEAD on the new snapshot. See stasis_channels.h for the invariant.

Definition at line 445 of file res/stasis/app.c.

449{
450
451 if (!old_snapshot) {
452 return channel_created_event(new_snapshot, tv);
453 } else if (ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD)) {
454 return channel_destroyed_event(new_snapshot, tv);
455 } else if (old_snapshot->state != new_snapshot->state) {
456 return channel_state_change_event(new_snapshot, tv);
457 }
458
459 return NULL;
460}
@ AST_FLAG_DEAD
Definition channel.h:1065
static struct ast_json * channel_destroyed_event(struct ast_channel_snapshot *snapshot, const struct timeval *tv)
static struct ast_json * channel_created_event(struct ast_channel_snapshot *snapshot, const struct timeval *tv)
static struct ast_json * channel_state_change_event(struct ast_channel_snapshot *snapshot, const struct timeval *tv)
enum ast_channel_state state
struct ast_flags flags
#define ast_test_flag(p, flag)
Definition utils.h:64

References AST_FLAG_DEAD, ast_test_flag, channel_created_event(), channel_destroyed_event(), channel_state_change_event(), ast_channel_snapshot::flags, NULL, and ast_channel_snapshot::state.

◆ channel_state_change_event()

static struct ast_json * channel_state_change_event ( struct ast_channel_snapshot snapshot,
const struct timeval *  tv 
)
static

Definition at line 431 of file res/stasis/app.c.

434{
435 return simple_channel_event("ChannelStateChange", snapshot, tv);
436}

References simple_channel_event().

Referenced by channel_state().

◆ endpoint_find()

static void * endpoint_find ( const struct stasis_app app,
const char *  id 
)
static

Definition at line 1626 of file res/stasis/app.c.

1627{
1628 return ast_endpoint_find_by_id(id);
1629}
struct ast_endpoint * ast_endpoint_find_by_id(const char *id)
Finds the endpoint with the given tech[/resource] id.

References ast_endpoint_find_by_id().

◆ endpoint_state_cb()

static void endpoint_state_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 190 of file res/stasis/app.c.

192{
193 struct stasis_app *app = data;
194
195 stasis_publish(app->topic, message);
196}

References app, stasis_app::data, and stasis_publish().

Referenced by forwards_create_endpoint().

◆ forwards_create()

static struct app_forwards * forwards_create ( struct stasis_app app,
const char *  id 
)
static

Definition at line 116 of file res/stasis/app.c.

118{
119 struct app_forwards *forwards;
120
121 if (!app || ast_strlen_zero(id)) {
122 return NULL;
123 }
124
125 forwards = ao2_t_alloc(sizeof(*forwards) + strlen(id) + 1, forwards_dtor, id);
126 if (!forwards) {
127 return NULL;
128 }
129
130 strcpy(forwards->id, id); /* SAFE */
131
132 return forwards;
133}
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition astobj2.h:407
static void forwards_dtor(void *obj)

References ao2_t_alloc, app, ast_strlen_zero(), forwards_dtor(), app_forwards::id, and NULL.

Referenced by forwards_create_bridge(), forwards_create_channel(), and forwards_create_endpoint().

◆ forwards_create_bridge()

static struct app_forwards * forwards_create_bridge ( struct stasis_app app,
struct ast_bridge bridge 
)
static

Forward a bridge's topics to an app

Definition at line 164 of file res/stasis/app.c.

166{
167 struct app_forwards *forwards;
168
169 if (!app) {
170 return NULL;
171 }
172
173 forwards = forwards_create(app, bridge ? bridge->uniqueid : BRIDGE_ALL);
174 if (!forwards) {
175 return NULL;
176 }
177
178 forwards->forward_type = FORWARD_BRIDGE;
179 forwards->topic_forward = stasis_forward_all(ast_bridge_topic(bridge), app->topic);
180
181 if (!forwards->topic_forward && bridge) {
182 forwards_unsubscribe(forwards);
183 ao2_ref(forwards, -1);
184 return NULL;
185 }
186
187 return forwards;
188}
static void forwards_unsubscribe(struct app_forwards *forwards)
static struct app_forwards * forwards_create(struct stasis_app *app, const char *id)
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition stasis.c:1645
struct stasis_topic * ast_bridge_topic(struct ast_bridge *bridge)
A topic which publishes the events for a particular bridge.
struct stasis_forward * topic_forward

References ao2_ref, app, ast_bridge_topic(), BRIDGE_ALL, FORWARD_BRIDGE, app_forwards::forward_type, forwards_create(), forwards_unsubscribe(), NULL, stasis_forward_all(), app_forwards::topic_forward, and ast_bridge::uniqueid.

Referenced by app_subscribe_bridge().

◆ forwards_create_channel()

static struct app_forwards * forwards_create_channel ( struct stasis_app app,
struct ast_channel chan 
)
static

Forward a channel's topics to an app

Definition at line 136 of file res/stasis/app.c.

138{
139 struct app_forwards *forwards;
140
141 if (!app) {
142 return NULL;
143 }
144
145 forwards = forwards_create(app, chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL);
146 if (!forwards) {
147 return NULL;
148 }
149
150 forwards->forward_type = FORWARD_CHANNEL;
153 app->topic);
154
155 if (!forwards->topic_forward) {
156 ao2_ref(forwards, -1);
157 return NULL;
158 }
159
160 return forwards;
161}
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.

References ao2_ref, app, ast_channel_topic(), ast_channel_topic_all(), ast_channel_uniqueid(), CHANNEL_ALL, FORWARD_CHANNEL, app_forwards::forward_type, forwards_create(), NULL, stasis_forward_all(), and app_forwards::topic_forward.

Referenced by app_subscribe_channel().

◆ forwards_create_endpoint()

static struct app_forwards * forwards_create_endpoint ( struct stasis_app app,
struct ast_endpoint endpoint 
)
static

Forward a endpoint's topics to an app

Definition at line 199 of file res/stasis/app.c.

201{
202 struct app_forwards *forwards;
203 int ret = 0;
204
205 if (!app) {
206 return NULL;
207 }
208
209 forwards = forwards_create(app, endpoint ? ast_endpoint_get_id(endpoint) : ENDPOINT_ALL);
210 if (!forwards) {
211 return NULL;
212 }
213
214 forwards->forward_type = FORWARD_ENDPOINT;
215 if (endpoint) {
217 app->topic);
219 ast_endpoint_topic_cached(endpoint), app->topic);
220
221 if (!forwards->topic_forward || !forwards->topic_cached_forward) {
222 /* Half-subscribed is a bad thing */
223 forwards_unsubscribe(forwards);
224 ao2_ref(forwards, -1);
225 return NULL;
226 }
227 } else {
228 /* Since endpoint subscriptions also subscribe to channels, in the case
229 * of all endpoint subscriptions, we only want messages for the endpoints.
230 * As such, we route those particular messages and then re-publish them
231 * on the app's topic.
232 */
233 ast_assert(app->endpoint_router == NULL);
235 if (!app->endpoint_router) {
236 forwards_unsubscribe(forwards);
237 ao2_ref(forwards, -1);
238 return NULL;
239 }
240
241 ret |= stasis_message_router_add(app->endpoint_router,
243 ret |= stasis_message_router_add(app->endpoint_router,
245
246 if (ret) {
247 ao2_ref(app->endpoint_router, -1);
248 app->endpoint_router = NULL;
249 ao2_ref(forwards, -1);
250 return NULL;
251 }
252 }
253
254 return forwards;
255}
struct stasis_topic * ast_endpoint_topic_cached(struct ast_endpoint *endpoint)
Returns the topic for a specific endpoint.
struct stasis_message_type * ast_endpoint_contact_state_type(void)
Message type for endpoint contact state changes.
struct stasis_topic * ast_endpoint_topic(struct ast_endpoint *endpoint)
Returns the topic for a specific endpoint.
struct stasis_topic * ast_endpoint_topic_all_cached(void)
Cached topic for all endpoint related messages.
struct stasis_message_type * ast_endpoint_state_type(void)
Message type for endpoint state changes.
static void endpoint_state_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct stasis_forward * topic_cached_forward

References ao2_ref, app, ast_assert, ast_endpoint_contact_state_type(), ast_endpoint_get_id(), ast_endpoint_state_type(), ast_endpoint_topic(), ast_endpoint_topic_all_cached(), ast_endpoint_topic_cached(), ENDPOINT_ALL, endpoint_state_cb(), FORWARD_ENDPOINT, app_forwards::forward_type, forwards_create(), forwards_unsubscribe(), NULL, stasis_forward_all(), stasis_message_router_add(), stasis_message_router_create, app_forwards::topic_cached_forward, and app_forwards::topic_forward.

Referenced by app_subscribe_endpoint().

◆ forwards_dtor()

static void forwards_dtor ( void *  obj)
static

Definition at line 98 of file res/stasis/app.c.

99{
100#ifdef AST_DEVMODE
101 struct app_forwards *forwards = obj;
102#endif /* AST_DEVMODE */
103
104 ast_assert(forwards->topic_forward == NULL);
106}

References ast_assert, NULL, app_forwards::topic_cached_forward, and app_forwards::topic_forward.

Referenced by forwards_create().

◆ forwards_filter_by_type()

static int forwards_filter_by_type ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 1173 of file res/stasis/app.c.

1174{
1175 struct app_forwards *forward = obj;
1176 enum forward_type *forward_type = arg;
1177
1178 if (forward->forward_type == *forward_type) {
1179 return CMP_MATCH;
1180 }
1181
1182 return 0;
1183}
@ CMP_MATCH
Definition astobj2.h:1027
forward_type

References CMP_MATCH, and app_forwards::forward_type.

Referenced by stasis_app_to_cli().

◆ forwards_sort()

static int forwards_sort ( const void *  obj_left,
const void *  obj_right,
int  flags 
)
static

Definition at line 257 of file res/stasis/app.c.

258{
259 const struct app_forwards *object_left = obj_left;
260 const struct app_forwards *object_right = obj_right;
261 const char *right_key = obj_right;
262 int cmp;
263
264 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
265 case OBJ_POINTER:
266 right_key = object_right->id;
267 /* Fall through */
268 case OBJ_KEY:
269 cmp = strcmp(object_left->id, right_key);
270 break;
271 case OBJ_PARTIAL_KEY:
272 /*
273 * We could also use a partial key struct containing a length
274 * so strlen() does not get called for every comparison instead.
275 */
276 cmp = strncmp(object_left->id, right_key, strlen(right_key));
277 break;
278 default:
279 /* Sort can only work on something with a full or partial key. */
280 ast_assert(0);
281 cmp = 0;
282 break;
283 }
284 return cmp;
285}
#define OBJ_KEY
Definition astobj2.h:1151
#define OBJ_POINTER
Definition astobj2.h:1150
#define OBJ_PARTIAL_KEY
Definition astobj2.h:1152

References ast_assert, app_forwards::id, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by app_create().

◆ forwards_unsubscribe()

static void forwards_unsubscribe ( struct app_forwards forwards)
static

Definition at line 108 of file res/stasis/app.c.

109{
111 forwards->topic_forward = NULL;
113 forwards->topic_cached_forward = NULL;
114}
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition stasis.c:1615

References NULL, stasis_forward_cancel(), app_forwards::topic_cached_forward, and app_forwards::topic_forward.

Referenced by forwards_create_bridge(), forwards_create_endpoint(), and unsubscribe().

◆ message_received_handler()

static int message_received_handler ( const char *  endpoint_id,
struct ast_json json_msg,
void *  pvt 
)
static

Definition at line 601 of file res/stasis/app.c.

602{
603 struct ast_endpoint_snapshot *snapshot;
604 struct ast_json *json_endpoint;
605 struct ast_json *message;
606 struct stasis_app *app = pvt;
607 char *tech;
608 char *resource;
609
610 tech = ast_strdupa(endpoint_id);
611 resource = strchr(tech, '/');
612 if (resource) {
613 resource[0] = '\0';
614 resource++;
615 }
616
617 if (ast_strlen_zero(tech) || ast_strlen_zero(resource)) {
618 return -1;
619 }
620
621 snapshot = ast_endpoint_latest_snapshot(tech, resource);
622 if (!snapshot) {
623 return -1;
624 }
625
626 json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
627 ao2_ref(snapshot, -1);
628 if (!json_endpoint) {
629 return -1;
630 }
631
632 message = ast_json_pack("{s: s, s: o, s: o, s: o}",
633 "type", "TextMessageReceived",
634 "timestamp", ast_json_timeval(ast_tvnow(), NULL),
635 "endpoint", json_endpoint,
636 "message", ast_json_ref(json_msg));
637 if (message) {
640 }
641
642 return 0;
643}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
struct ast_endpoint_snapshot * ast_endpoint_latest_snapshot(const char *tech, const char *resource)
Retrieve the most recent snapshot for the endpoint with the given name.
struct ast_json * ast_endpoint_snapshot_to_json(const struct ast_endpoint_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_endpoint_snapshot.
A snapshot of an endpoint's state.

References ao2_ref, app, app_send(), ast_endpoint_latest_snapshot(), ast_endpoint_snapshot_to_json(), ast_json_pack(), ast_json_ref(), ast_json_timeval(), ast_json_unref(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), NULL, and stasis_app_get_sanitizer().

Referenced by app_subscribe_endpoint().

◆ simple_bridge_event()

static struct ast_json * simple_bridge_event ( const char *  type,
struct ast_bridge_snapshot snapshot,
const struct timeval *  tv 
)
static

Definition at line 683 of file res/stasis/app.c.

687{
688 struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
689 if (!json_bridge) {
690 return NULL;
691 }
692
693 return ast_json_pack("{s: s, s: o, s: o}",
694 "type", type,
695 "timestamp", ast_json_timeval(*tv, NULL),
696 "bridge", json_bridge);
697}
static const char type[]
struct ast_json * ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_bridge_snapshot.

References ast_bridge_snapshot_to_json(), ast_json_pack(), ast_json_timeval(), NULL, stasis_app_get_sanitizer(), and type.

Referenced by sub_bridge_update_handler().

◆ simple_channel_event()

static struct ast_json * simple_channel_event ( const char *  type,
struct ast_channel_snapshot snapshot,
const struct timeval *  tv 
)
static

Definition at line 376 of file res/stasis/app.c.

380{
381 struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
382
383 if (!json_channel) {
384 return NULL;
385 }
386
387 return ast_json_pack("{s: s, s: o, s: o}",
388 "type", type,
389 "timestamp", ast_json_timeval(*tv, NULL),
390 "channel", json_channel);
391}

References ast_channel_snapshot_to_json(), ast_json_pack(), ast_json_timeval(), NULL, stasis_app_get_sanitizer(), and type.

Referenced by channel_created_event(), and channel_state_change_event().

◆ simple_endpoint_event()

static struct ast_json * simple_endpoint_event ( const char *  type,
struct ast_endpoint_snapshot snapshot,
const struct timeval *  tv 
)
static

Definition at line 584 of file res/stasis/app.c.

588{
589 struct ast_json *json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
590
591 if (!json_endpoint) {
592 return NULL;
593 }
594
595 return ast_json_pack("{s: s, s: o, s: o}",
596 "type", type,
597 "timestamp", ast_json_timeval(*tv, NULL),
598 "endpoint", json_endpoint);
599}

References ast_endpoint_snapshot_to_json(), ast_json_pack(), ast_json_timeval(), NULL, stasis_app_get_sanitizer(), and type.

Referenced by sub_endpoint_update_handler().

◆ stasis_app_event_allowed()

int stasis_app_event_allowed ( const char *  app_name,
struct ast_json event 
)

Check if the given event should be filtered.

Attempts first to find the event in the application's disallowed events list. If found then the event won't be sent to the remote. If not found in the disallowed list then a search is done to see if it can be found in the allowed list. If found the event message is sent, otherwise it is not sent.

Parameters
app_nameThe application name
eventThe event to check
Returns
True if allowed, false otherwise

Definition at line 1751 of file res/stasis/app.c.

1752{
1754 int res;
1755
1756 if (!app) {
1757 return 0;
1758 }
1759
1760 ao2_lock(app);
1761 res = !app_event_filter_matched(app->events_disallowed, event, 0) &&
1762 app_event_filter_matched(app->events_allowed, event, 1);
1763 ao2_unlock(app);
1764 ao2_ref(app, -1);
1765
1766 return res;
1767}
const char * app_name(struct ast_app *app)
Definition pbx_app.c:463
static int app_event_filter_matched(struct ast_json *array, struct ast_json *event, int empty)
struct stasis_app * stasis_app_get_by_name(const char *name)
Retrieve a handle to a Stasis application by its name.

References ao2_lock, ao2_ref, ao2_unlock, app, app_event_filter_matched(), app_name(), and stasis_app_get_by_name().

Referenced by ari_websocket_send_event().

◆ stasis_app_event_filter_set()

int stasis_app_event_filter_set ( struct stasis_app app,
struct ast_json filter 
)

Set the application's event type filter.

Parameters
appThe application
filterThe allowed and/or disallowed event filter
Returns
0 if successfully set

Definition at line 1725 of file res/stasis/app.c.

1726{
1728}
static int app_events_allowed_set(struct stasis_app *app, struct ast_json *filter)
static int app_events_disallowed_set(struct stasis_app *app, struct ast_json *filter)

References app, app_events_allowed_set(), app_events_disallowed_set(), and filter().

Referenced by ast_ari_applications_filter().

◆ stasis_app_event_filter_to_json()

struct ast_json * stasis_app_event_filter_to_json ( struct stasis_app app,
struct ast_json json 
)

Convert and add the app's event type filter(s) to the given json object.

Parameters
appThe application
jsonThe json object to add the filter data to
Returns
The given json object

Definition at line 1653 of file res/stasis/app.c.

1654{
1655 if (!app || !json) {
1656 return json;
1657 }
1658
1659 ast_json_object_set(json, "events_allowed", app->events_allowed ?
1660 ast_json_ref(app->events_allowed) : ast_json_array_create());
1661 ast_json_object_set(json, "events_disallowed", app->events_disallowed ?
1662 ast_json_ref(app->events_disallowed) : ast_json_array_create());
1663
1664 return json;
1665}
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition json.c:362

References app, ast_json_array_create(), ast_json_object_set(), and ast_json_ref().

Referenced by stasis_app_object_to_json().

◆ stasis_app_get_debug()

int stasis_app_get_debug ( struct stasis_app app)

Get debug status of an application.

Parameters
appThe app to check
Returns
The debug flag for the app || the global debug flag

Definition at line 880 of file res/stasis/app.c.

881{
882 return (app ? app->debug : 0) || global_debug;
883}
int global_debug

References app, and global_debug.

◆ stasis_app_get_debug_by_name()

int stasis_app_get_debug_by_name ( const char *  app_name)

Get debug status of an application.

Parameters
app_nameThe app_name to check
Returns
The debug flag for the app || the global debug flag

Definition at line 885 of file res/stasis/app.c.

886{
887 int debug_enabled = 0;
888
889 if (global_debug) {
890 debug_enabled = 1;
891 } else {
893
894 if (app) {
895 if (app->debug) {
896 debug_enabled = 1;
897 }
898 ao2_ref(app, -1);
899 }
900 }
901 return debug_enabled;
902}

References ao2_ref, app, app_name(), global_debug, and stasis_app_get_by_name().

Referenced by ari_websocket_process_request(), ast_ari_callback(), session_send_app_event(), and stasis_app_message_handler().

◆ stasis_app_name()

const char * stasis_app_name ( const struct stasis_app app)

Retrieve an application's name.

Parameters
appAn application
Returns
The name of the application.

Definition at line 1168 of file res/stasis/app.c.

1169{
1170 return app->name;
1171}

References app.

Referenced by app_compare(), app_hash(), app_send_end_msg(), app_subscribe(), app_unsubscribe(), append_name(), ari_set_debug(), bridge_stasis_push_peek(), cleanup_cb(), device_state_subscription_create(), devices_to_json(), find_device_state_subscription(), send_start_msg_snapshots(), stasis_app_exec(), and subscribe_device_state().

◆ stasis_app_register_event_sources()

void stasis_app_register_event_sources ( void  )

Register core event sources.

Definition at line 1639 of file res/stasis/app.c.

1640{
1644}
struct stasis_app_event_source bridge_event_source
struct stasis_app_event_source channel_event_source
struct stasis_app_event_source endpoint_event_source
void stasis_app_register_event_source(struct stasis_app_event_source *obj)
Register an application event source.

References bridge_event_source, channel_event_source, endpoint_event_source, and stasis_app_register_event_source().

Referenced by load_module().

◆ stasis_app_set_debug()

void stasis_app_set_debug ( struct stasis_app app,
int  debug 
)

Enable/disable request/response and event logging on an application.

Parameters
appThe app to debug
debugIf non-zero, enable debugging. If zero, disable.

Definition at line 859 of file res/stasis/app.c.

860{
861 if (!app) {
862 return;
863 }
864
865 app->debug = debug;
866}
static int debug
Global debug status.
Definition res_xmpp.c:570

References app, and debug.

Referenced by ari_set_debug(), and stasis_app_set_global_debug().

◆ stasis_app_set_debug_by_name()

void stasis_app_set_debug_by_name ( const char *  app_name,
int  debug 
)

Enable/disable request/response and event logging on an application.

Parameters
app_nameThe app name to debug
debugIf non-zero, enable debugging. If zero, disable.

Definition at line 868 of file res/stasis/app.c.

869{
871
872 if (!app) {
873 return;
874 }
875
876 app->debug = debug;
878}

References ao2_cleanup, app, app_name(), debug, and stasis_app_get_by_name().

◆ stasis_app_set_global_debug()

void stasis_app_set_global_debug ( int  debug)

Enable/disable request/response and event logging on all applications.

Parameters
debugIf non-zero, enable debugging. If zero, disable.

Definition at line 904 of file res/stasis/app.c.

905{
907 if (!global_debug) {
908 struct ao2_container *app_names = stasis_app_get_all();
909 struct ao2_iterator it_app_names;
910 char *app_name;
911 struct stasis_app *app;
912
913 if (!app_names || !ao2_container_count(app_names)) {
914 ao2_cleanup(app_names);
915 return;
916 }
917
918 it_app_names = ao2_iterator_init(app_names, 0);
919 while ((app_name = ao2_iterator_next(&it_app_names))) {
922 }
923
926 }
927 ao2_iterator_cleanup(&it_app_names);
928 ao2_cleanup(app_names);
929 }
930}
void ao2_iterator_cleanup(struct ao2_iterator *iter)
void stasis_app_set_debug(struct stasis_app *app, int debug)
Enable/disable request/response and event logging on an application.
struct ao2_container * stasis_app_get_all(void)
Gets the names of all registered Stasis applications.
Generic container type.

References ao2_cleanup, ao2_container_count(), ao2_iterator_cleanup(), ao2_iterator_init(), ao2_iterator_next, app, app_name(), debug, global_debug, stasis_app_get_all(), stasis_app_get_by_name(), and stasis_app_set_debug().

Referenced by ari_set_debug().

◆ stasis_app_to_cli()

void stasis_app_to_cli ( const struct stasis_app app,
struct ast_cli_args a 
)

Dump properties of a stasis_app to the CLI.

Parameters
appThe application
aThe CLI arguments

Definition at line 1185 of file res/stasis/app.c.

1186{
1187 struct ao2_iterator *channels;
1188 struct ao2_iterator *endpoints;
1189 struct ao2_iterator *bridges;
1190 struct app_forwards *forward;
1192
1193 ast_cli(a->fd, "Name: %s\n"
1194 " Debug: %s\n"
1195 " Subscription Model: %s\n",
1196 app->name,
1197 app->debug ? "Yes" : "No",
1198 app->subscription_model == STASIS_APP_SUBSCRIBE_ALL ?
1199 "Global Resource Subscription" :
1200 "Application/Explicit Resource Subscription");
1201 ast_cli(a->fd, " Subscriptions: %d\n", ao2_container_count(app->forwards));
1202
1203 ast_cli(a->fd, " Channels:\n");
1207 if (channels) {
1208 while ((forward = ao2_iterator_next(channels))) {
1209 ast_cli(a->fd, " %s (%d)\n", forward->id, forward->interested);
1210 ao2_ref(forward, -1);
1211 }
1213 }
1214
1215 ast_cli(a->fd, " Bridges:\n");
1217 bridges = ao2_callback(app->forwards, OBJ_MULTIPLE,
1219 if (bridges) {
1220 while ((forward = ao2_iterator_next(bridges))) {
1221 ast_cli(a->fd, " %s (%d)\n", forward->id, forward->interested);
1222 ao2_ref(forward, -1);
1223 }
1225 }
1226
1227 ast_cli(a->fd, " Endpoints:\n");
1231 if (endpoints) {
1232 while ((forward = ao2_iterator_next(endpoints))) {
1233 ast_cli(a->fd, " %s (%d)\n", forward->id, forward->interested);
1234 ao2_ref(forward, -1);
1235 }
1237 }
1238}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition astobj2.h:1693
@ OBJ_MULTIPLE
Definition astobj2.h:1049
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
static int forwards_filter_by_type(void *obj, void *arg, int flags)
@ STASIS_APP_SUBSCRIBE_ALL
An application is automatically subscribed to all resources in Asterisk, even if it does not control ...
const char * name
static struct test_val a

References a, ao2_callback, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_next, ao2_ref, app, ast_cli(), bridges, channels, endpoints, FORWARD_BRIDGE, FORWARD_CHANNEL, FORWARD_ENDPOINT, forwards_filter_by_type(), app_forwards::id, app_forwards::interested, test_val::name, OBJ_MULTIPLE, and STASIS_APP_SUBSCRIBE_ALL.

Referenced by ari_show_app().

◆ stasis_app_unregister_event_sources()

void stasis_app_unregister_event_sources ( void  )

Unregister core event sources.

Definition at line 1646 of file res/stasis/app.c.

1647{
1651}
void stasis_app_unregister_event_source(struct stasis_app_event_source *obj)
Unregister an application event source.

References bridge_event_source, channel_event_source, endpoint_event_source, and stasis_app_unregister_event_source().

Referenced by unload_module().

◆ sub_bridge_update_handler()

static void sub_bridge_update_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 699 of file res/stasis/app.c.

702{
703 struct ast_json *json = NULL;
704 struct stasis_app *app = data;
706 const struct timeval *tv;
707
709
711
712 if (!update->new_snapshot) {
713 json = simple_bridge_event("BridgeDestroyed", update->old_snapshot, tv);
714 } else if (!update->old_snapshot) {
715 json = simple_bridge_event("BridgeCreated", update->new_snapshot, tv);
716 } else if (update->new_snapshot && update->old_snapshot
717 && strcmp(update->new_snapshot->video_source_id, update->old_snapshot->video_source_id)) {
718 json = simple_bridge_event("BridgeVideoSourceChanged", update->new_snapshot, tv);
719 if (json && !ast_strlen_zero(update->old_snapshot->video_source_id)) {
720 ast_json_object_set(json, "old_video_source_id",
721 ast_json_string_create(update->old_snapshot->video_source_id));
722 }
723 }
724
725 if (json) {
726 app_send(app, json);
727 ast_json_unref(json);
728 }
729
730 if (!update->new_snapshot && update->old_snapshot) {
731 unsubscribe(app, "bridge", update->old_snapshot->uniqueid, 1);
732 }
733}
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition codec_g726.c:367
static struct ast_json * simple_bridge_event(const char *type, struct ast_bridge_snapshot *snapshot, const struct timeval *tv)
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.

References app, app_send(), ast_json_object_set(), ast_json_string_create(), ast_json_unref(), ast_strlen_zero(), stasis_app::data, NULL, simple_bridge_event(), stasis_message_data(), stasis_message_timestamp(), unsubscribe(), and update().

Referenced by app_create().

◆ sub_channel_update_handler()

static void sub_channel_update_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 560 of file res/stasis/app.c.

563{
564 struct stasis_app *app = data;
566 int i;
567
568 for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) {
569 struct ast_json *msg;
570
571 msg = channel_monitors[i](update->old_snapshot, update->new_snapshot,
573 if (msg) {
574 app_send(app, msg);
575 ast_json_unref(msg);
576 }
577 }
578
579 if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
580 unsubscribe(app, "channel", update->new_snapshot->base->uniqueid, 1);
581 }
582}
static channel_snapshot_monitor channel_monitors[]
Structure representing a change of snapshot of channel state.
#define ARRAY_LEN(a)
Definition utils.h:706

References app, app_send(), ARRAY_LEN, AST_FLAG_DEAD, ast_json_unref(), ast_test_flag, channel_monitors, stasis_app::data, stasis_message_data(), stasis_message_timestamp(), unsubscribe(), and update().

Referenced by app_create().

◆ sub_default_handler()

static void sub_default_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 347 of file res/stasis/app.c.

349{
350 struct stasis_app *app = data;
351 struct ast_json *json;
352
353 /* The dial type can be converted to JSON so it will always be passed
354 * here.
355 */
358 }
359
360 /* By default, send any message that has a JSON representation */
362 if (!json) {
363 return;
364 }
365
366 app_send(app, json);
367 ast_json_unref(json);
368}
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
static void call_forwarded_handler(struct stasis_app *app, struct stasis_message *message)
struct ast_json * stasis_message_to_json(struct stasis_message *msg, struct stasis_message_sanitizer *sanitize)
Build the JSON representation of the message.

Referenced by app_create().

◆ sub_endpoint_update_handler()

static void sub_endpoint_update_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 645 of file res/stasis/app.c.

648{
649 struct stasis_app *app = data;
651 struct ast_endpoint_snapshot *new_snapshot;
652 struct ast_endpoint_snapshot *old_snapshot;
653 const struct timeval *tv;
654
656
658
660
661 new_snapshot = stasis_message_data(update->new_snapshot);
662 old_snapshot = stasis_message_data(update->old_snapshot);
663
664 if (new_snapshot) {
665 struct ast_json *json;
666
667 tv = stasis_message_timestamp(update->new_snapshot);
668
669 json = simple_endpoint_event("EndpointStateChange", new_snapshot, tv);
670 if (!json) {
671 return;
672 }
673
674 app_send(app, json);
675 ast_json_unref(json);
676 }
677
678 if (!new_snapshot && old_snapshot) {
679 unsubscribe(app, "endpoint", old_snapshot->id, 1);
680 }
681}
struct stasis_message_type * stasis_cache_update_type(void)
Message type for cache update messages.
static struct ast_json * simple_endpoint_event(const char *type, struct ast_endpoint_snapshot *snapshot, const struct timeval *tv)
const ast_string_field id
Cache update message.
Definition stasis.h:965

References app, app_send(), ast_assert, ast_endpoint_snapshot_type(), ast_json_unref(), stasis_app::data, ast_endpoint_snapshot::id, simple_endpoint_event(), stasis_cache_update_type(), stasis_message_data(), stasis_message_timestamp(), unsubscribe(), and update().

Referenced by app_create().

◆ sub_subscription_change_handler()

static void sub_subscription_change_handler ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 337 of file res/stasis/app.c.

339{
340 struct stasis_app *app = data;
341
344 }
345}

References ao2_cleanup, app, stasis_app::data, stasis_subscription_final_message(), and sub.

Referenced by app_create().

◆ subscribe_bridge()

static int subscribe_bridge ( struct stasis_app app,
void *  obj 
)
static

Definition at line 1493 of file res/stasis/app.c.

1494{
1495 return app_subscribe_bridge(app, obj);
1496}
int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Add a bridge subscription to an existing channel subscription.

References app, and app_subscribe_bridge().

◆ subscribe_channel()

static int subscribe_channel ( struct stasis_app app,
void *  obj 
)
static

Definition at line 1346 of file res/stasis/app.c.

1347{
1348 return app_subscribe_channel(app, obj);
1349}

References app, and app_subscribe_channel().

◆ subscribe_endpoint()

static int subscribe_endpoint ( struct stasis_app app,
void *  obj 
)
static

Definition at line 1599 of file res/stasis/app.c.

1600{
1601 return app_subscribe_endpoint(app, obj);
1602}
int app_subscribe_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint)
Subscribes an application to a endpoint.

References app, and app_subscribe_endpoint().

◆ unsubscribe()

static int unsubscribe ( struct stasis_app app,
const char *  kind,
const char *  id,
int  terminate 
)
static

Definition at line 1351 of file res/stasis/app.c.

1352{
1353 struct app_forwards *forwards;
1354
1355 if (!id) {
1356 if (!strcmp(kind, "bridge")) {
1357 id = BRIDGE_ALL;
1358 } else if (!strcmp(kind, "channel")) {
1359 id = CHANNEL_ALL;
1360 } else if (!strcmp(kind, "endpoint")) {
1361 id = ENDPOINT_ALL;
1362 } else {
1363 ast_log(LOG_WARNING, "Unknown subscription kind '%s'\n", kind);
1364 return -1;
1365 }
1366 }
1367
1368 ao2_lock(app->forwards);
1369 forwards = ao2_find(app->forwards, id, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1370 if (!forwards) {
1371 ao2_unlock(app->forwards);
1372 ast_debug(3, "App '%s' not subscribed to %s '%s'\n", app->name, kind, id);
1373 return -1;
1374 }
1375 forwards->interested--;
1376
1377 ast_debug(3, "%s '%s': is %d interested in %s\n", kind, id, forwards->interested, app->name);
1378 if (forwards->interested == 0 || terminate) {
1379 /* No one is interested any more; unsubscribe */
1380 ast_debug(3, "%s '%s' unsubscribed from %s\n", kind, id, app->name);
1381 forwards_unsubscribe(forwards);
1382 ao2_find(app->forwards, forwards,
1384 OBJ_NODATA);
1385
1386 if (!strcmp(kind, "endpoint")) {
1388 }
1389 }
1390 ao2_unlock(app->forwards);
1391 ao2_ref(forwards, -1);
1392
1393 return 0;
1394}
@ OBJ_NODATA
Definition astobj2.h:1044
@ OBJ_UNLINK
Definition astobj2.h:1039
void messaging_app_unsubscribe_endpoint(const char *app_name, const char *endpoint_id)
Subscribe for messages from a particular endpoint.
Definition messaging.c:423

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, app, ast_debug, ast_log, BRIDGE_ALL, CHANNEL_ALL, ENDPOINT_ALL, forwards_unsubscribe(), app_forwards::interested, LOG_WARNING, messaging_app_unsubscribe_endpoint(), OBJ_NODATA, OBJ_NOLOCK, OBJ_POINTER, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by app_unsubscribe_bridge_id(), app_unsubscribe_channel_id(), app_unsubscribe_endpoint_id(), sub_bridge_update_handler(), sub_channel_update_handler(), and sub_endpoint_update_handler().

Variable Documentation

◆ bridge_event_source

struct stasis_app_event_source bridge_event_source

Definition at line 1535 of file res/stasis/app.c.

1535 {
1536 .scheme = "bridge:",
1537 .find = bridge_find,
1538 .subscribe = subscribe_bridge,
1539 .unsubscribe = app_unsubscribe_bridge_id,
1540 .is_subscribed = app_is_subscribed_bridge_id
1541};
static int subscribe_bridge(struct stasis_app *app, void *obj)
int app_is_subscribed_bridge_id(struct stasis_app *app, const char *bridge_id)
Test if an app is subscribed to a bridge.
static void * bridge_find(const struct stasis_app *app, const char *id)

Referenced by stasis_app_register_event_sources(), and stasis_app_unregister_event_sources().

◆ channel_event_source

struct stasis_app_event_source channel_event_source

Definition at line 1432 of file res/stasis/app.c.

1432 {
1433 .scheme = "channel:",
1434 .find = channel_find,
1435 .subscribe = subscribe_channel,
1436 .unsubscribe = app_unsubscribe_channel_id,
1437 .is_subscribed = app_is_subscribed_channel_id
1438};
static void * channel_find(const struct stasis_app *app, const char *id)
static int subscribe_channel(struct stasis_app *app, void *obj)
int app_is_subscribed_channel_id(struct stasis_app *app, const char *channel_id)
Test if an app is subscribed to a channel.

Referenced by stasis_app_register_event_sources(), and stasis_app_unregister_event_sources().

◆ channel_monitors

channel_snapshot_monitor channel_monitors[]
static

Definition at line 553 of file res/stasis/app.c.

553 {
558};
static struct ast_json * channel_connected_line(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)
static struct ast_json * channel_callerid(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)
static struct ast_json * channel_state(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)
Handle channel state changes.
static struct ast_json * channel_dialplan(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv)

Referenced by sub_channel_update_handler().

◆ endpoint_event_source

struct stasis_app_event_source endpoint_event_source

Definition at line 1631 of file res/stasis/app.c.

1631 {
1632 .scheme = "endpoint:",
1633 .find = endpoint_find,
1634 .subscribe = subscribe_endpoint,
1635 .unsubscribe = app_unsubscribe_endpoint_id,
1636 .is_subscribed = app_is_subscribed_endpoint_id
1637};
int app_is_subscribed_endpoint_id(struct stasis_app *app, const char *endpoint_id)
Test if an app is subscribed to a endpoint.
int app_unsubscribe_endpoint_id(struct stasis_app *app, const char *endpoint_id)
Cancel the subscription an app has for a endpoint.
static void * endpoint_find(const struct stasis_app *app, const char *id)
static int subscribe_endpoint(struct stasis_app *app, void *obj)

Referenced by stasis_app_register_event_sources(), and stasis_app_unregister_event_sources().

◆ global_debug

int global_debug

Global debug flag. No need for locking

Definition at line 45 of file res/stasis/app.c.

Referenced by stasis_app_get_debug(), stasis_app_get_debug_by_name(), and stasis_app_set_global_debug().