Asterisk - The Open Source Telephony Project GIT-master-4f2b068
Loading...
Searching...
No Matches
Enumerations | Functions
app.h File Reference

Internal API for the Stasis application controller. More...

#include "asterisk/channel.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_app.h"
Include dependency graph for res/stasis/app.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  stasis_app_subscription_model { STASIS_APP_SUBSCRIBE_MANUAL , STASIS_APP_SUBSCRIBE_ALL }
 

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.
 
char * app_get_replace_channel_app (struct ast_channel *chan)
 Get the app that the replacement channel will be controlled by.
 
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.
 
int app_send_end_msg (struct stasis_app *app, struct ast_channel *chan)
 Send StasisEnd message to the listening app.
 
int app_set_replace_channel_app (struct ast_channel *chan, const char *replace_app)
 Set the app that the replacement channel will be controlled by.
 
int app_set_replace_channel_snapshot (struct ast_channel *chan, struct ast_channel_snapshot *replace_snapshot)
 Set the snapshot of the channel that this channel will replace.
 
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.
 

Detailed Description

Internal API for the Stasis application controller.

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

Definition in file res/stasis/app.h.

Enumeration Type Documentation

◆ stasis_app_subscription_model

Enumerator
STASIS_APP_SUBSCRIBE_MANUAL 

An application must manually subscribe to each resource that it cares about. This is the default approach.

STASIS_APP_SUBSCRIBE_ALL 

An application is automatically subscribed to all resources in Asterisk, even if it does not control them.

Definition at line 39 of file res/stasis/app.h.

39 {
40 /*!
41 * \brief An application must manually subscribe to each
42 * resource that it cares about. This is the default approach.
43 */
45 /*!
46 * \brief An application is automatically subscribed to all
47 * resources in Asterisk, even if it does not control them.
48 */
50};
@ STASIS_APP_SUBSCRIBE_MANUAL
An application must manually subscribe to each resource that it cares about. This is the default appr...
@ STASIS_APP_SUBSCRIBE_ALL
An application is automatically subscribed to all resources in Asterisk, even if it does not control ...

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_get_replace_channel_app()

char * app_get_replace_channel_app ( struct ast_channel chan)

Get the app that the replacement channel will be controlled by.

Parameters
chanThe channel on which this will be set
Return values
NULLon error
Returns
the name of the controlling app (must be ast_free()d)

Definition at line 1012 of file res_stasis.c.

1013{
1015 char *replace_channel_app;
1016
1017 if (!replace) {
1018 return NULL;
1019 }
1020
1021 replace_channel_app = replace->app;
1022 replace->app = NULL;
1023
1024 return replace_channel_app;
1025}
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static struct replace_channel_store * get_replace_channel_store(struct ast_channel *chan, int no_create)
Definition res_stasis.c:935

References get_replace_channel_store(), NULL, and replace().

Referenced by bridge_stasis_run_cb().

◆ 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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65

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
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
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_send_end_msg()

int app_send_end_msg ( struct stasis_app app,
struct ast_channel chan 
)

Send StasisEnd message to the listening app.

Parameters
appThe app that owns the channel
chanThe channel for which the message is being sent
Return values
zeroon success
Returns
non-zero on failure

Definition at line 1128 of file res_stasis.c.

1129{
1131 struct ast_json *blob;
1132 struct stasis_message *msg;
1133
1134 if (sanitize && sanitize->channel
1135 && sanitize->channel(chan)) {
1136 return 0;
1137 }
1138
1139 blob = ast_json_pack("{s: s, s: o}",
1140 "app", stasis_app_name(app),
1141 "timestamp", ast_json_timeval(ast_tvnow(), NULL)
1142 );
1143 if (!blob) {
1144 ast_log(LOG_ERROR, "Error packing JSON for StasisEnd message\n");
1145 return -1;
1146 }
1147
1150 msg = ast_channel_blob_create(chan, end_message_type(), blob);
1151 if (msg) {
1153 }
1154 ao2_cleanup(msg);
1155 ast_json_unref(blob);
1156
1157 return 0;
1158}
struct stasis_message * ast_channel_blob_create(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Creates a ast_channel_blob message.
#define LOG_ERROR
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition json.c:670
int app_unsubscribe_channel(struct stasis_app *app, struct ast_channel *chan)
Cancel the subscription an app has for a channel.
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
static void remove_masquerade_store(struct ast_channel *chan)
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1578
struct stasis_topic * ast_app_get_topic(struct stasis_app *app)
Returns the stasis topic for an app.
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application's name.
Abstract JSON element (object, array, string, int, ...).
Structure containing callbacks for Stasis message sanitization.
Definition stasis.h:200
int(* channel)(const struct ast_channel *chan)
Callback which determines whether a channel should be sanitized from a message based on the channel.
Definition stasis.h:232
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159

References ao2_cleanup, app, app_unsubscribe_channel(), ast_app_get_topic(), ast_channel_blob_create(), ast_json_pack(), ast_json_timeval(), ast_json_unref(), ast_log, ast_tvnow(), stasis_message_sanitizer::channel, LOG_ERROR, NULL, remove_masquerade_store(), stasis_app_get_sanitizer(), stasis_app_name(), and stasis_publish().

Referenced by bridge_stasis_moving(), channel_replaced_cb(), channel_stolen_cb(), and stasis_app_exec().

◆ app_set_replace_channel_app()

int app_set_replace_channel_app ( struct ast_channel chan,
const char *  replace_app 
)

Set the app that the replacement channel will be controlled by.

Parameters
chanThe channel on which this will be set
replace_appThe app that will be controlling this channel
Return values
zerosuccess
non-zerofailure

Definition at line 976 of file res_stasis.c.

977{
979
980 if (!replace) {
981 return -1;
982 }
983
984 ast_free(replace->app);
985 replace->app = NULL;
986
987 if (replace_app) {
988 replace->app = ast_strdup(replace_app);
989 if (!replace->app) {
990 return -1;
991 }
992 }
993
994 return 0;
995}

References ast_free, ast_strdup, get_replace_channel_store(), NULL, and replace().

Referenced by bridge_stasis_push_peek().

◆ app_set_replace_channel_snapshot()

int app_set_replace_channel_snapshot ( struct ast_channel chan,
struct ast_channel_snapshot replace_snapshot 
)

Set the snapshot of the channel that this channel will replace.

Parameters
chanThe channel on which this will be set
replace_snapshotThe snapshot of the channel that is being replaced
Return values
zerosuccess
non-zerofailure

Definition at line 964 of file res_stasis.c.

965{
967
968 if (!replace) {
969 return -1;
970 }
971
972 ao2_replace(replace->snapshot, replace_snapshot);
973 return 0;
974}
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition astobj2.h:501

References ao2_replace, get_replace_channel_store(), and replace().

Referenced by bridge_stasis_push_peek().

◆ 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
static int array(struct ast_channel *chan, const char *cmd, char *var, const char *value)
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition json.c:378
static struct ao2_container * endpoints
@ FORWARD_CHANNEL
@ FORWARD_ENDPOINT
@ FORWARD_BRIDGE
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}
void app_send(struct stasis_app *app, struct ast_json *message)
Send a message to an application.

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().