Asterisk - The Open Source Telephony Project GIT-master-27fb039
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 928 of file res/stasis/app.c.

929{
931 size_t size;
932 int res = 0;
933 size_t context_size = strlen("stasis-") + strlen(name) + 1;
934 char context_name[context_size];
935 char *topic_name;
936 int ret;
937
938 ast_assert(name != NULL);
940
941 ast_verb(1, "Creating Stasis app '%s'\n", name);
942
943 size = sizeof(*app) + strlen(name) + 1;
945 if (!app) {
946 return NULL;
947 }
948 app->subscription_model = subscription_model;
949
953 if (!app->forwards) {
954 return NULL;
955 }
956
957 ret = ast_asprintf(&topic_name, "ari:application/%s", name);
958 if (ret < 0) {
959 return NULL;
960 }
961
962 app->topic = stasis_topic_create(topic_name);
963 ast_free(topic_name);
964 if (!app->topic) {
965 return NULL;
966 }
967
969 if (!app->bridge_router) {
970 return NULL;
971 }
972
973 res |= stasis_message_router_add(app->bridge_router,
975
976 res |= stasis_message_router_add(app->bridge_router,
978
979 res |= stasis_message_router_add(app->bridge_router,
981
982 res |= stasis_message_router_add(app->bridge_router,
984
985 if (res != 0) {
986 return NULL;
987 }
988 /* Bridge router holds a reference */
989 ao2_ref(app, +1);
990
991 app->router = stasis_message_router_create(app->topic);
992 if (!app->router) {
993 return NULL;
994 }
995
996 res |= stasis_message_router_add(app->router,
998
999 res |= stasis_message_router_add(app->router,
1001
1004
1005 res |= stasis_message_router_add(app->router,
1007
1010
1011 if (res != 0) {
1012 return NULL;
1013 }
1014 /* Router holds a reference */
1015 ao2_ref(app, +1);
1016
1017 strncpy(app->name, name, size - sizeof(*app));
1018 app->handler = handler;
1019 app->data = ao2_bump(data);
1020
1021 /* Create a context, a match-all extension, and a 'h' extension for this application. Note that
1022 * this should only be done if a context does not already exist. */
1023 strcpy(context_name, "stasis-");
1024 strcat(context_name, name);
1026 if (!ast_context_find_or_create(NULL, NULL, context_name, "res_stasis")) {
1027 ast_log(LOG_WARNING, "Could not create context '%s' for Stasis application '%s'\n", context_name, name);
1028 } else {
1029 ast_add_extension(context_name, 0, "_.", 1, NULL, NULL, "Stasis", ast_strdup(name), ast_free_ptr, "res_stasis");
1030 ast_add_extension(context_name, 0, "h", 1, NULL, NULL, "NoOp", NULL, NULL, "res_stasis");
1031 }
1032 } else {
1033 ast_log(LOG_WARNING, "Not creating context '%s' for Stasis application '%s' because it already exists\n",
1035 }
1036
1037 ao2_ref(app, +1);
1038 return app;
1039}
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:6949
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 1074 of file res/stasis/app.c.

1075{
1076 ao2_lock(app);
1077
1078 ast_verb(1, "Deactivating Stasis app '%s'\n", app->name);
1079 app->handler = NULL;
1080 ao2_cleanup(app->data);
1081 app->data = NULL;
1082
1083 ao2_unlock(app);
1084}
#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 1102 of file res/stasis/app.c.

1103{
1104 int ret;
1105
1106 ao2_lock(app);
1107 ret = app->handler != NULL;
1108 ao2_unlock(app);
1109
1110 return ret;
1111}

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 1113 of file res/stasis/app.c.

1114{
1115 int ret;
1116
1117 ao2_lock(app);
1118 ret = app->handler == NULL && ao2_container_count(app->forwards) == 0;
1119 ao2_unlock(app);
1120
1121 return ret;
1122}
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 1512 of file res/stasis/app.c.

1513{
1514 struct app_forwards *forwards;
1515
1516 if (ast_strlen_zero(bridge_id)) {
1517 bridge_id = BRIDGE_ALL;
1518 }
1519
1520 forwards = ao2_find(app->forwards, bridge_id, OBJ_SEARCH_KEY);
1521 ao2_cleanup(forwards);
1522
1523 return forwards != NULL;
1524}
#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 1410 of file res/stasis/app.c.

1411{
1412 struct app_forwards *forwards;
1413
1414 if (ast_strlen_zero(channel_id)) {
1415 channel_id = CHANNEL_ALL;
1416 }
1417 forwards = ao2_find(app->forwards, channel_id, OBJ_SEARCH_KEY);
1418 ao2_cleanup(forwards);
1419
1420 return forwards != NULL;
1421}
#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 1609 of file res/stasis/app.c.

1610{
1611 struct app_forwards *forwards;
1612
1613 if (ast_strlen_zero(endpoint_id)) {
1614 endpoint_id = ENDPOINT_ALL;
1615 }
1616 forwards = ao2_find(app->forwards, endpoint_id, OBJ_SEARCH_KEY);
1617 ao2_cleanup(forwards);
1618
1619 return forwards != NULL;
1620}
#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 1046 of file res/stasis/app.c.

1047{
1049 char eid[20];
1050 void *data;
1051
1053 ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) {
1054 ast_log(AST_LOG_WARNING, "Failed to append EID to outgoing event %s\n",
1056 }
1057
1058 /* Copy off mutable state with lock held */
1059 ao2_lock(app);
1060 handler = app->handler;
1061 data = ao2_bump(app->data);
1062 ao2_unlock(app);
1063 /* Name is immutable; no need to copy */
1064
1065 if (handler) {
1066 handler(data, app->name, message);
1067 } else {
1068 ast_verb(3,
1069 "Inactive Stasis app '%s' missed message\n", app->name);
1070 }
1071 ao2_cleanup(data);
1072}
#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 1086 of file res/stasis/app.c.

1087{
1088 ao2_lock(app);
1089
1091
1093 app->router = NULL;
1094 stasis_message_router_unsubscribe(app->bridge_router);
1095 app->bridge_router = NULL;
1096 stasis_message_router_unsubscribe(app->endpoint_router);
1097 app->endpoint_router = NULL;
1098
1099 ao2_unlock(app);
1100}
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 1436 of file res/stasis/app.c.

1437{
1438 struct app_forwards *forwards;
1439
1440 if (!app) {
1441 return -1;
1442 }
1443
1444 ao2_lock(app->forwards);
1445 /* If subscribed to all, don't subscribe again */
1446 forwards = ao2_find(app->forwards, BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1447 if (forwards) {
1448 ao2_unlock(app->forwards);
1449 ao2_ref(forwards, -1);
1450
1451 return 0;
1452 }
1453
1454 forwards = ao2_find(app->forwards,
1455 bridge ? bridge->uniqueid : BRIDGE_ALL,
1457 if (!forwards) {
1458 int res;
1459
1460 /* Forwards not found, create one */
1461 forwards = forwards_create_bridge(app, bridge);
1462 if (!forwards) {
1463 ao2_unlock(app->forwards);
1464
1465 return -1;
1466 }
1467
1468 res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
1469 if (!res) {
1470 ao2_unlock(app->forwards);
1471 ao2_ref(forwards, -1);
1472
1473 return -1;
1474 }
1475 }
1476
1477 ++forwards->interested;
1478 ast_debug(3, "Bridge '%s' is %d interested in %s\n",
1479 bridge ? bridge->uniqueid : "ALL",
1480 forwards->interested,
1481 app->name);
1482
1483 ao2_unlock(app->forwards);
1484 ao2_ref(forwards, -1);
1485
1486 return 0;
1487}
#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 1289 of file res/stasis/app.c.

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

1540{
1541 struct app_forwards *forwards;
1542
1543 if (!app) {
1544 return -1;
1545 }
1546
1547 ao2_lock(app->forwards);
1548 /* If subscribed to all, don't subscribe again */
1549 forwards = ao2_find(app->forwards, ENDPOINT_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1550 if (forwards) {
1551 ao2_unlock(app->forwards);
1552 ao2_ref(forwards, -1);
1553
1554 return 0;
1555 }
1556
1557 forwards = ao2_find(app->forwards,
1558 endpoint ? ast_endpoint_get_id(endpoint) : ENDPOINT_ALL,
1560 if (!forwards) {
1561 int res;
1562
1563 /* Forwards not found, create one */
1564 forwards = forwards_create_endpoint(app, endpoint);
1565 if (!forwards) {
1566 ao2_unlock(app->forwards);
1567
1568 return -1;
1569 }
1570
1571 res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
1572 if (!res) {
1573 ao2_unlock(app->forwards);
1574 ao2_ref(forwards, -1);
1575
1576 return -1;
1577 }
1578
1579 /* Subscribe for messages */
1581 }
1582
1583 ++forwards->interested;
1584 ast_debug(3, "Endpoint '%s' is %d interested in %s\n",
1585 endpoint ? ast_endpoint_get_id(endpoint) : "ALL",
1586 forwards->interested,
1587 app->name);
1588
1589 ao2_unlock(app->forwards);
1590 ao2_ref(forwards, -1);
1591
1592 return 0;
1593}
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 1236 of file res/stasis/app.c.

1237{
1238 struct ast_json *json;
1239 struct ast_json *channels;
1240 struct ast_json *bridges;
1241 struct ast_json *endpoints;
1242 struct ao2_iterator i;
1243 struct app_forwards *forwards;
1244
1245 json = ast_json_pack("{s: s, s: [], s: [], s: []}",
1246 "name", app->name,
1247 "channel_ids", "bridge_ids", "endpoint_ids");
1248 if (!json) {
1249 return NULL;
1250 }
1251 channels = ast_json_object_get(json, "channel_ids");
1252 bridges = ast_json_object_get(json, "bridge_ids");
1253 endpoints = ast_json_object_get(json, "endpoint_ids");
1254
1255 i = ao2_iterator_init(app->forwards, 0);
1256 while ((forwards = ao2_iterator_next(&i))) {
1257 struct ast_json *array = NULL;
1258 int append_res;
1259
1260 switch (forwards->forward_type) {
1261 case FORWARD_CHANNEL:
1262 array = channels;
1263 break;
1264 case FORWARD_BRIDGE:
1265 array = bridges;
1266 break;
1267 case FORWARD_ENDPOINT:
1268 array = endpoints;
1269 break;
1270 }
1271
1272 /* If forward_type value is unexpected this will safely return an error. */
1273 append_res = ast_json_array_append(array, ast_json_string_create(forwards->id));
1274 ao2_ref(forwards, -1);
1275
1276 if (append_res != 0) {
1277 ast_log(LOG_ERROR, "Error building response\n");
1279 ast_json_unref(json);
1280
1281 return NULL;
1282 }
1283 }
1285
1286 return json;
1287}
#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 1494 of file res/stasis/app.c.

1495{
1496 if (!app) {
1497 return -1;
1498 }
1499
1500 return app_unsubscribe_bridge_id(app, bridge ? bridge->uniqueid : BRIDGE_ALL);
1501}
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 1503 of file res/stasis/app.c.

1504{
1505 if (!app) {
1506 return -1;
1507 }
1508
1509 return unsubscribe(app, "bridge", bridge_id, 0);
1510}
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 1392 of file res/stasis/app.c.

1393{
1394 if (!app) {
1395 return -1;
1396 }
1397
1399}
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 1401 of file res/stasis/app.c.

1402{
1403 if (!app) {
1404 return -1;
1405 }
1406
1407 return unsubscribe(app, "channel", channel_id, 0);
1408}

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 1600 of file res/stasis/app.c.

1601{
1602 if (!app) {
1603 return -1;
1604 }
1605
1606 return unsubscribe(app, "endpoint", endpoint_id, 0);
1607}

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 1124 of file res/stasis/app.c.

1125{
1126 ao2_lock(app);
1127 if (app->handler && app->data) {
1128 struct ast_json *msg;
1129
1130 ast_verb(1, "Replacing Stasis app '%s'\n", app->name);
1131
1132 msg = ast_json_pack("{s: s, s: o?, s: s}",
1133 "type", "ApplicationReplaced",
1134 "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1135 "application", app->name);
1136 if (msg) {
1137 /*
1138 * The app must be unlocked before calling 'send' since a handler may
1139 * subsequently attempt to grab the app lock after first obtaining a
1140 * lock for another object, thus causing a deadlock.
1141 */
1142 ao2_unlock(app);
1143 app_send(app, msg);
1144 ao2_lock(app);
1145 ast_json_unref(msg);
1146 if (!app->handler) {
1147 /*
1148 * If the handler disappeared then the app was deactivated. In that
1149 * case don't replace. Re-activation will reset the handler later.
1150 */
1151 ao2_unlock(app);
1152 return;
1153 }
1154 }
1155 } else {
1156 ast_verb(1, "Activating Stasis app '%s'\n", app->name);
1157 }
1158
1159 app->handler = handler;
1160 ao2_replace(app->data, data);
1161 ao2_unlock(app);
1162}
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().