Asterisk - The Open Source Telephony Project  18.5.0
Enumerations | Functions
res/stasis/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. More...
 
void app_deactivate (struct stasis_app *app)
 Deactivates an application. More...
 
char * app_get_replace_channel_app (struct ast_channel *chan)
 Get the app that the replacement channel will be controlled by. More...
 
int app_is_active (struct stasis_app *app)
 Checks whether an app is active. More...
 
int app_is_finished (struct stasis_app *app)
 Checks whether a deactivated app has no channels. More...
 
int app_is_subscribed_bridge_id (struct stasis_app *app, const char *bridge_id)
 Test if an app is subscribed to a bridge. More...
 
int app_is_subscribed_channel_id (struct stasis_app *app, const char *channel_id)
 Test if an app is subscribed to a channel. More...
 
int app_is_subscribed_endpoint_id (struct stasis_app *app, const char *endpoint_id)
 Test if an app is subscribed to a endpoint. More...
 
void app_send (struct stasis_app *app, struct ast_json *message)
 Send a message to an application. More...
 
int app_send_end_msg (struct stasis_app *app, struct ast_channel *chan)
 Send StasisEnd message to the listening app. More...
 
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. More...
 
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. More...
 
void app_shutdown (struct stasis_app *app)
 Tears down an application. More...
 
int app_subscribe_bridge (struct stasis_app *app, struct ast_bridge *bridge)
 Add a bridge subscription to an existing channel subscription. More...
 
int app_subscribe_channel (struct stasis_app *app, struct ast_channel *chan)
 Subscribes an application to a channel. More...
 
int app_subscribe_endpoint (struct stasis_app *app, struct ast_endpoint *endpoint)
 Subscribes an application to a endpoint. More...
 
struct ast_jsonapp_to_json (const struct stasis_app *app)
 Create a JSON representation of a stasis_app. More...
 
int app_unsubscribe_bridge (struct stasis_app *app, struct ast_bridge *bridge)
 Cancel the bridge subscription for an application. More...
 
int app_unsubscribe_bridge_id (struct stasis_app *app, const char *bridge_id)
 Cancel the subscription an app has for a bridge. More...
 
int app_unsubscribe_channel (struct stasis_app *app, struct ast_channel *chan)
 Cancel the subscription an app has for a channel. More...
 
int app_unsubscribe_channel_id (struct stasis_app *app, const char *channel_id)
 Cancel the subscription an app has for a channel. More...
 
int app_unsubscribe_endpoint_id (struct stasis_app *app, const char *endpoint_id)
 Cancel the subscription an app has for a endpoint. More...
 
void app_update (struct stasis_app *app, stasis_app_cb handler, void *data)
 Update the handler and data for a res_stasis application. More...
 

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 
STASIS_APP_SUBSCRIBE_ALL 

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 };

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.
Returns
New res_stasis application.
NULL on error.

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

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, forwards_sort(), stasis_app::handler, LOG_WARNING, 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().

916 {
917  RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
918  size_t size;
919  int res = 0;
920  size_t context_size = strlen("stasis-") + strlen(name) + 1;
921  char context_name[context_size];
922  char *topic_name;
923  int ret;
924 
925  ast_assert(name != NULL);
926  ast_assert(handler != NULL);
927 
928  ast_verb(1, "Creating Stasis app '%s'\n", name);
929 
930  size = sizeof(*app) + strlen(name) + 1;
932  if (!app) {
933  return NULL;
934  }
935  app->subscription_model = subscription_model;
936 
940  if (!app->forwards) {
941  return NULL;
942  }
943 
944  ret = ast_asprintf(&topic_name, "ari:application/%s", name);
945  if (ret < 0) {
946  return NULL;
947  }
948 
949  app->topic = stasis_topic_create(topic_name);
950  ast_free(topic_name);
951  if (!app->topic) {
952  return NULL;
953  }
954 
956  if (!app->bridge_router) {
957  return NULL;
958  }
959 
960  res |= stasis_message_router_add(app->bridge_router,
962 
963  res |= stasis_message_router_add(app->bridge_router,
965 
966  res |= stasis_message_router_add(app->bridge_router,
968 
969  res |= stasis_message_router_add(app->bridge_router,
971 
972  if (res != 0) {
973  return NULL;
974  }
975  /* Bridge router holds a reference */
976  ao2_ref(app, +1);
977 
978  app->router = stasis_message_router_create(app->topic);
979  if (!app->router) {
980  return NULL;
981  }
982 
983  res |= stasis_message_router_add(app->router,
985 
986  res |= stasis_message_router_add(app->router,
988 
991 
992  res |= stasis_message_router_add(app->router,
994 
997 
998  if (res != 0) {
999  return NULL;
1000  }
1001  /* Router holds a reference */
1002  ao2_ref(app, +1);
1003 
1004  strncpy(app->name, name, size - sizeof(*app));
1005  app->handler = handler;
1006  app->data = ao2_bump(data);
1007 
1008  /* Create a context, a match-all extension, and a 'h' extension for this application. Note that
1009  * this should only be done if a context does not already exist. */
1010  strcpy(context_name, "stasis-");
1011  strcat(context_name, name);
1012  if (!ast_context_find(context_name)) {
1013  if (!ast_context_find_or_create(NULL, NULL, context_name, "res_stasis")) {
1014  ast_log(LOG_WARNING, "Could not create context '%s' for Stasis application '%s'\n", context_name, name);
1015  } else {
1016  ast_add_extension(context_name, 0, "_.", 1, NULL, NULL, "Stasis", ast_strdup(name), ast_free_ptr, "res_stasis");
1017  ast_add_extension(context_name, 0, "h", 1, NULL, NULL, "NoOp", NULL, NULL, "res_stasis");
1018  }
1019  } else {
1020  ast_log(LOG_WARNING, "Not creating context '%s' for Stasis application '%s' because it already exists\n",
1021  context_name, name);
1022  }
1023 
1024  ao2_ref(app, +1);
1025  return app;
1026 }
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.
static void sub_bridge_update_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 sub_channel_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)
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.
static int forwards_sort(const void *obj_left, const void *obj_right, int flags)
static void app_dtor(void *obj)
#define LOG_WARNING
Definition: logger.h:274
struct stasis_message_type * ast_endpoint_snapshot_type(void)
Message type for ast_endpoint_snapshot.
static void bridge_attended_transfer_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:695
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
static void sub_default_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
#define NULL
Definition: resample.c:96
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
#define ast_verb(level,...)
Definition: logger.h:463
static const char context_name[]
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
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.
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
struct stasis_message_type * ast_bridge_merge_message_type(void)
Message type for ast_bridge_merge_message.
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: extconf.c:4174
#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:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:618
#define stasis_message_router_create(topic)
struct stasis_message_type * ast_attended_transfer_type(void)
Message type for ast_attended_transfer_message.
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
static void bridge_subscription_change_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
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:6970
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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
static void sub_endpoint_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1358
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:6198
static const char app[]
Definition: app_mysql.c:62
Reject duplicate objects in container.
Definition: astobj2.h:1205
static void bridge_merge_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)

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

References ao2_cleanup, ao2_lock, ao2_unlock, ast_verb, stasis_app::data, stasis_app::handler, stasis_app::name, and NULL.

Referenced by stasis_app_unregister().

1067 {
1068  ao2_lock(app);
1069 
1070  ast_verb(1, "Deactivating Stasis app '%s'\n", app->name);
1071  app->handler = NULL;
1072  ao2_cleanup(app->data);
1073  app->data = NULL;
1074 
1075  ao2_unlock(app);
1076 }
stasis_app_cb handler
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ 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
channelThe 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 967 of file res_stasis.c.

References replace_channel_store::app, get_replace_channel_store(), NULL, and replace().

Referenced by bridge_stasis_run_cb().

968 {
970  char *replace_channel_app;
971 
972  if (!replace) {
973  return NULL;
974  }
975 
976  replace_channel_app = replace->app;
977  replace->app = NULL;
978 
979  return replace_channel_app;
980 }
#define NULL
Definition: resample.c:96
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
static struct replace_channel_store * get_replace_channel_store(struct ast_channel *chan, int no_create)
Definition: res_stasis.c:890

◆ app_is_active()

int app_is_active ( struct stasis_app app)

Checks whether an app is active.

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

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

References ao2_lock, ao2_unlock, stasis_app::handler, and NULL.

Referenced by stasis_app_exec().

1095 {
1096  int ret;
1097 
1098  ao2_lock(app);
1099  ret = app->handler != NULL;
1100  ao2_unlock(app);
1101 
1102  return ret;
1103 }
stasis_app_cb handler
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_lock(a)
Definition: astobj2.h:718

◆ app_is_finished()

int app_is_finished ( struct stasis_app app)

Checks whether a deactivated app has no channels.

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

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

References ao2_container_count(), ao2_lock, ao2_unlock, stasis_app::forwards, stasis_app::handler, and NULL.

Referenced by app_shutdown(), and cleanup_cb().

1106 {
1107  int ret;
1108 
1109  ao2_lock(app);
1110  ret = app->handler == NULL && ao2_container_count(app->forwards) == 0;
1111  ao2_unlock(app);
1112 
1113  return ret;
1114 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
stasis_app_cb handler
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ao2_container * forwards
#define ao2_lock(a)
Definition: astobj2.h:718

◆ 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.
Returns
True (non-zero) if bridge is subscribed to app.
False (zero) if bridge is not subscribed.

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

References ao2_cleanup, ao2_find, ast_strlen_zero, BRIDGE_ALL, stasis_app::forwards, NULL, and OBJ_SEARCH_KEY.

1505 {
1506  struct app_forwards *forwards;
1507 
1508  if (ast_strlen_zero(bridge_id)) {
1509  bridge_id = BRIDGE_ALL;
1510  }
1511 
1512  forwards = ao2_find(app->forwards, bridge_id, OBJ_SEARCH_KEY);
1513  ao2_cleanup(forwards);
1514 
1515  return forwards != NULL;
1516 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ao2_container * forwards
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define BRIDGE_ALL

◆ 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.
Returns
True (non-zero) if channel is subscribed to app.
False (zero) if channel is not subscribed.

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

References ao2_cleanup, ao2_find, ast_strlen_zero, CHANNEL_ALL, stasis_app::forwards, NULL, and OBJ_SEARCH_KEY.

1403 {
1404  struct app_forwards *forwards;
1405 
1406  if (ast_strlen_zero(channel_id)) {
1407  channel_id = CHANNEL_ALL;
1408  }
1409  forwards = ao2_find(app->forwards, channel_id, OBJ_SEARCH_KEY);
1410  ao2_cleanup(forwards);
1411 
1412  return forwards != NULL;
1413 }
#define CHANNEL_ALL
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ao2_container * forwards
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ 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.
Returns
True (non-zero) if endpoint is subscribed to app.
False (zero) if endpoint is not subscribed.

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

References ao2_cleanup, ao2_find, ast_strlen_zero, ENDPOINT_ALL, stasis_app::forwards, NULL, and OBJ_SEARCH_KEY.

1602 {
1603  struct app_forwards *forwards;
1604 
1605  if (ast_strlen_zero(endpoint_id)) {
1606  endpoint_id = ENDPOINT_ALL;
1607  }
1608  forwards = ao2_find(app->forwards, endpoint_id, OBJ_SEARCH_KEY);
1609  ao2_cleanup(forwards);
1610 
1611  return forwards != NULL;
1612 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ao2_container * forwards
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ENDPOINT_ALL

◆ app_send()

void app_send ( struct stasis_app app,
struct ast_json message 
)

Send a message to an application.

Parameters
appApplication.
messageMessage to send.

Send a message to an application.

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

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

References ao2_bump, ao2_cleanup, ao2_lock, ao2_unlock, 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, stasis_app::data, stasis_app::handler, and stasis_app::name.

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

1039 {
1041  char eid[20];
1042  void *data;
1043 
1044  if (ast_json_object_set(message, "asterisk_id", ast_json_string_create(
1045  ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) {
1046  ast_log(AST_LOG_WARNING, "Failed to append EID to outgoing event %s\n",
1047  ast_json_string_get(ast_json_object_get(message, "type")));
1048  }
1049 
1050  /* Copy off mutable state with lock held */
1051  ao2_lock(app);
1052  handler = app->handler;
1053  data = ao2_bump(app->data);
1054  ao2_unlock(app);
1055  /* Name is immutable; no need to copy */
1056 
1057  if (handler) {
1058  handler(data, app->name, message);
1059  } else {
1060  ast_verb(3,
1061  "Inactive Stasis app '%s' missed message\n", app->name);
1062  }
1063  ao2_cleanup(data);
1064 }
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
#define AST_LOG_WARNING
Definition: logger.h:279
stasis_app_cb handler
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_verb(level,...)
Definition: logger.h:463
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:404
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
void(* stasis_app_cb)(void *data, const char *app_name, struct ast_json *message)
Callback for Stasis application handler.
Definition: stasis_app.h:67
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
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

◆ 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 1083 of file res_stasis.c.

References ao2_cleanup, app_unsubscribe_channel(), ast_app_get_topic(), ast_channel_blob_create(), ast_json_pack(), ast_json_timeval(), ast_json_unref(), ast_log, ast_tvnow(), start_message_blob::blob, 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().

1084 {
1086  struct ast_json *blob;
1087  struct stasis_message *msg;
1088 
1089  if (sanitize && sanitize->channel
1090  && sanitize->channel(chan)) {
1091  return 0;
1092  }
1093 
1094  blob = ast_json_pack("{s: s, s: o}",
1095  "app", stasis_app_name(app),
1096  "timestamp", ast_json_timeval(ast_tvnow(), NULL)
1097  );
1098  if (!blob) {
1099  ast_log(LOG_ERROR, "Error packing JSON for StasisEnd message\n");
1100  return -1;
1101  }
1102 
1104  app_unsubscribe_channel(app, chan);
1105  msg = ast_channel_blob_create(chan, end_message_type(), blob);
1106  if (msg) {
1107  stasis_publish(ast_app_get_topic(app), msg);
1108  }
1109  ao2_cleanup(msg);
1110  ast_json_unref(blob);
1111 
1112  return 0;
1113 }
struct stasis_topic * ast_app_get_topic(struct stasis_app *app)
Returns the stasis topic for an app.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int app_unsubscribe_channel(struct stasis_app *app, struct ast_channel *chan)
Cancel the subscription an app has for a channel.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static void remove_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1236
#define NULL
Definition: resample.c:96
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
Definition: res_stasis.c:2264
Structure containing callbacks for Stasis message sanitization.
Definition: stasis.h:200
#define ast_log
Definition: astobj2.c:42
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
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 ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:649
#define LOG_ERROR
Definition: logger.h:285
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.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Abstract JSON element (object, array, string, int, ...).

◆ 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
channelThe channel on which this will be set
replace_appThe app that will be controlling this channel
Return values
zerosuccess
non-zerofailure

Definition at line 931 of file res_stasis.c.

References replace_channel_store::app, ast_free, ast_strdup, get_replace_channel_store(), NULL, and replace().

Referenced by bridge_stasis_push_peek().

932 {
934 
935  if (!replace) {
936  return -1;
937  }
938 
939  ast_free(replace->app);
940  replace->app = NULL;
941 
942  if (replace_app) {
943  replace->app = ast_strdup(replace_app);
944  if (!replace->app) {
945  return -1;
946  }
947  }
948 
949  return 0;
950 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ast_free(a)
Definition: astmm.h:182
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
static struct replace_channel_store * get_replace_channel_store(struct ast_channel *chan, int no_create)
Definition: res_stasis.c:890

◆ 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
channelThe 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 919 of file res_stasis.c.

References ao2_replace, get_replace_channel_store(), replace(), and replace_channel_store::snapshot.

Referenced by bridge_stasis_push_peek().

920 {
922 
923  if (!replace) {
924  return -1;
925  }
926 
927  ao2_replace(replace->snapshot, replace_snapshot);
928  return 0;
929 }
struct ast_channel_snapshot * snapshot
Definition: res_stasis.c:872
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
#define ao2_replace(dst, src)
Definition: astobj2.h:517
static struct replace_channel_store * get_replace_channel_store(struct ast_channel *chan, int no_create)
Definition: res_stasis.c:890

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

References ao2_lock, ao2_unlock, app_is_finished(), ast_assert, stasis_app::bridge_router, stasis_app::endpoint_router, NULL, stasis_app::router, and stasis_message_router_unsubscribe().

Referenced by cleanup_cb().

1079 {
1080  ao2_lock(app);
1081 
1083 
1085  app->router = NULL;
1087  app->bridge_router = NULL;
1089  app->endpoint_router = NULL;
1090 
1091  ao2_unlock(app);
1092 }
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct stasis_message_router * endpoint_router
#define ao2_lock(a)
Definition: astobj2.h:718
int app_is_finished(struct stasis_app *app)
Checks whether a deactivated app has no channels.
struct stasis_message_router * router
void stasis_message_router_unsubscribe(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic.
struct stasis_message_router * bridge_router

◆ 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.
Returns
0 on success.
Non-zero on error.

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

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

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

1429 {
1430  struct app_forwards *forwards;
1431 
1432  if (!app) {
1433  return -1;
1434  }
1435 
1436  ao2_lock(app->forwards);
1437  /* If subscribed to all, don't subscribe again */
1438  forwards = ao2_find(app->forwards, BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1439  if (forwards) {
1440  ao2_unlock(app->forwards);
1441  ao2_ref(forwards, -1);
1442 
1443  return 0;
1444  }
1445 
1446  forwards = ao2_find(app->forwards,
1447  bridge ? bridge->uniqueid : BRIDGE_ALL,
1449  if (!forwards) {
1450  int res;
1451 
1452  /* Forwards not found, create one */
1453  forwards = forwards_create_bridge(app, bridge);
1454  if (!forwards) {
1455  ao2_unlock(app->forwards);
1456 
1457  return -1;
1458  }
1459 
1460  res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
1461  if (!res) {
1462  ao2_unlock(app->forwards);
1463  ao2_ref(forwards, -1);
1464 
1465  return -1;
1466  }
1467  }
1468 
1469  ++forwards->interested;
1470  ast_debug(3, "Bridge '%s' is %d interested in %s\n",
1471  bridge ? bridge->uniqueid : "ALL",
1472  forwards->interested,
1473  app->name);
1474 
1475  ao2_unlock(app->forwards);
1476  ao2_ref(forwards, -1);
1477 
1478  return 0;
1479 }
static struct app_forwards * forwards_create_bridge(struct stasis_app *app, struct ast_bridge *bridge)
const ast_string_field uniqueid
Definition: bridge.h:409
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ao2_container * forwards
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define BRIDGE_ALL

◆ 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.
Returns
0 on success.
Non-zero on error.

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

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

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

1282 {
1283  struct app_forwards *forwards;
1284 
1285  if (!app) {
1286  return -1;
1287  }
1288 
1289  ao2_lock(app->forwards);
1290  /* If subscribed to all, don't subscribe again */
1291  forwards = ao2_find(app->forwards, CHANNEL_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1292  if (forwards) {
1293  ao2_unlock(app->forwards);
1294  ao2_ref(forwards, -1);
1295 
1296  return 0;
1297  }
1298 
1299  forwards = ao2_find(app->forwards,
1300  chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL,
1302  if (!forwards) {
1303  int res;
1304 
1305  /* Forwards not found, create one */
1306  forwards = forwards_create_channel(app, chan);
1307  if (!forwards) {
1308  ao2_unlock(app->forwards);
1309 
1310  return -1;
1311  }
1312 
1313  res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
1314  if (!res) {
1315  ao2_unlock(app->forwards);
1316  ao2_ref(forwards, -1);
1317 
1318  return -1;
1319  }
1320  }
1321 
1322  ++forwards->interested;
1323  ast_debug(3, "Channel '%s' is %d interested in %s\n",
1324  chan ? ast_channel_uniqueid(chan) : "ALL",
1325  forwards->interested,
1326  app->name);
1327 
1328  ao2_unlock(app->forwards);
1329  ao2_ref(forwards, -1);
1330 
1331  return 0;
1332 }
#define CHANNEL_ALL
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ao2_container * forwards
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct app_forwards * forwards_create_channel(struct stasis_app *app, struct ast_channel *chan)

◆ app_subscribe_endpoint()

int app_subscribe_endpoint ( struct stasis_app app,
struct ast_endpoint endpoint 
)

Subscribes an application to a endpoint.

Parameters
appApplication.
chanEndpoint to subscribe to.
Returns
0 on success.
Non-zero on error.

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

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

Referenced by subscribe_endpoint().

1532 {
1533  struct app_forwards *forwards;
1534 
1535  if (!app) {
1536  return -1;
1537  }
1538 
1539  ao2_lock(app->forwards);
1540  /* If subscribed to all, don't subscribe again */
1542  if (forwards) {
1543  ao2_unlock(app->forwards);
1544  ao2_ref(forwards, -1);
1545 
1546  return 0;
1547  }
1548 
1549  forwards = ao2_find(app->forwards,
1550  endpoint ? ast_endpoint_get_id(endpoint) : ENDPOINT_ALL,
1552  if (!forwards) {
1553  int res;
1554 
1555  /* Forwards not found, create one */
1556  forwards = forwards_create_endpoint(app, endpoint);
1557  if (!forwards) {
1558  ao2_unlock(app->forwards);
1559 
1560  return -1;
1561  }
1562 
1563  res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
1564  if (!res) {
1565  ao2_unlock(app->forwards);
1566  ao2_ref(forwards, -1);
1567 
1568  return -1;
1569  }
1570 
1571  /* Subscribe for messages */
1573  }
1574 
1575  ++forwards->interested;
1576  ast_debug(3, "Endpoint '%s' is %d interested in %s\n",
1577  endpoint ? ast_endpoint_get_id(endpoint) : "ALL",
1578  forwards->interested,
1579  app->name);
1580 
1581  ao2_unlock(app->forwards);
1582  ao2_ref(forwards, -1);
1583 
1584  return 0;
1585 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
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
struct ao2_container * forwards
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static struct app_forwards * forwards_create_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
static int message_received_handler(const char *endpoint_id, struct ast_json *json_msg, void *pvt)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * ast_endpoint_get_id(const struct ast_endpoint *endpoint)
Gets the tech/resource id of the given endpoint.
#define ENDPOINT_ALL

◆ 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
NULL on error

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

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, 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, stasis_app::forwards, app_forwards::id, LOG_ERROR, stasis_app::name, and NULL.

Referenced by stasis_app_object_to_json().

1229 {
1230  struct ast_json *json;
1231  struct ast_json *channels;
1232  struct ast_json *bridges;
1233  struct ast_json *endpoints;
1234  struct ao2_iterator i;
1235  struct app_forwards *forwards;
1236 
1237  json = ast_json_pack("{s: s, s: [], s: [], s: []}",
1238  "name", app->name,
1239  "channel_ids", "bridge_ids", "endpoint_ids");
1240  if (!json) {
1241  return NULL;
1242  }
1243  channels = ast_json_object_get(json, "channel_ids");
1244  bridges = ast_json_object_get(json, "bridge_ids");
1245  endpoints = ast_json_object_get(json, "endpoint_ids");
1246 
1247  i = ao2_iterator_init(app->forwards, 0);
1248  while ((forwards = ao2_iterator_next(&i))) {
1249  struct ast_json *array = NULL;
1250  int append_res;
1251 
1252  switch (forwards->forward_type) {
1253  case FORWARD_CHANNEL:
1254  array = channels;
1255  break;
1256  case FORWARD_BRIDGE:
1257  array = bridges;
1258  break;
1259  case FORWARD_ENDPOINT:
1260  array = endpoints;
1261  break;
1262  }
1263 
1264  /* If forward_type value is unexpected this will safely return an error. */
1265  append_res = ast_json_array_append(array, ast_json_string_create(forwards->id));
1266  ao2_ref(forwards, -1);
1267 
1268  if (append_res != 0) {
1269  ast_log(LOG_ERROR, "Error building response\n");
1271  ast_json_unref(json);
1272 
1273  return NULL;
1274  }
1275  }
1277 
1278  return json;
1279 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define NULL
Definition: resample.c:96
enum forward_type forward_type
struct ao2_container * forwards
#define ast_log
Definition: astobj2.c:42
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
static struct ao2_container * endpoints
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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:368
#define LOG_ERROR
Definition: logger.h:285
static int array(struct ast_channel *chan, const char *cmd, char *var, const char *value)
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static struct ao2_container * bridges
Definition: bridge.c:123
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
Abstract JSON element (object, array, string, int, ...).
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ app_unsubscribe_bridge()

int app_unsubscribe_bridge ( struct stasis_app app,
struct ast_bridge bridge 
)

Cancel the bridge subscription for an application.

Parameters
forwardsReturn from app_subscribe_channel().
bridgeBridge to subscribe to.
Returns
0 on success.
Non-zero on error.

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

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

Referenced by internal_bridge_after_cb(), and stasis_app_exec().

1487 {
1488  if (!app) {
1489  return -1;
1490  }
1491 
1492  return app_unsubscribe_bridge_id(app, bridge ? bridge->uniqueid : BRIDGE_ALL);
1493 }
const ast_string_field uniqueid
Definition: bridge.h:409
int app_unsubscribe_bridge_id(struct stasis_app *app, const char *bridge_id)
Cancel the subscription an app has for a bridge.
#define BRIDGE_ALL

◆ 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.
Returns
0 on success.
Non-zero on error.

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

References unsubscribe().

Referenced by app_unsubscribe_bridge().

1496 {
1497  if (!app) {
1498  return -1;
1499  }
1500 
1501  return unsubscribe(app, "bridge", bridge_id, 0);
1502 }
static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate)

◆ 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.
Returns
0 on success.
Non-zero on error.

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

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

Referenced by app_send_end_msg().

1385 {
1386  if (!app) {
1387  return -1;
1388  }
1389 
1390  return app_unsubscribe_channel_id(app, chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL);
1391 }
#define CHANNEL_ALL
int app_unsubscribe_channel_id(struct stasis_app *app, const char *channel_id)
Cancel the subscription an app has for a channel.
const char * ast_channel_uniqueid(const struct ast_channel *chan)

◆ 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.
Returns
0 on success.
Non-zero on error.

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

References unsubscribe().

Referenced by app_unsubscribe_channel(), and send_start_msg_snapshots().

1394 {
1395  if (!app) {
1396  return -1;
1397  }
1398 
1399  return unsubscribe(app, "channel", channel_id, 0);
1400 }
static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate)

◆ 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.
Returns
0 on success.
Non-zero on error.

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

References unsubscribe().

1593 {
1594  if (!app) {
1595  return -1;
1596  }
1597 
1598  return unsubscribe(app, "endpoint", endpoint_id, 0);
1599 }
static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate)

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

References ao2_lock, ao2_replace, ao2_unlock, app_send(), ast_json_pack(), ast_json_timeval(), ast_json_unref(), ast_tvnow(), ast_verb, stasis_app::data, stasis_app::handler, stasis_app::name, and NULL.

Referenced by __stasis_app_register().

1117 {
1118  ao2_lock(app);
1119  if (app->handler && app->data) {
1120  struct ast_json *msg;
1121 
1122  ast_verb(1, "Replacing Stasis app '%s'\n", app->name);
1123 
1124  msg = ast_json_pack("{s: s, s: o?, s: s}",
1125  "type", "ApplicationReplaced",
1126  "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1127  "application", app->name);
1128  if (msg) {
1129  /*
1130  * The app must be unlocked before calling 'send' since a handler may
1131  * subsequently attempt to grab the app lock after first obtaining a
1132  * lock for another object, thus causing a deadlock.
1133  */
1134  ao2_unlock(app);
1135  app_send(app, msg);
1136  ao2_lock(app);
1137  ast_json_unref(msg);
1138  if (!app->handler) {
1139  /*
1140  * If the handler disappeared then the app was deactivated. In that
1141  * case don't replace. Re-activation will reset the handler later.
1142  */
1143  ao2_unlock(app);
1144  return;
1145  }
1146  }
1147  } else {
1148  ast_verb(1, "Activating Stasis app '%s'\n", app->name);
1149  }
1150 
1151  app->handler = handler;
1152  ao2_replace(app->data, data);
1153  ao2_unlock(app);
1154 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
stasis_app_cb handler
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:649
void app_send(struct stasis_app *app, struct ast_json *message)
Send a message to the given application.
#define ao2_replace(dst, src)
Definition: astobj2.h:517
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
Abstract JSON element (object, array, string, int, ...).