Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Typedefs | Functions | Variables
res_stasis.c File Reference

Stasis application support. More...

#include "asterisk.h"
#include "asterisk/astobj2.h"
#include "asterisk/callerid.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app_impl.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/strings.h"
#include "stasis/app.h"
#include "stasis/control.h"
#include "stasis/messaging.h"
#include "stasis/stasis_bridge.h"
#include "asterisk/core_unreal.h"
#include "asterisk/musiconhold.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/bridge_after.h"
#include "asterisk/format_cache.h"
Include dependency graph for res_stasis.c:

Go to the source code of this file.

Data Structures

struct  event_sources
 
struct  replace_channel_store
 
struct  start_message_blob
 
struct  stasis_app_bridge_channel_wrapper
 

Macros

#define APPS_NUM_BUCKETS   127
 Number of buckets for the Stasis application hash table. Remember to keep it a prime number! More...
 
#define BRIDGES_NUM_BUCKETS   127
 Number of buckets for the Stasis bridges hash table. Remember to keep it a prime number! More...
 
#define CONTROLS_NUM_BUCKETS   127
 Number of buckets for the Stasis application hash table. Remember to keep it a prime number! More...
 
#define MAX_WAIT_MS   200
 

Typedefs

typedef enum stasis_app_subscribe_res(* app_subscription_handler) (struct stasis_app *app, const char *uri, struct stasis_app_event_source *event_source)
 

Functions

static void __reg_module (void)
 
static int __stasis_app_register (const char *app_name, stasis_app_cb handler, void *data, int all_events)
 
static void __unreg_module (void)
 
static int add_masquerade_store (struct ast_channel *chan)
 
static int app_compare (void *obj, void *arg, int flags)
 
static struct stasis_app_event_sourceapp_event_source_find (const char *uri)
 
static struct ast_jsonapp_event_sources_to_json (const struct stasis_app *app, struct ast_json *json)
 
char * app_get_replace_channel_app (struct ast_channel *chan)
 Get the app that the replacement channel will be controlled by. More...
 
static enum stasis_app_subscribe_res app_handle_subscriptions (const char *app_name, const char **event_source_uris, int event_sources_count, struct ast_json **json, app_subscription_handler handler)
 
static int app_hash (const void *obj, const int flags)
 
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...
 
static enum stasis_app_subscribe_res app_subscribe (struct stasis_app *app, const char *uri, struct stasis_app_event_source *event_source)
 
static enum stasis_app_subscribe_res app_unsubscribe (struct stasis_app *app, const char *uri, struct stasis_app_event_source *event_source)
 
static int append_name (void *obj, void *arg, int flags)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static struct ast_bridgebridge_create_common (const char *type, const char *name, const char *id, int invisible)
 
static struct ast_channelbridge_moh_create (struct ast_bridge *bridge)
 
static int bridges_channel_compare (void *obj, void *arg, int flags)
 
static int bridges_channel_hash_fn (const void *obj, const int flags)
 
static int bridges_channel_sort_fn (const void *obj_left, const void *obj_right, const int flags)
 
static int bridges_compare (void *obj, void *arg, int flags)
 
static int bridges_hash (const void *obj, const int flags)
 
static int channel_id_sanitizer (const char *id)
 
static void channel_replaced_cb (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 
static int channel_sanitizer (const struct ast_channel *chan)
 
static int channel_snapshot_sanitizer (const struct ast_channel_snapshot *snapshot)
 
static void channel_stolen_cb (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 
static void cleanup (void)
 Clean up any old apps that we don't need any more. More...
 
static int cleanup_cb (void *obj, void *arg, int flags)
 
static int control_compare (void *obj, void *arg, int flags)
 
static int control_hash (const void *obj, const int flags)
 
static void control_unlink (struct stasis_app_control *control)
 In addition to running ao2_cleanup(), this function also removes the object from the app_controls container. More...
 
static struct stasis_appfind_app_by_name (const char *app_name)
 
static struct ast_channel_snapshotget_replace_channel_snapshot (struct ast_channel *chan)
 
static struct replace_channel_storeget_replace_channel_store (struct ast_channel *chan, int no_create)
 
static int has_masquerade_store (struct ast_channel *chan)
 
static int load_module (void)
 
static int masq_match_cb (void *obj, void *data, int flags)
 
static void * moh_channel_thread (void *data)
 
static void playback_after_bridge_cb (struct ast_channel *chan, void *data)
 
static void playback_after_bridge_cb_failed (enum ast_bridge_after_cb_reason reason, void *data)
 
static struct ast_channelprepare_bridge_moh_channel (void)
 
static void remove_bridge_playback (char *bridge_id)
 
static void remove_masquerade_store (struct ast_channel *chan)
 
static void remove_stasis_end_published (struct ast_channel *chan)
 
static void replace_channel_destroy (void *obj)
 
static int send_start_msg (struct stasis_app *app, struct ast_channel *chan, int argc, char *argv[])
 
static int send_start_msg_snapshots (struct ast_channel *chan, struct stasis_app *app, int argc, char *argv[], struct ast_channel_snapshot *snapshot, struct ast_channel_snapshot *replace_channel_snapshot)
 
static int set_internal_datastore (struct ast_channel *chan)
 
static void start_message_blob_dtor (void *obj)
 
static void stasis_app_bridge_channel_wrapper_destructor (void *obj)
 
struct ast_bridgestasis_app_bridge_create (const char *type, const char *name, const char *id)
 Create a bridge of the specified type. More...
 
struct ast_bridgestasis_app_bridge_create_invisible (const char *type, const char *name, const char *id)
 Create an invisible bridge of the specified type. More...
 
void stasis_app_bridge_destroy (const char *bridge_id)
 Destroy the bridge. More...
 
struct ast_bridgestasis_app_bridge_find_by_id (const char *bridge_id)
 Returns the bridge with the given id. More...
 
struct ast_channelstasis_app_bridge_moh_channel (struct ast_bridge *bridge)
 Finds or creates an announcer channel in a bridge that can play music on hold. More...
 
int stasis_app_bridge_moh_stop (struct ast_bridge *bridge)
 Breaks down MOH channels playing on the bridge created by stasis_app_bridge_moh_channel. More...
 
int stasis_app_bridge_playback_channel_add (struct ast_bridge *bridge, struct ast_channel *chan, struct stasis_app_control *control)
 Adds a channel to the list of ARI playback channels for bridges. More...
 
struct ast_channelstasis_app_bridge_playback_channel_find (struct ast_bridge *bridge)
 Finds an existing ARI playback channel in a bridge. More...
 
void stasis_app_bridge_playback_channel_remove (char *bridge_id, struct stasis_app_control *control)
 remove channel from list of ARI playback channels for bridges. More...
 
int stasis_app_channel_is_internal (struct ast_channel *chan)
 Is this channel internal to Stasis? More...
 
int stasis_app_channel_is_stasis_end_published (struct ast_channel *chan)
 Has this channel had a StasisEnd published on it? More...
 
int stasis_app_channel_set_internal (struct ast_channel *chan)
 Mark this channel as being internal to Stasis. More...
 
void stasis_app_channel_set_stasis_end_published (struct ast_channel *chan)
 Indicate that this channel has had a StasisEnd published for it. More...
 
int stasis_app_channel_unreal_set_internal (struct ast_channel *chan)
 Mark this unreal channel and it's other half as being internal to Stasis. More...
 
struct stasis_app_controlstasis_app_control_create (struct ast_channel *chan)
 Creates a control handler for a channel that isn't in a stasis app. More...
 
void stasis_app_control_execute_until_exhausted (struct ast_channel *chan, struct stasis_app_control *control)
 Act on a stasis app control queue until it is empty. More...
 
struct stasis_app_controlstasis_app_control_find_by_channel (const struct ast_channel *chan)
 Returns the handler for the given channel. More...
 
struct stasis_app_controlstasis_app_control_find_by_channel_id (const char *channel_id)
 Returns the handler for the channel with the given id. More...
 
void stasis_app_control_flush_queue (struct stasis_app_control *control)
 Flush the control command queue. More...
 
int stasis_app_control_is_done (struct stasis_app_control *control)
 Check if a control is marked as done. More...
 
int stasis_app_exec (struct ast_channel *chan, const char *app_name, int argc, char *argv[])
 Control a channel using stasis_app. More...
 
struct ao2_containerstasis_app_get_all (void)
 Gets the names of all registered Stasis applications. More...
 
struct stasis_appstasis_app_get_by_name (const char *name)
 Retrieve a handle to a Stasis application by its name. More...
 
struct stasis_message_sanitizerstasis_app_get_sanitizer (void)
 Get the Stasis message sanitizer for app_stasis applications. More...
 
struct ast_jsonstasis_app_object_to_json (struct stasis_app *app)
 Return the JSON representation of a Stasis application. More...
 
int stasis_app_register (const char *app_name, stasis_app_cb handler, void *data)
 Register a new Stasis application. More...
 
int stasis_app_register_all (const char *app_name, stasis_app_cb handler, void *data)
 Register a new Stasis application that receives all Asterisk events. More...
 
void stasis_app_register_event_source (struct stasis_app_event_source *obj)
 Register an application event source. More...
 
int stasis_app_send (const char *app_name, struct ast_json *message)
 Send a message to the given Stasis application. More...
 
enum stasis_app_subscribe_res stasis_app_subscribe (const char *app_name, const char **event_source_uris, int event_sources_count, struct ast_json **json)
 Subscribes an application to a list of event sources. More...
 
enum stasis_app_subscribe_res stasis_app_subscribe_channel (const char *app_name, struct ast_channel *chan)
 Directly subscribe an application to a channel. More...
 
struct ast_jsonstasis_app_to_json (const char *app_name)
 Return the JSON representation of a Stasis application. More...
 
void stasis_app_unregister (const char *app_name)
 Unregister a Stasis application. More...
 
void stasis_app_unregister_event_source (struct stasis_app_event_source *obj)
 Unregister an application event source. More...
 
enum stasis_app_subscribe_res stasis_app_unsubscribe (const char *app_name, const char **event_source_uris, int event_sources_count, struct ast_json **json)
 Unsubscribes an application from a list of event sources. More...
 
enum stasis_app_user_event_res stasis_app_user_event (const char *app_name, const char *event_name, const char **source_uris, int sources_count, struct ast_json *json_variables)
 Generate a Userevent for stasis app (echo to AMI) More...
 
static struct ast_jsonstasis_end_to_json (struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (end_message_type,.to_json=stasis_end_to_json)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (start_message_type,.to_json=stasis_start_to_json)
 
static struct ast_jsonstasis_start_to_json (struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Stasis application support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load_pri = AST_MODPRI_APP_DEPEND - 1, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, }
 
struct ao2_containerapp_bridges
 
struct ao2_containerapp_bridges_moh
 
struct ao2_containerapp_bridges_playback
 
struct ao2_containerapp_controls
 
struct stasis_message_sanitizer app_sanitizer
 
struct ao2_containerapps_registry
 Stasis application container. More...
 
static const struct ast_module_infoast_module_info = &__mod_info
 
struct event_sources event_sources = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static const struct ast_datastore_info masquerade_store_info
 
static const struct ast_datastore_info replace_channel_store_info
 
struct ast_datastore_info set_end_published_info
 
static const struct ast_datastore_info stasis_internal_channel_info
 

Detailed Description

Stasis application support.

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

res_stasis.so brings together the various components of the Stasis application infrastructure.

First, there's the Stasis application handler, stasis_app_exec(). This is called by app_stasis.so to give control of a channel to the Stasis application code from the dialplan.

While a channel is in stasis_app_exec(), it has a stasis_app_control object, which may be used to control the channel.

To control the channel, commands may be sent to channel using stasis_app_send_command() and stasis_app_send_async_command().

Alongside this, applications may be registered/unregistered using stasis_app_register()/stasis_app_unregister(). While a channel is in Stasis, events received on the channel's topic are converted to JSON and forwarded to the stasis_app_cb. The application may also subscribe to the channel to continue to receive messages even after the channel has left Stasis, but it will not be able to control it.

Given all the stuff that comes together in this module, it's been broken up into several pieces that are in res/stasis/ and compiled into res_stasis.so.

Definition in file res_stasis.c.

Macro Definition Documentation

◆ APPS_NUM_BUCKETS

#define APPS_NUM_BUCKETS   127

Number of buckets for the Stasis application hash table. Remember to keep it a prime number!

Definition at line 83 of file res_stasis.c.

Referenced by load_module().

◆ BRIDGES_NUM_BUCKETS

#define BRIDGES_NUM_BUCKETS   127

Number of buckets for the Stasis bridges hash table. Remember to keep it a prime number!

Definition at line 95 of file res_stasis.c.

Referenced by load_module().

◆ CONTROLS_NUM_BUCKETS

#define CONTROLS_NUM_BUCKETS   127

Number of buckets for the Stasis application hash table. Remember to keep it a prime number!

Definition at line 89 of file res_stasis.c.

Referenced by load_module().

◆ MAX_WAIT_MS

#define MAX_WAIT_MS   200

Time to wait for a frame in the application

Definition at line 77 of file res_stasis.c.

Referenced by stasis_app_exec().

Typedef Documentation

◆ app_subscription_handler

typedef enum stasis_app_subscribe_res(* app_subscription_handler) (struct stasis_app *app, const char *uri, struct stasis_app_event_source *event_source)

Definition at line 1922 of file res_stasis.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2379 of file res_stasis.c.

◆ __stasis_app_register()

static int __stasis_app_register ( const char *  app_name,
stasis_app_cb  handler,
void *  data,
int  all_events 
)
static

Definition at line 1726 of file res_stasis.c.

References ao2_cleanup, ao2_find, ao2_link_flags, ao2_lock, ao2_unlock, app, app_create(), app_update(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, cleanup(), stasis_app_event_source::next, NULL, OBJ_NOLOCK, OBJ_SEARCH_KEY, RAII_VAR, STASIS_APP_SUBSCRIBE_ALL, STASIS_APP_SUBSCRIBE_MANUAL, and stasis_app_event_source::subscribe.

Referenced by stasis_app_register(), and stasis_app_register_all().

1727 {
1728  RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
1729 
1730  if (!apps_registry) {
1731  return -1;
1732  }
1733 
1736  if (app) {
1737  /*
1738  * We need to unlock the apps_registry before calling app_update to
1739  * prevent the possibility of a deadlock with the session.
1740  */
1742  app_update(app, handler, data);
1743  cleanup();
1744  return 0;
1745  }
1746 
1748  if (!app) {
1750  return -1;
1751  }
1752 
1753  if (all_events) {
1754  struct stasis_app_event_source *source;
1755 
1757  AST_LIST_TRAVERSE(&event_sources, source, next) {
1758  if (!source->subscribe) {
1759  continue;
1760  }
1761 
1762  source->subscribe(app, NULL);
1763  }
1765  }
1767 
1769 
1770  /* We lazily clean up the apps_registry, because it's good enough to
1771  * prevent memory leaks, and we're lazy.
1772  */
1773  cleanup();
1774  return 0;
1775 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
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
#define NULL
Definition: resample.c:96
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
static void cleanup(void)
Clean up any old apps that we don't need any more.
Definition: res_stasis.c:327
#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
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.
Event source information and callbacks.
Definition: stasis_app.h:174
#define ao2_lock(a)
Definition: astobj2.h:718
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
void app_update(struct stasis_app *app, stasis_app_cb handler, void *data)
Update the handler and data for a res_stasis application.
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
struct stasis_app_event_source * next
Definition: stasis_app.h:227
static const char app[]
Definition: app_mysql.c:62
int(* subscribe)(struct stasis_app *app, void *obj)
Subscribe an application to an event source.
Definition: stasis_app.h:196

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2379 of file res_stasis.c.

◆ add_masquerade_store()

static int add_masquerade_store ( struct ast_channel chan)
static

Definition at line 1217 of file res_stasis.c.

References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, lock, NULL, and SCOPED_CHANNELLOCK.

Referenced by stasis_app_exec().

1218 {
1219  struct ast_datastore *datastore;
1220 
1221  SCOPED_CHANNELLOCK(lock, chan);
1223  return 0;
1224  }
1225 
1227  if (!datastore) {
1228  return -1;
1229  }
1230 
1231  ast_channel_datastore_add(chan, datastore);
1232 
1233  return 0;
1234 }
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
ast_mutex_t lock
Definition: app_meetme.c:1091
static const struct ast_datastore_info masquerade_store_info
Definition: res_stasis.c:1205
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ app_compare()

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

AO2 comparison function for app

Definition at line 208 of file res_stasis.c.

References CMP_MATCH, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, and stasis_app_name().

Referenced by load_module().

209 {
210  const struct stasis_app *object_left = obj;
211  const struct stasis_app *object_right = arg;
212  const char *right_key = arg;
213  int cmp;
214 
215  switch (flags & OBJ_SEARCH_MASK) {
216  case OBJ_SEARCH_OBJECT:
217  right_key = stasis_app_name(object_right);
218  /* Fall through */
219  case OBJ_SEARCH_KEY:
220  cmp = strcmp(stasis_app_name(object_left), right_key);
221  break;
223  /*
224  * We could also use a partial key struct containing a length
225  * so strlen() does not get called for every comparison instead.
226  */
227  cmp = strncmp(stasis_app_name(object_left), right_key, strlen(right_key));
228  break;
229  default:
230  /*
231  * What arg points to is specific to this traversal callback
232  * and has no special meaning to astobj2.
233  */
234  cmp = 0;
235  break;
236  }
237  if (cmp) {
238  return 0;
239  }
240  /*
241  * At this point the traversal callback is identical to a sorted
242  * container.
243  */
244  return CMP_MATCH;
245 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application's name.
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ app_event_source_find()

static struct stasis_app_event_source* app_event_source_find ( const char *  uri)
static

Definition at line 1897 of file res_stasis.c.

References ast_begins_with(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, stasis_app_event_source::next, and stasis_app_event_source::scheme.

Referenced by app_handle_subscriptions().

1898 {
1899  struct stasis_app_event_source *source;
1900 
1902  AST_LIST_TRAVERSE(&event_sources, source, next) {
1903  if (ast_begins_with(uri, source->scheme)) {
1904  break;
1905  }
1906  }
1908 
1909  return source;
1910 }
const char * scheme
The scheme to match against on [un]subscribes.
Definition: stasis_app.h:176
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
Event source information and callbacks.
Definition: stasis_app.h:174
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct stasis_app_event_source * next
Definition: stasis_app.h:227
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Definition: strings.h:94

◆ app_event_sources_to_json()

static struct ast_json* app_event_sources_to_json ( const struct stasis_app app,
struct ast_json json 
)
static

Definition at line 1850 of file res_stasis.c.

References AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, stasis_app_event_source::next, and stasis_app_event_source::to_json.

Referenced by stasis_app_object_to_json().

1852 {
1853  struct stasis_app_event_source *source;
1854 
1856  AST_LIST_TRAVERSE(&event_sources, source, next) {
1857  if (source->to_json) {
1858  source->to_json(app, json);
1859  }
1860  }
1862 
1863  return json;
1864 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
void(* to_json)(const struct stasis_app *app, struct ast_json *json)
Convert event source data to json.
Definition: stasis_app.h:224
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
Event source information and callbacks.
Definition: stasis_app.h:174
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct stasis_app_event_source * next
Definition: stasis_app.h:227

◆ 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_handle_subscriptions()

static enum stasis_app_subscribe_res app_handle_subscriptions ( const char *  app_name,
const char **  event_source_uris,
int  event_sources_count,
struct ast_json **  json,
app_subscription_handler  handler 
)
static

Definition at line 1939 of file res_stasis.c.

References ao2_ref, app_event_source_find(), ast_assert, ast_debug, ast_log, find_app_by_name(), handler(), LOG_WARNING, NULL, stasis_app_object_to_json(), STASIS_ASR_APP_NOT_FOUND, STASIS_ASR_EVENT_SOURCE_BAD_SCHEME, and STASIS_ASR_OK.

Referenced by stasis_app_subscribe(), and stasis_app_unsubscribe().

1943 {
1945  int i;
1946 
1947  ast_assert(handler != NULL);
1948 
1949  if (!app) {
1950  return STASIS_ASR_APP_NOT_FOUND;
1951  }
1952 
1953  for (i = 0; i < event_sources_count; ++i) {
1954  const char *uri = event_source_uris[i];
1955  struct stasis_app_event_source *event_source;
1956  enum stasis_app_subscribe_res res;
1957 
1958  event_source = app_event_source_find(uri);
1959  if (!event_source) {
1960  ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);
1961  ao2_ref(app, -1);
1962 
1964  }
1965 
1966  res = handler(app, uri, event_source);
1967  if (res != STASIS_ASR_OK) {
1968  ao2_ref(app, -1);
1969 
1970  return res;
1971  }
1972  }
1973 
1974  if (json) {
1975  ast_debug(3, "%s: Successful; setting results\n", app_name);
1976  *json = stasis_app_object_to_json(app);
1977  }
1978 
1979  ao2_ref(app, -1);
1980 
1981  return STASIS_ASR_OK;
1982 }
struct ast_json * stasis_app_object_to_json(struct stasis_app *app)
Return the JSON representation of a Stasis application.
Definition: res_stasis.c:1866
static struct stasis_app_event_source * app_event_source_find(const char *uri)
Definition: res_stasis.c:1897
#define LOG_WARNING
Definition: logger.h:274
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
Event source information and callbacks.
Definition: stasis_app.h:174
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
stasis_app_subscribe_res
Return code for stasis_app_[un]subscribe.
Definition: stasis_app.h:282
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 struct stasis_app * find_app_by_name(const char *app_name)
Definition: res_stasis.c:1679
static const char app[]
Definition: app_mysql.c:62

◆ app_hash()

static int app_hash ( const void *  obj,
const int  flags 
)
static

AO2 hash function for app

Definition at line 186 of file res_stasis.c.

References app, ast_assert, ast_str_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and stasis_app_name().

Referenced by load_module().

187 {
188  const struct stasis_app *app;
189  const char *key;
190 
191  switch (flags & OBJ_SEARCH_MASK) {
192  case OBJ_SEARCH_KEY:
193  key = obj;
194  break;
195  case OBJ_SEARCH_OBJECT:
196  app = obj;
197  key = stasis_app_name(app);
198  break;
199  default:
200  /* Hash can only work on something with a full key. */
201  ast_assert(0);
202  return 0;
203  }
204  return ast_str_hash(key);
205 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
static const char app[]
Definition: app_mysql.c:62
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ 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_subscribe()

static enum stasis_app_subscribe_res app_subscribe ( struct stasis_app app,
const char *  uri,
struct stasis_app_event_source event_source 
)
static

Definition at line 2019 of file res_stasis.c.

References ao2_cleanup, app_name(), ast_debug, ast_log, ast_strlen_zero, stasis_app_event_source::find, LOG_WARNING, NULL, RAII_VAR, stasis_app_event_source::scheme, stasis_app_name(), STASIS_ASR_EVENT_SOURCE_NOT_FOUND, STASIS_ASR_INTERNAL_ERROR, STASIS_ASR_OK, and stasis_app_event_source::subscribe.

Referenced by stasis_app_subscribe().

2022 {
2023  const char *app_name = stasis_app_name(app);
2024  RAII_VAR(void *, obj, NULL, ao2_cleanup);
2025 
2026  ast_debug(3, "%s: Checking %s\n", app_name, uri);
2027 
2028  if (!ast_strlen_zero(uri + strlen(event_source->scheme)) &&
2029  (!event_source->find || (!(obj = event_source->find(app, uri + strlen(event_source->scheme)))))) {
2030  ast_log(LOG_WARNING, "Event source not found: %s\n", uri);
2032  }
2033 
2034  ast_debug(3, "%s: Subscribing to %s\n", app_name, uri);
2035 
2036  if (!event_source->subscribe || (event_source->subscribe(app, obj))) {
2037  ast_log(LOG_WARNING, "Error subscribing app '%s' to '%s'\n",
2038  app_name, uri);
2040  }
2041 
2042  return STASIS_ASR_OK;
2043 }
void *(* find)(const struct stasis_app *app, const char *id)
Find an event source data object by the given id/name.
Definition: stasis_app.h:186
const char * scheme
The scheme to match against on [un]subscribes.
Definition: stasis_app.h:176
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#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
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int(* subscribe)(struct stasis_app *app, void *obj)
Subscribe an application to an event source.
Definition: stasis_app.h:196

◆ app_unsubscribe()

static enum stasis_app_subscribe_res app_unsubscribe ( struct stasis_app app,
const char *  uri,
struct stasis_app_event_source event_source 
)
static

Definition at line 2064 of file res_stasis.c.

References app_name(), ast_debug, ast_log, stasis_app_event_source::is_subscribed, LOG_WARNING, stasis_app_event_source::scheme, stasis_app_name(), STASIS_ASR_EVENT_SOURCE_NOT_FOUND, and stasis_app_event_source::unsubscribe.

Referenced by stasis_app_unsubscribe().

2067 {
2068  const char *app_name = stasis_app_name(app);
2069  const char *id = uri + strlen(event_source->scheme);
2070 
2071  if (!event_source->is_subscribed ||
2072  (!event_source->is_subscribed(app, id))) {
2074  }
2075 
2076  ast_debug(3, "%s: Unsubscribing from %s\n", app_name, uri);
2077 
2078  if (!event_source->unsubscribe || (event_source->unsubscribe(app, id))) {
2079  ast_log(LOG_WARNING, "Error unsubscribing app '%s' to '%s'\n",
2080  app_name, uri);
2081  return -1;
2082  }
2083  return 0;
2084 }
const char * scheme
The scheme to match against on [un]subscribes.
Definition: stasis_app.h:176
#define LOG_WARNING
Definition: logger.h:274
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int(* unsubscribe)(struct stasis_app *app, const char *id)
Cancel the subscription an app has to an event source.
Definition: stasis_app.h:206
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
int(* is_subscribed)(struct stasis_app *app, const char *id)
Find an event source by the given id/name.
Definition: stasis_app.h:216

◆ append_name()

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

Definition at line 1699 of file res_stasis.c.

References app, ast_str_container_add(), and stasis_app_name().

Referenced by stasis_app_get_all().

1700 {
1701  struct stasis_app *app = obj;
1702  struct ao2_container *apps = arg;
1703 
1705  return 0;
1706 }
Registered applications container.
Definition: pbx_app.c:67
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
Generic container type.
static const char app[]
Definition: app_mysql.c:62
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
Definition: strings.c:206

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 2379 of file res_stasis.c.

◆ bridge_create_common()

static struct ast_bridge* bridge_create_common ( const char *  type,
const char *  name,
const char *  id,
int  invisible 
)
static

Definition at line 795 of file res_stasis.c.

References ao2_link, AST_BRIDGE_CAPABILITY_HOLDING, AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_CAPABILITY_NATIVE, ast_bridge_destroy(), AST_BRIDGE_FLAG_INVISIBLE, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO, AST_BRIDGE_FLAG_SMART, AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM, AST_BRIDGE_FLAG_SWAP_INHIBIT_TO, AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY, AST_BRIDGE_VIDEO_MODE_SFU, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_strdupa, ast_strip(), bridge_stasis_new(), NULL, S_OR, STASIS_BRIDGE_MIXING_CAPABILITIES, and strsep().

Referenced by stasis_app_bridge_create(), and stasis_app_bridge_create_invisible().

796 {
797  struct ast_bridge *bridge;
798  char *requested_type, *requested_types = ast_strdupa(S_OR(type, "mixing"));
799  int capabilities = 0;
804 
805  if (invisible) {
806  flags |= AST_BRIDGE_FLAG_INVISIBLE;
807  }
808 
809  while ((requested_type = strsep(&requested_types, ","))) {
810  requested_type = ast_strip(requested_type);
811 
812  if (!strcmp(requested_type, "mixing")) {
813  capabilities |= STASIS_BRIDGE_MIXING_CAPABILITIES;
814  flags |= AST_BRIDGE_FLAG_SMART;
815  } else if (!strcmp(requested_type, "holding")) {
816  capabilities |= AST_BRIDGE_CAPABILITY_HOLDING;
817  } else if (!strcmp(requested_type, "dtmf_events") ||
818  !strcmp(requested_type, "proxy_media")) {
819  capabilities &= ~AST_BRIDGE_CAPABILITY_NATIVE;
820  } else if (!strcmp(requested_type, "video_sfu")) {
821  video_mode = AST_BRIDGE_VIDEO_MODE_SFU;
822  } else if (!strcmp(requested_type, "video_single")) {
824  }
825  }
826 
827  /* For an SFU video bridge we ensure it always remains in multimix for the best experience. */
828  if (video_mode == AST_BRIDGE_VIDEO_MODE_SFU) {
829  capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
830  flags &= ~AST_BRIDGE_FLAG_SMART;
831  }
832 
833  if (!capabilities
834  /* Holding and mixing capabilities don't mix. */
835  || ((capabilities & AST_BRIDGE_CAPABILITY_HOLDING)
836  && (capabilities & (STASIS_BRIDGE_MIXING_CAPABILITIES)))) {
837  return NULL;
838  }
839 
840  bridge = bridge_stasis_new(capabilities, flags, name, id, video_mode);
841  if (bridge) {
842  if (!ao2_link(app_bridges, bridge)) {
843  ast_bridge_destroy(bridge, 0);
844  bridge = NULL;
845  }
846  }
847 
848  return bridge;
849 }
static const char type[]
Definition: chan_ooh323.c:109
ast_bridge_video_mode_type
Video source modes.
Definition: bridge.h:98
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
#define NULL
Definition: resample.c:96
struct ao2_container * app_bridges
Definition: res_stasis.c:104
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
Structure that contains information about a bridge.
Definition: bridge.h:357
#define STASIS_BRIDGE_MIXING_CAPABILITIES
Definition: stasis_bridge.h:39
static const char name[]
Definition: cdr_mysql.c:74
char * strsep(char **str, const char *delims)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_bridge * bridge_stasis_new(uint32_t capabilities, unsigned int flags, const char *name, const char *id, enum ast_bridge_video_mode_type video_mode)
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ bridge_moh_create()

static struct ast_channel* bridge_moh_create ( struct ast_bridge bridge)
static

Definition at line 574 of file res_stasis.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_link_flags, ao2_ref, ao2_unlink_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE, AST_BRIDGE_CHANNEL_FLAG_LONELY, AST_CHANNEL_NAME, ast_channel_uniqueid(), ast_hangup(), ast_log, ast_pthread_create_detached, ast_string_field_init, ast_string_field_set, ast_unreal_channel_push_to_bridge(), AST_UUID_STR_LEN, LOG_ERROR, moh_channel_thread(), NULL, OBJ_NOLOCK, prepare_bridge_moh_channel(), stasis_app_bridge_channel_wrapper_destructor(), stasis_app_channel_unreal_set_internal(), and ast_bridge::uniqueid.

Referenced by stasis_app_bridge_moh_channel().

575 {
576  struct stasis_app_bridge_channel_wrapper *new_wrapper;
577  struct ast_channel *chan;
578  pthread_t threadid;
579 
581  if (!chan) {
582  return NULL;
583  }
584 
586  ast_hangup(chan);
587  return NULL;
588  }
589 
590  if (ast_unreal_channel_push_to_bridge(chan, bridge,
592  ast_hangup(chan);
593  return NULL;
594  }
595 
596  new_wrapper = ao2_alloc_options(sizeof(*new_wrapper),
598  if (!new_wrapper) {
599  ast_hangup(chan);
600  return NULL;
601  }
602 
604  || ast_string_field_set(new_wrapper, bridge_id, bridge->uniqueid)
605  || ast_string_field_set(new_wrapper, channel_id, ast_channel_uniqueid(chan))) {
606  ao2_ref(new_wrapper, -1);
607  ast_hangup(chan);
608  return NULL;
609  }
610 
611  if (!ao2_link_flags(app_bridges_moh, new_wrapper, OBJ_NOLOCK)) {
612  ao2_ref(new_wrapper, -1);
613  ast_hangup(chan);
614  return NULL;
615  }
616 
617  /* Pass the new_wrapper ref to moh_channel_thread() */
618  if (ast_pthread_create_detached(&threadid, NULL, moh_channel_thread, new_wrapper)) {
619  ast_log(LOG_ERROR, "Failed to create channel thread. Abandoning MOH channel creation.\n");
621  ao2_ref(new_wrapper, -1);
622  ast_hangup(chan);
623  return NULL;
624  }
625 
626  return chan;
627 }
Main Channel structure associated with a channel.
const ast_string_field uniqueid
Definition: bridge.h:409
#define AST_UUID_STR_LEN
Definition: uuid.h:27
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
struct ao2_container * app_bridges_moh
Definition: res_stasis.c:106
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags)
Push the semi2 unreal channel into a bridge from either member of the unreal pair.
Definition: core_unreal.c:928
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define LOG_ERROR
Definition: logger.h:285
int stasis_app_channel_unreal_set_internal(struct ast_channel *chan)
Mark this unreal channel and it&#39;s other half as being internal to Stasis.
Definition: res_stasis.c:2288
#define AST_CHANNEL_NAME
Definition: channel.h:172
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622
static struct ast_channel * prepare_bridge_moh_channel(void)
Definition: res_stasis.c:510
static void stasis_app_bridge_channel_wrapper_destructor(void *obj)
Definition: res_stasis.c:455
static void * moh_channel_thread(void *data)
Definition: res_stasis.c:529
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ bridges_channel_compare()

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

AO2 comparison function for bridges moh container

Definition at line 429 of file res_stasis.c.

References stasis_app_bridge_channel_wrapper::bridge_id, CMP_MATCH, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by load_module().

430 {
431  const struct stasis_app_bridge_channel_wrapper *object_left = obj;
432  const struct stasis_app_bridge_channel_wrapper *object_right = arg;
433  const char *right_key = arg;
434  int cmp;
435 
436  switch (flags & OBJ_SEARCH_MASK) {
437  case OBJ_SEARCH_OBJECT:
438  right_key = object_right->bridge_id;
439  case OBJ_SEARCH_KEY:
440  cmp = strcmp(object_left->bridge_id, right_key);
441  break;
443  cmp = strncmp(object_left->bridge_id, right_key, strlen(right_key));
444  break;
445  default:
446  cmp = 0;
447  break;
448  }
449  if (cmp) {
450  return 0;
451  }
452  return CMP_MATCH;
453 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const ast_string_field bridge_id
Definition: res_stasis.c:425
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ bridges_channel_hash_fn()

static int bridges_channel_hash_fn ( const void *  obj,
const int  flags 
)
static

AO2 hash function for the bridges moh container

Definition at line 462 of file res_stasis.c.

References ast_assert, ast_str_hash(), stasis_app_bridge_channel_wrapper::bridge_id, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by load_module().

463 {
464  const struct stasis_app_bridge_channel_wrapper *wrapper;
465  const char *key;
466 
467  switch (flags & OBJ_SEARCH_MASK) {
468  case OBJ_SEARCH_KEY:
469  key = obj;
470  break;
471  case OBJ_SEARCH_OBJECT:
472  wrapper = obj;
473  key = wrapper->bridge_id;
474  break;
475  default:
476  /* Hash can only work on something with a full key. */
477  ast_assert(0);
478  return 0;
479  }
480  return ast_str_hash(key);
481 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
const ast_string_field bridge_id
Definition: res_stasis.c:425
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ bridges_channel_sort_fn()

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

Definition at line 483 of file res_stasis.c.

References ast_assert, stasis_app_bridge_channel_wrapper::bridge_id, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by load_module().

484 {
485  const struct stasis_app_bridge_channel_wrapper *left = obj_left;
486  const struct stasis_app_bridge_channel_wrapper *right = obj_right;
487  const char *right_key = obj_right;
488  int cmp;
489 
490  switch (flags & OBJ_SEARCH_MASK) {
491  case OBJ_SEARCH_OBJECT:
492  right_key = right->bridge_id;
493  /* Fall through */
494  case OBJ_SEARCH_KEY:
495  cmp = strcmp(left->bridge_id, right_key);
496  break;
498  cmp = strncmp(left->bridge_id, right_key, strlen(right_key));
499  break;
500  default:
501  /* Sort can only work on something with a full or partial key. */
502  ast_assert(0);
503  cmp = 0;
504  break;
505  }
506  return cmp;
507 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
const ast_string_field bridge_id
Definition: res_stasis.c:425
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ bridges_compare()

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

AO2 comparison function for bridges container

Definition at line 378 of file res_stasis.c.

References CMP_MATCH, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, and ast_bridge::uniqueid.

Referenced by load_module().

379 {
380  const struct ast_bridge *object_left = obj;
381  const struct ast_bridge *object_right = arg;
382  const char *right_key = arg;
383  int cmp;
384 
385  switch (flags & OBJ_SEARCH_MASK) {
386  case OBJ_SEARCH_OBJECT:
387  right_key = object_right->uniqueid;
388  /* Fall through */
389  case OBJ_SEARCH_KEY:
390  cmp = strcmp(object_left->uniqueid, right_key);
391  break;
393  /*
394  * We could also use a partial key struct containing a length
395  * so strlen() does not get called for every comparison instead.
396  */
397  cmp = strncmp(object_left->uniqueid, right_key, strlen(right_key));
398  break;
399  default:
400  /*
401  * What arg points to is specific to this traversal callback
402  * and has no special meaning to astobj2.
403  */
404  cmp = 0;
405  break;
406  }
407  if (cmp) {
408  return 0;
409  }
410  /*
411  * At this point the traversal callback is identical to a sorted
412  * container.
413  */
414  return CMP_MATCH;
415 }
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
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
Structure that contains information about a bridge.
Definition: bridge.h:357
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ bridges_hash()

static int bridges_hash ( const void *  obj,
const int  flags 
)
static

AO2 hash function for bridges container

Definition at line 356 of file res_stasis.c.

References ast_assert, ast_str_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and ast_bridge::uniqueid.

Referenced by load_module().

357 {
358  const struct ast_bridge *bridge;
359  const char *key;
360 
361  switch (flags & OBJ_SEARCH_MASK) {
362  case OBJ_SEARCH_KEY:
363  key = obj;
364  break;
365  case OBJ_SEARCH_OBJECT:
366  bridge = obj;
367  key = bridge->uniqueid;
368  break;
369  default:
370  /* Hash can only work on something with a full key. */
371  ast_assert(0);
372  return 0;
373  }
374  return ast_str_hash(key);
375 }
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
#define ast_assert(a)
Definition: utils.h:695
Structure that contains information about a bridge.
Definition: bridge.h:357
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ channel_id_sanitizer()

static int channel_id_sanitizer ( const char *  id)
static

Definition at line 2245 of file res_stasis.c.

References ao2_cleanup, ast_channel_snapshot_get_latest(), and channel_snapshot_sanitizer().

2246 {
2247  struct ast_channel_snapshot *snapshot;
2248  int ret;
2249 
2250  snapshot = ast_channel_snapshot_get_latest(id);
2251  ret = channel_snapshot_sanitizer(snapshot);
2252  ao2_cleanup(snapshot);
2253 
2254  return ret;
2255 }
static int channel_snapshot_sanitizer(const struct ast_channel_snapshot *snapshot)
Definition: res_stasis.c:2227
Structure representing a snapshot of channel state.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ channel_replaced_cb()

static void channel_replaced_cb ( void *  data,
struct ast_channel old_chan,
struct ast_channel new_chan 
)
static

Definition at line 1159 of file res_stasis.c.

References ao2_callback, ao2_cleanup, ao2_link, app_send_end_msg(), ast_channel_snapshot_get_latest(), ast_channel_uniqueid(), ast_log, control_app(), LOG_ERROR, masq_match_cb(), NULL, OBJ_UNLINK, RAII_VAR, and send_start_msg_snapshots().

1160 {
1161  RAII_VAR(struct ast_channel_snapshot *, new_snapshot, NULL, ao2_cleanup);
1162  RAII_VAR(struct ast_channel_snapshot *, old_snapshot, NULL, ao2_cleanup);
1163  struct stasis_app_control *control;
1164 
1165  /* At this point, new_chan is the channel pointer that is in Stasis() and
1166  * has the unknown channel's name in it while old_chan is the channel pointer
1167  * that is not in Stasis(), but has the guts of the channel that Stasis() knows
1168  * about */
1169 
1170  /* grab a snapshot for the channel that is jumping into Stasis() */
1171  new_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(new_chan));
1172  if (!new_snapshot) {
1173  ast_log(LOG_ERROR, "Could not get snapshot for masquerading channel\n");
1174  return;
1175  }
1176 
1177  /* grab a snapshot for the channel that has been kicked out of Stasis() */
1178  old_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(old_chan));
1179  if (!old_snapshot) {
1180  ast_log(LOG_ERROR, "Could not get snapshot for masqueraded channel\n");
1181  return;
1182  }
1183 
1184  /*
1185  * Find, unlink, and relink control since the channel has a new
1186  * name/uniqueid and its hash has changed.
1187  */
1188  control = ao2_callback(app_controls, OBJ_UNLINK, masq_match_cb, new_chan);
1189  if (!control) {
1190  ast_log(LOG_ERROR, "Could not find control for masquerading channel\n");
1191  return;
1192  }
1193  ao2_link(app_controls, control);
1194 
1195 
1196  /* send the StasisStart with replace_channel to the app */
1197  send_start_msg_snapshots(new_chan, control_app(control), 0, NULL, new_snapshot,
1198  old_snapshot);
1199  /* send the StasisEnd message to the app */
1200  app_send_end_msg(control_app(control), old_chan);
1201 
1202  ao2_cleanup(control);
1203 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
Structure representing a snapshot of channel state.
#define NULL
Definition: resample.c:96
struct stasis_app * control_app(struct stasis_app_control *control)
Returns the pointer (non-reffed) to the app associated with this control.
Definition: control.c:1563
struct ao2_container * app_controls
Definition: res_stasis.c:102
int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
Send StasisEnd message to the listening app.
Definition: res_stasis.c:1083
static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app *app, int argc, char *argv[], struct ast_channel_snapshot *snapshot, struct ast_channel_snapshot *replace_channel_snapshot)
Definition: res_stasis.c:991
#define ast_log
Definition: astobj2.c:42
#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
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define LOG_ERROR
Definition: logger.h:285
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int masq_match_cb(void *obj, void *data, int flags)
Definition: res_stasis.c:1115
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ channel_sanitizer()

static int channel_sanitizer ( const struct ast_channel chan)
static

Definition at line 2236 of file res_stasis.c.

References AST_CHAN_TP_INTERNAL, and ast_channel_tech().

2237 {
2238  if (!chan || !(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)) {
2239  return 0;
2240  }
2241  return 1;
2242 }
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:972
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)

◆ channel_snapshot_sanitizer()

static int channel_snapshot_sanitizer ( const struct ast_channel_snapshot snapshot)
static

Definition at line 2227 of file res_stasis.c.

References AST_CHAN_TP_INTERNAL, ast_channel_snapshot::base, and ast_channel_snapshot_base::tech_properties.

Referenced by channel_id_sanitizer().

2228 {
2229  if (!snapshot || !(snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL)) {
2230  return 0;
2231  }
2232  return 1;
2233 }
struct ast_channel_snapshot_base * base
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:972

◆ channel_stolen_cb()

static void channel_stolen_cb ( void *  data,
struct ast_channel old_chan,
struct ast_channel new_chan 
)
static

Definition at line 1128 of file res_stasis.c.

References ao2_callback, ao2_cleanup, app_send_end_msg(), ast_log, control_app(), LOG_ERROR, masq_match_cb(), OBJ_UNLINK, remove_masquerade_store(), and stasis_app_channel_set_stasis_end_published().

1129 {
1130  struct stasis_app_control *control;
1131 
1132  /*
1133  * At this point, old_chan is the channel pointer that is in Stasis() and
1134  * has the unknown channel's name in it while new_chan is the channel pointer
1135  * that is not in Stasis(), but has the guts of the channel that Stasis() knows
1136  * about.
1137  *
1138  * Find and unlink control since the channel has a new name/uniqueid
1139  * and its hash has changed. Since the channel is leaving stasis don't
1140  * bother putting it back into the container. Nobody is going to
1141  * remove it from the container later.
1142  */
1143  control = ao2_callback(app_controls, OBJ_UNLINK, masq_match_cb, old_chan);
1144  if (!control) {
1145  ast_log(LOG_ERROR, "Could not find control for masqueraded channel\n");
1146  return;
1147  }
1148 
1149  /* send the StasisEnd message to the app */
1151  app_send_end_msg(control_app(control), new_chan);
1152 
1153  /* remove the datastore */
1154  remove_masquerade_store(old_chan);
1155 
1156  ao2_cleanup(control);
1157 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static void remove_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1236
struct stasis_app * control_app(struct stasis_app_control *control)
Returns the pointer (non-reffed) to the app associated with this control.
Definition: control.c:1563
struct ao2_container * app_controls
Definition: res_stasis.c:102
int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
Send StasisEnd message to the listening app.
Definition: res_stasis.c:1083
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
void stasis_app_channel_set_stasis_end_published(struct ast_channel *chan)
Indicate that this channel has had a StasisEnd published for it.
Definition: res_stasis.c:1287
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int masq_match_cb(void *obj, void *data, int flags)
Definition: res_stasis.c:1115

◆ cleanup()

static void cleanup ( void  )
static

Clean up any old apps that we don't need any more.

Definition at line 327 of file res_stasis.c.

References ao2_callback, cleanup_cb(), NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by __stasis_app_register(), stasis_app_exec(), stasis_app_unregister(), and unload_module().

328 {
330  cleanup_cb, NULL);
331 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define NULL
Definition: resample.c:96
static int cleanup_cb(void *obj, void *arg, int flags)
Definition: res_stasis.c:309
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100

◆ cleanup_cb()

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

Definition at line 309 of file res_stasis.c.

References app, app_is_finished(), app_shutdown(), ast_verb, CMP_MATCH, and stasis_app_name().

Referenced by ast_sched_clean_by_callback(), and cleanup().

310 {
311  struct stasis_app *app = obj;
312 
313  if (!app_is_finished(app)) {
314  return 0;
315  }
316 
317  ast_verb(1, "Shutting down application '%s'\n", stasis_app_name(app));
318  app_shutdown(app);
319 
320  return CMP_MATCH;
321 
322 }
void app_shutdown(struct stasis_app *app)
Tears down an application.
#define ast_verb(level,...)
Definition: logger.h:463
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
int app_is_finished(struct stasis_app *app)
Checks whether a deactivated app has no channels.
static const char app[]
Definition: app_mysql.c:62

◆ control_compare()

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

AO2 comparison function for stasis_app_control

Definition at line 270 of file res_stasis.c.

References CMP_MATCH, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, and stasis_app_control_get_channel_id().

Referenced by load_module().

271 {
272  const struct stasis_app_control *object_left = obj;
273  const struct stasis_app_control *object_right = arg;
274  const char *right_key = arg;
275  int cmp;
276 
277  switch (flags & OBJ_SEARCH_MASK) {
278  case OBJ_SEARCH_OBJECT:
279  right_key = stasis_app_control_get_channel_id(object_right);
280  /* Fall through */
281  case OBJ_SEARCH_KEY:
282  cmp = strcmp(stasis_app_control_get_channel_id(object_left), right_key);
283  break;
285  /*
286  * We could also use a partial key struct containing a length
287  * so strlen() does not get called for every comparison instead.
288  */
289  cmp = strncmp(stasis_app_control_get_channel_id(object_left), right_key, strlen(right_key));
290  break;
291  default:
292  /*
293  * What arg points to is specific to this traversal callback
294  * and has no special meaning to astobj2.
295  */
296  cmp = 0;
297  break;
298  }
299  if (cmp) {
300  return 0;
301  }
302  /*
303  * At this point the traversal callback is identical to a sorted
304  * container.
305  */
306  return CMP_MATCH;
307 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
const char * stasis_app_control_get_channel_id(const struct stasis_app_control *control)
Returns the uniqueid of the channel associated with this control.
Definition: control.c:1430
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ control_hash()

static int control_hash ( const void *  obj,
const int  flags 
)
static

AO2 hash function for stasis_app_control

Definition at line 248 of file res_stasis.c.

References ast_assert, ast_str_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and stasis_app_control_get_channel_id().

Referenced by load_module().

249 {
250  const struct stasis_app_control *control;
251  const char *key;
252 
253  switch (flags & OBJ_SEARCH_MASK) {
254  case OBJ_SEARCH_KEY:
255  key = obj;
256  break;
257  case OBJ_SEARCH_OBJECT:
258  control = obj;
259  key = stasis_app_control_get_channel_id(control);
260  break;
261  default:
262  /* Hash can only work on something with a full key. */
263  ast_assert(0);
264  return 0;
265  }
266  return ast_str_hash(key);
267 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
const char * stasis_app_control_get_channel_id(const struct stasis_app_control *control)
Returns the uniqueid of the channel associated with this control.
Definition: control.c:1430
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ control_unlink()

static void control_unlink ( struct stasis_app_control control)
static

In addition to running ao2_cleanup(), this function also removes the object from the app_controls container.

Definition at line 785 of file res_stasis.c.

References ao2_cleanup, and ao2_unlink.

Referenced by stasis_app_exec().

786 {
787  if (!control) {
788  return;
789  }
790 
791  ao2_unlink(app_controls, control);
792  ao2_cleanup(control);
793 }
struct ao2_container * app_controls
Definition: res_stasis.c:102
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ find_app_by_name()

static struct stasis_app* find_app_by_name ( const char *  app_name)
static

Definition at line 1679 of file res_stasis.c.

References ao2_find, ast_strlen_zero, NULL, and OBJ_SEARCH_KEY.

Referenced by app_handle_subscriptions(), stasis_app_get_by_name(), stasis_app_subscribe_channel(), stasis_app_to_json(), and stasis_app_user_event().

1680 {
1681  struct stasis_app *res = NULL;
1682 
1683  if (!apps_registry) {
1684  return NULL;
1685  }
1686 
1687  if (!ast_strlen_zero(app_name)) {
1689  }
1690 
1691  return res;
1692 }
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
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100

◆ get_replace_channel_snapshot()

static struct ast_channel_snapshot* get_replace_channel_snapshot ( struct ast_channel chan)
static

Definition at line 952 of file res_stasis.c.

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

Referenced by send_start_msg().

953 {
955  struct ast_channel_snapshot *replace_channel_snapshot;
956 
957  if (!replace) {
958  return NULL;
959  }
960 
961  replace_channel_snapshot = replace->snapshot;
962  replace->snapshot = NULL;
963 
964  return replace_channel_snapshot;
965 }
struct ast_channel_snapshot * snapshot
Definition: res_stasis.c:872
Structure representing a snapshot of channel state.
#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

◆ get_replace_channel_store()

static struct replace_channel_store* get_replace_channel_store ( struct ast_channel chan,
int  no_create 
)
static

Definition at line 890 of file res_stasis.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore::data, and NULL.

Referenced by app_get_replace_channel_app(), app_set_replace_channel_app(), app_set_replace_channel_snapshot(), and get_replace_channel_snapshot().

891 {
892  struct ast_datastore *datastore;
893  struct replace_channel_store *ret;
894 
895  ast_channel_lock(chan);
897  if (!datastore && !no_create) {
899  if (datastore) {
900  ast_channel_datastore_add(chan, datastore);
901  }
902  }
903 
904  if (!datastore) {
905  ast_channel_unlock(chan);
906  return NULL;
907  }
908 
909  if (!datastore->data) {
910  datastore->data = ast_calloc(1, sizeof(struct replace_channel_store));
911  }
912 
913  ret = datastore->data;
914  ast_channel_unlock(chan);
915 
916  return ret;
917 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
static const struct ast_datastore_info replace_channel_store_info
Definition: res_stasis.c:885
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void * data
Definition: datastore.h:70
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ has_masquerade_store()

static int has_masquerade_store ( struct ast_channel chan)
static

Definition at line 1211 of file res_stasis.c.

References ast_channel_datastore_find(), lock, NULL, and SCOPED_CHANNELLOCK.

Referenced by stasis_app_exec().

1212 {
1213  SCOPED_CHANNELLOCK(lock, chan);
1215 }
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
ast_mutex_t lock
Definition: app_meetme.c:1091
static const struct ast_datastore_info masquerade_store_info
Definition: res_stasis.c:1205

◆ load_module()

static int load_module ( void  )
static

Definition at line 2337 of file res_stasis.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, app_compare(), app_hash(), APPS_NUM_BUCKETS, AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, bridge_stasis_init(), bridges_channel_compare(), bridges_channel_hash_fn(), bridges_channel_sort_fn(), bridges_compare(), bridges_hash(), BRIDGES_NUM_BUCKETS, control_compare(), control_hash(), CONTROLS_NUM_BUCKETS, messaging_init(), NULL, stasis_app_register_event_sources(), STASIS_MESSAGE_TYPE_INIT, and unload_module().

2338 {
2339  if (STASIS_MESSAGE_TYPE_INIT(start_message_type) != 0) {
2340  return AST_MODULE_LOAD_DECLINE;
2341  }
2342  if (STASIS_MESSAGE_TYPE_INIT(end_message_type) != 0) {
2343  return AST_MODULE_LOAD_DECLINE;
2344  }
2358  unload_module();
2359  return AST_MODULE_LOAD_DECLINE;
2360  }
2361 
2362  if (messaging_init()) {
2363  unload_module();
2364  return AST_MODULE_LOAD_DECLINE;
2365  }
2366 
2368 
2370 
2371  return AST_MODULE_LOAD_SUCCESS;
2372 }
static int bridges_channel_hash_fn(const void *obj, const int flags)
Definition: res_stasis.c:462
void stasis_app_register_event_sources(void)
Register core event sources.
static int bridges_channel_compare(void *obj, void *arg, int flags)
Definition: res_stasis.c:429
static int app_compare(void *obj, void *arg, int flags)
Definition: res_stasis.c:208
static int bridges_compare(void *obj, void *arg, int flags)
Definition: res_stasis.c:378
static int unload_module(void)
Definition: res_stasis.c:2195
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
static int control_compare(void *obj, void *arg, int flags)
Definition: res_stasis.c:270
struct ao2_container * app_bridges_moh
Definition: res_stasis.c:106
#define APPS_NUM_BUCKETS
Number of buckets for the Stasis application hash table. Remember to keep it a prime number! ...
Definition: res_stasis.c:83
#define BRIDGES_NUM_BUCKETS
Number of buckets for the Stasis bridges hash table. Remember to keep it a prime number! ...
Definition: res_stasis.c:95
#define NULL
Definition: resample.c:96
struct ao2_container * app_bridges
Definition: res_stasis.c:104
static int control_hash(const void *obj, const int flags)
Definition: res_stasis.c:248
struct ao2_container * app_controls
Definition: res_stasis.c:102
int messaging_init(void)
Initialize the messaging layer.
Definition: messaging.c:539
#define CONTROLS_NUM_BUCKETS
Number of buckets for the Stasis application hash table. Remember to keep it a prime number! ...
Definition: res_stasis.c:89
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
struct ao2_container * app_bridges_playback
Definition: res_stasis.c:108
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int bridges_channel_sort_fn(const void *obj_left, const void *obj_right, const int flags)
Definition: res_stasis.c:483
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
static int app_hash(const void *obj, const int flags)
Definition: res_stasis.c:186
static int bridges_hash(const void *obj, const int flags)
Definition: res_stasis.c:356
Reject objects with duplicate keys in container.
Definition: astobj2.h:1192
void bridge_stasis_init(void)

◆ masq_match_cb()

static int masq_match_cb ( void *  obj,
void *  data,
int  flags 
)
static

Definition at line 1115 of file res_stasis.c.

References ast_channel_uniqueid(), CMP_MATCH, ast_channel::data, and stasis_app_control_get_channel_id().

Referenced by channel_replaced_cb(), and channel_stolen_cb().

1116 {
1117  struct stasis_app_control *control = obj;
1118  struct ast_channel *chan = data;
1119 
1120  if (!strcmp(ast_channel_uniqueid(chan),
1122  return CMP_MATCH;
1123  }
1124 
1125  return 0;
1126 }
Main Channel structure associated with a channel.
const char * data
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * stasis_app_control_get_channel_id(const struct stasis_app_control *control)
Returns the uniqueid of the channel associated with this control.
Definition: control.c:1430

◆ moh_channel_thread()

static void* moh_channel_thread ( void *  data)
static

Provides the moh channel with a thread so it can actually play its music

Definition at line 529 of file res_stasis.c.

References ao2_ref, ao2_unlink, ast_channel_get_by_name(), ast_frfree, ast_hangup(), ast_moh_stop(), ast_read(), ast_waitfor(), stasis_app_bridge_channel_wrapper::channel_id, and NULL.

Referenced by bridge_moh_create().

530 {
531  struct stasis_app_bridge_channel_wrapper *moh_wrapper = data;
532  struct ast_channel *moh_channel = ast_channel_get_by_name(moh_wrapper->channel_id);
533  struct ast_frame *f;
534 
535  if (!moh_channel) {
536  ao2_unlink(app_bridges_moh, moh_wrapper);
537  ao2_ref(moh_wrapper, -1);
538  return NULL;
539  }
540 
541  /* Read and discard any frame coming from the stasis bridge. */
542  for (;;) {
543  if (ast_waitfor(moh_channel, -1) < 0) {
544  /* Error or hungup */
545  break;
546  }
547 
548  f = ast_read(moh_channel);
549  if (!f) {
550  /* Hungup */
551  break;
552  }
553  ast_frfree(f);
554  }
555 
556  ao2_unlink(app_bridges_moh, moh_wrapper);
557  ao2_ref(moh_wrapper, -1);
558 
559  ast_moh_stop(moh_channel);
560  ast_hangup(moh_channel);
561 
562  return NULL;
563 }
Main Channel structure associated with a channel.
struct ao2_container * app_bridges_moh
Definition: res_stasis.c:106
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
#define NULL
Definition: resample.c:96
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
const ast_string_field channel_id
Definition: res_stasis.c:425
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
#define ast_frfree(fr)
Data structure associated with a single frame of data.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

◆ playback_after_bridge_cb()

static void playback_after_bridge_cb ( struct ast_channel chan,
void *  data 
)
static

Definition at line 698 of file res_stasis.c.

References remove_bridge_playback().

Referenced by stasis_app_bridge_playback_channel_add().

699 {
700  char *bridge_id = data;
701 
702  remove_bridge_playback(bridge_id);
703 }
union ast_frame::@263 data
static void remove_bridge_playback(char *bridge_id)
Definition: res_stasis.c:673

◆ playback_after_bridge_cb_failed()

static void playback_after_bridge_cb_failed ( enum ast_bridge_after_cb_reason  reason,
void *  data 
)
static

Definition at line 691 of file res_stasis.c.

References remove_bridge_playback().

Referenced by stasis_app_bridge_playback_channel_add().

692 {
693  char *bridge_id = data;
694 
695  remove_bridge_playback(bridge_id);
696 }
union ast_frame::@263 data
static void remove_bridge_playback(char *bridge_id)
Definition: res_stasis.c:673

◆ prepare_bridge_moh_channel()

static struct ast_channel* prepare_bridge_moh_channel ( void  )
static

Request a bridge MOH channel

Definition at line 510 of file res_stasis.c.

References ao2_ref, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_request(), and NULL.

Referenced by bridge_moh_create().

511 {
512  struct ast_channel *chan;
513  struct ast_format_cap *cap;
514 
516  if (!cap) {
517  return NULL;
518  }
519 
521 
522  chan = ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL);
523  ao2_ref(cap, -1);
524 
525  return chan;
526 }
Main Channel structure associated with a channel.
#define NULL
Definition: resample.c:96
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition: channel.c:6444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41

◆ remove_bridge_playback()

static void remove_bridge_playback ( char *  bridge_id)
static

Removes the bridge to playback channel link

Definition at line 673 of file res_stasis.c.

References ao2_find, ao2_ref, ao2_unlink, ast_free, stasis_app_bridge_channel_wrapper::channel_id, OBJ_SEARCH_KEY, OBJ_UNLINK, and stasis_app_control_find_by_channel_id().

Referenced by playback_after_bridge_cb(), and playback_after_bridge_cb_failed().

674 {
675  struct stasis_app_bridge_channel_wrapper *wrapper;
676  struct stasis_app_control *control;
677 
678  wrapper = ao2_find(app_bridges_playback, bridge_id, OBJ_SEARCH_KEY | OBJ_UNLINK);
679 
680  if (wrapper) {
682  if (control) {
683  ao2_unlink(app_controls, control);
684  ao2_ref(control, -1);
685  }
686  ao2_ref(wrapper, -1);
687  }
688  ast_free(bridge_id);
689 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ao2_container * app_controls
Definition: res_stasis.c:102
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ao2_container * app_bridges_playback
Definition: res_stasis.c:108
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
struct stasis_app_control * stasis_app_control_find_by_channel_id(const char *channel_id)
Returns the handler for the channel with the given id.
Definition: res_stasis.c:349
const ast_string_field channel_id
Definition: res_stasis.c:425
#define ast_free(a)
Definition: astmm.h:182
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ remove_masquerade_store()

static void remove_masquerade_store ( struct ast_channel chan)
static

Definition at line 1236 of file res_stasis.c.

References ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_datastore_free(), lock, NULL, and SCOPED_CHANNELLOCK.

Referenced by app_send_end_msg(), channel_stolen_cb(), send_start_msg(), and stasis_app_exec().

1237 {
1238  struct ast_datastore *datastore;
1239 
1240  SCOPED_CHANNELLOCK(lock, chan);
1242  if (!datastore) {
1243  return;
1244  }
1245 
1246  ast_channel_datastore_remove(chan, datastore);
1247  ast_datastore_free(datastore);
1248 }
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
ast_mutex_t lock
Definition: app_meetme.c:1091
static const struct ast_datastore_info masquerade_store_info
Definition: res_stasis.c:1205
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2399

◆ remove_stasis_end_published()

static void remove_stasis_end_published ( struct ast_channel chan)
static

Definition at line 1310 of file res_stasis.c.

References ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_unlock, ast_datastore_free(), and NULL.

Referenced by stasis_app_exec().

1311 {
1312  struct ast_datastore *datastore;
1313 
1314  ast_channel_lock(chan);
1316  if (datastore) {
1317  ast_channel_datastore_remove(chan, datastore);
1318  ast_datastore_free(datastore);
1319  }
1320  ast_channel_unlock(chan);
1321 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
struct ast_datastore_info set_end_published_info
Definition: res_stasis.c:1283
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2399

◆ replace_channel_destroy()

static void replace_channel_destroy ( void *  obj)
static

Definition at line 876 of file res_stasis.c.

References ao2_cleanup, replace_channel_store::app, ast_free, replace(), and replace_channel_store::snapshot.

877 {
878  struct replace_channel_store *replace = obj;
879 
880  ao2_cleanup(replace->snapshot);
881  ast_free(replace->app);
882  ast_free(replace);
883 }
struct ast_channel_snapshot * snapshot
Definition: res_stasis.c:872
#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
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ send_start_msg()

static int send_start_msg ( struct stasis_app app,
struct ast_channel chan,
int  argc,
char *  argv[] 
)
static

Definition at line 1057 of file res_stasis.c.

References ao2_cleanup, ao2_ref, ast_assert, ast_channel_lock, ast_channel_snapshot_create(), ast_channel_unlock, get_replace_channel_snapshot(), NULL, remove_masquerade_store(), and send_start_msg_snapshots().

Referenced by stasis_app_exec().

1059 {
1060  int ret = -1;
1061  struct ast_channel_snapshot *snapshot;
1062  struct ast_channel_snapshot *replace_channel_snapshot;
1063 
1064  ast_assert(chan != NULL);
1065 
1066  replace_channel_snapshot = get_replace_channel_snapshot(chan);
1067 
1068  /* Set channel info */
1069  ast_channel_lock(chan);
1070  snapshot = ast_channel_snapshot_create(chan);
1071  ast_channel_unlock(chan);
1072  if (snapshot) {
1073  ret = send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot);
1074  ao2_ref(snapshot, -1);
1075  }
1076  ao2_cleanup(replace_channel_snapshot);
1077 
1078  return ret;
1079 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static struct ast_channel_snapshot * get_replace_channel_snapshot(struct ast_channel *chan)
Definition: res_stasis.c:952
Structure representing a snapshot of channel state.
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate...
static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app *app, int argc, char *argv[], struct ast_channel_snapshot *snapshot, struct ast_channel_snapshot *replace_channel_snapshot)
Definition: res_stasis.c:991
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ send_start_msg_snapshots()

static int send_start_msg_snapshots ( struct ast_channel chan,
struct stasis_app app,
int  argc,
char *  argv[],
struct ast_channel_snapshot snapshot,
struct ast_channel_snapshot replace_channel_snapshot 
)
static

Definition at line 991 of file res_stasis.c.

References ao2_alloc, ao2_bump, ao2_ref, app_subscribe_channel(), app_unsubscribe_channel_id(), ast_app_get_topic(), ast_assert, ast_channel_name(), ast_json_array_append(), ast_json_object_get(), ast_json_pack(), ast_json_string_create(), ast_json_timeval(), ast_log, ast_tvnow(), ast_channel_snapshot::base, start_message_blob::blob, start_message_blob::channel, LOG_ERROR, NULL, start_message_blob::replace_channel, start_message_blob_dtor(), stasis_app_name(), stasis_message_create(), stasis_publish(), and ast_channel_snapshot_base::uniqueid.

Referenced by channel_replaced_cb(), and send_start_msg().

994 {
995  struct ast_json *json_blob;
996  struct ast_json *json_args;
997  struct start_message_blob *payload;
998  struct stasis_message *msg;
999  int i;
1000 
1001  if (app_subscribe_channel(app, chan)) {
1002  ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
1003  stasis_app_name(app), ast_channel_name(chan));
1004  return -1;
1005  }
1006 
1007  payload = ao2_alloc(sizeof(*payload), start_message_blob_dtor);
1008  if (!payload) {
1009  ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
1010  return -1;
1011  }
1012 
1013  payload->channel = ao2_bump(snapshot);
1014  payload->replace_channel = ao2_bump(replace_channel_snapshot);
1015 
1016  json_blob = ast_json_pack("{s: s, s: o, s: []}",
1017  "app", stasis_app_name(app),
1018  "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1019  "args");
1020  if (!json_blob) {
1021  ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
1022  ao2_ref(payload, -1);
1023  return -1;
1024  }
1025  payload->blob = json_blob;
1026 
1027 
1028  /* Append arguments to args array */
1029  json_args = ast_json_object_get(json_blob, "args");
1030  ast_assert(json_args != NULL);
1031  for (i = 0; i < argc; ++i) {
1032  int r = ast_json_array_append(json_args,
1033  ast_json_string_create(argv[i]));
1034  if (r != 0) {
1035  ast_log(LOG_ERROR, "Error appending to StasisStart message\n");
1036  ao2_ref(payload, -1);
1037  return -1;
1038  }
1039  }
1040 
1041 
1042  msg = stasis_message_create(start_message_type(), payload);
1043  ao2_ref(payload, -1);
1044  if (!msg) {
1045  ast_log(LOG_ERROR, "Error sending StasisStart message\n");
1046  return -1;
1047  }
1048 
1049  if (replace_channel_snapshot) {
1050  app_unsubscribe_channel_id(app, replace_channel_snapshot->base->uniqueid);
1051  }
1052  stasis_publish(ast_app_get_topic(app), msg);
1053  ao2_ref(msg, -1);
1054  return 0;
1055 }
struct stasis_topic * ast_app_get_topic(struct stasis_app *app)
Returns the stasis topic for an app.
struct ast_channel_snapshot * replace_channel
Definition: res_stasis.c:143
struct ast_channel_snapshot_base * base
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
const ast_string_field uniqueid
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#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
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int app_unsubscribe_channel_id(struct stasis_app *app, const char *channel_id)
Cancel the subscription an app has for a channel.
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:649
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
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
struct ast_channel_snapshot * channel
Definition: res_stasis.c:142
struct ast_json * blob
Definition: res_stasis.c:144
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
const char * ast_channel_name(const struct ast_channel *chan)
Abstract JSON element (object, array, string, int, ...).
int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan)
Subscribes an application to a channel.
static void start_message_blob_dtor(void *obj)
Definition: res_stasis.c:982

◆ set_internal_datastore()

static int set_internal_datastore ( struct ast_channel chan)
static

Definition at line 2273 of file res_stasis.c.

References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, and NULL.

Referenced by stasis_app_channel_set_internal(), and stasis_app_channel_unreal_set_internal().

2274 {
2275  struct ast_datastore *datastore;
2276 
2278  if (!datastore) {
2280  if (!datastore) {
2281  return -1;
2282  }
2283  ast_channel_datastore_add(chan, datastore);
2284  }
2285  return 0;
2286 }
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
static const struct ast_datastore_info stasis_internal_channel_info
Definition: res_stasis.c:2269
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ start_message_blob_dtor()

static void start_message_blob_dtor ( void *  obj)
static

Definition at line 982 of file res_stasis.c.

References ao2_cleanup, ast_json_unref(), start_message_blob::blob, start_message_blob::channel, and start_message_blob::replace_channel.

Referenced by send_start_msg_snapshots().

983 {
984  struct start_message_blob *payload = obj;
985 
986  ao2_cleanup(payload->channel);
987  ao2_cleanup(payload->replace_channel);
988  ast_json_unref(payload->blob);
989 }
struct ast_channel_snapshot * replace_channel
Definition: res_stasis.c:143
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_channel_snapshot * channel
Definition: res_stasis.c:142
struct ast_json * blob
Definition: res_stasis.c:144
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ stasis_app_bridge_channel_wrapper_destructor()

static void stasis_app_bridge_channel_wrapper_destructor ( void *  obj)
static

Definition at line 455 of file res_stasis.c.

References ast_string_field_free_memory.

Referenced by bridge_moh_create(), and stasis_app_bridge_playback_channel_add().

456 {
457  struct stasis_app_bridge_channel_wrapper *wrapper = obj;
459 }
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ stasis_app_bridge_create()

struct ast_bridge* stasis_app_bridge_create ( const char *  type,
const char *  name,
const char *  id 
)

Create a bridge of the specified type.

Parameters
typeThe type of bridge to be created
nameOptional name to give to the bridge
idOptional Unique ID to give to the bridge
Returns
New bridge.
NULL on error.

Definition at line 851 of file res_stasis.c.

References bridge_create_common().

Referenced by ast_ari_bridges_create(), and ast_ari_bridges_create_with_id().

852 {
853  return bridge_create_common(type, name, id, 0);
854 }
static const char type[]
Definition: chan_ooh323.c:109
static struct ast_bridge * bridge_create_common(const char *type, const char *name, const char *id, int invisible)
Definition: res_stasis.c:795
static const char name[]
Definition: cdr_mysql.c:74

◆ stasis_app_bridge_create_invisible()

struct ast_bridge* stasis_app_bridge_create_invisible ( const char *  type,
const char *  name,
const char *  id 
)

Create an invisible bridge of the specified type.

Parameters
typeThe type of bridge to be created
nameOptional name to give to the bridge
idOptional Unique ID to give to the bridge
Returns
New bridge.
NULL on error.

Definition at line 856 of file res_stasis.c.

References bridge_create_common().

Referenced by get_dial_bridge().

857 {
858  return bridge_create_common(type, name, id, 1);
859 }
static const char type[]
Definition: chan_ooh323.c:109
static struct ast_bridge * bridge_create_common(const char *type, const char *name, const char *id, int invisible)
Definition: res_stasis.c:795
static const char name[]
Definition: cdr_mysql.c:74

◆ stasis_app_bridge_destroy()

void stasis_app_bridge_destroy ( const char *  bridge_id)

Destroy the bridge.

Parameters
bridge_idUniqueid of bridge to be destroyed
Return values
non-zeroon failure
zeroon success

Definition at line 861 of file res_stasis.c.

References ao2_unlink, ast_bridge_destroy(), and stasis_app_bridge_find_by_id().

Referenced by ast_ari_bridges_destroy().

862 {
863  struct ast_bridge *bridge = stasis_app_bridge_find_by_id(bridge_id);
864  if (!bridge) {
865  return;
866  }
867  ao2_unlink(app_bridges, bridge);
868  ast_bridge_destroy(bridge, 0);
869 }
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
struct ao2_container * app_bridges
Definition: res_stasis.c:104
Structure that contains information about a bridge.
Definition: bridge.h:357
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
struct ast_bridge * stasis_app_bridge_find_by_id(const char *bridge_id)
Returns the bridge with the given id.
Definition: res_stasis.c:774

◆ stasis_app_bridge_find_by_id()

struct ast_bridge* stasis_app_bridge_find_by_id ( const char *  bridge_id)

Returns the bridge with the given id.

Parameters
bridge_idUniqueid of the bridge.
Returns
NULL bridge not created by a Stasis application, or bridge does not exist.
Pointer to bridge.

Definition at line 774 of file res_stasis.c.

References ao2_find, and OBJ_SEARCH_KEY.

Referenced by bridge_find(), find_bridge(), and stasis_app_bridge_destroy().

776 {
777  return ao2_find(app_bridges, bridge_id, OBJ_SEARCH_KEY);
778 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ao2_container * app_bridges
Definition: res_stasis.c:104
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ stasis_app_bridge_moh_channel()

struct ast_channel* stasis_app_bridge_moh_channel ( struct ast_bridge bridge)

Finds or creates an announcer channel in a bridge that can play music on hold.

Parameters
bridgeBridge we want an MOH channel for
Returns
NULL if the music on hold channel fails to be created or join the bridge for any reason.
Pointer to the ;1 end of the announcer channel chain.

Definition at line 629 of file res_stasis.c.

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_channel_get_by_name(), bridge_moh_create(), stasis_app_bridge_channel_wrapper::channel_id, OBJ_NOLOCK, OBJ_SEARCH_KEY, and ast_bridge::uniqueid.

Referenced by ast_ari_bridges_start_moh().

630 {
631  struct ast_channel *chan;
632  struct stasis_app_bridge_channel_wrapper *moh_wrapper;
633 
635  moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_NOLOCK);
636  if (!moh_wrapper) {
637  chan = bridge_moh_create(bridge);
638  }
640 
641  if (moh_wrapper) {
642  chan = ast_channel_get_by_name(moh_wrapper->channel_id);
643  ao2_ref(moh_wrapper, -1);
644  }
645 
646  return chan;
647 }
Main Channel structure associated with a channel.
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
struct ao2_container * app_bridges_moh
Definition: res_stasis.c:106
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
static struct ast_channel * bridge_moh_create(struct ast_bridge *bridge)
Definition: res_stasis.c:574
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const ast_string_field channel_id
Definition: res_stasis.c:425
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

◆ stasis_app_bridge_moh_stop()

int stasis_app_bridge_moh_stop ( struct ast_bridge bridge)

Breaks down MOH channels playing on the bridge created by stasis_app_bridge_moh_channel.

Parameters
bridgeBridge we want to stop the MOH on
Returns
-1 if no moh channel could be found and stopped
0 on success

Definition at line 649 of file res_stasis.c.

References ao2_cleanup, ao2_find, ao2_ref, AST_CAUSE_NORMAL_CLEARING, ast_channel_get_by_name(), ast_moh_stop(), ast_softhangup(), stasis_app_bridge_channel_wrapper::channel_id, OBJ_SEARCH_KEY, OBJ_UNLINK, and ast_bridge::uniqueid.

Referenced by ast_ari_bridges_stop_moh().

650 {
651  struct stasis_app_bridge_channel_wrapper *moh_wrapper;
652  struct ast_channel *chan;
653 
654  moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_UNLINK);
655  if (!moh_wrapper) {
656  return -1;
657  }
658 
659  chan = ast_channel_get_by_name(moh_wrapper->channel_id);
660  ao2_ref(moh_wrapper, -1);
661  if (!chan) {
662  return -1;
663  }
664 
665  ast_moh_stop(chan);
667  ao2_cleanup(chan);
668 
669  return 0;
670 }
Main Channel structure associated with a channel.
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
struct ao2_container * app_bridges_moh
Definition: res_stasis.c:106
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
const ast_string_field channel_id
Definition: res_stasis.c:425
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

◆ stasis_app_bridge_playback_channel_add()

int stasis_app_bridge_playback_channel_add ( struct ast_bridge bridge,
struct ast_channel chan,
struct stasis_app_control control 
)

Adds a channel to the list of ARI playback channels for bridges.

Parameters
bridgeBridge we are adding the playback channel for
chanChannel being added as a playback channel (must be ;1)
Return values
-1failed to add channel for any reason
0on success

Definition at line 705 of file res_stasis.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_link, ast_bridge_set_after_callback(), ast_channel_uniqueid(), ast_free, ast_strdup, ast_string_field_init, ast_string_field_set, NULL, playback_after_bridge_cb(), playback_after_bridge_cb_failed(), RAII_VAR, stasis_app_bridge_channel_wrapper_destructor(), and ast_bridge::uniqueid.

Referenced by ari_bridges_play_new().

708 {
710  char *bridge_id = ast_strdup(bridge->uniqueid);
711 
712  if (!bridge_id) {
713  return -1;
714  }
715 
718  ast_free(bridge_id);
719  return -1;
720  }
721 
722  new_wrapper = ao2_alloc_options(sizeof(*new_wrapper),
724  if (!new_wrapper) {
725  return -1;
726  }
727 
728  if (ast_string_field_init(new_wrapper, 32)) {
729  return -1;
730  }
731 
732  ast_string_field_set(new_wrapper, bridge_id, bridge->uniqueid);
733  ast_string_field_set(new_wrapper, channel_id, ast_channel_uniqueid(chan));
734 
735  if (!ao2_link(app_bridges_playback, new_wrapper)) {
736  return -1;
737  }
738 
739  ao2_link(app_controls, control);
740  return 0;
741 }
static void playback_after_bridge_cb(struct ast_channel *chan, void *data)
Definition: res_stasis.c:698
const ast_string_field uniqueid
Definition: bridge.h:409
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
Setup an after bridge callback for when the channel leaves the bridging system.
Definition: bridge_after.c:259
struct ao2_container * app_controls
Definition: res_stasis.c:102
#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 ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ao2_container * app_bridges_playback
Definition: res_stasis.c:108
#define ast_free(a)
Definition: astmm.h:182
static void playback_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition: res_stasis.c:691
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static void stasis_app_bridge_channel_wrapper_destructor(void *obj)
Definition: res_stasis.c:455
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ stasis_app_bridge_playback_channel_find()

struct ast_channel* stasis_app_bridge_playback_channel_find ( struct ast_bridge bridge)

Finds an existing ARI playback channel in a bridge.

Parameters
bridgeBridge we want to find the playback channel for
Returns
NULL if the playback channel can not be found for any reason.
Pointer to the ;1 end of the playback channel chain.

Definition at line 759 of file res_stasis.c.

References ao2_find, ao2_ref, ast_channel_get_by_name(), stasis_app_bridge_channel_wrapper::channel_id, NULL, OBJ_SEARCH_KEY, and ast_bridge::uniqueid.

Referenced by ari_bridges_handle_play().

760 {
761  struct stasis_app_bridge_channel_wrapper *playback_wrapper;
762  struct ast_channel *chan;
763 
764  playback_wrapper = ao2_find(app_bridges_playback, bridge->uniqueid, OBJ_SEARCH_KEY);
765  if (!playback_wrapper) {
766  return NULL;
767  }
768 
769  chan = ast_channel_get_by_name(playback_wrapper->channel_id);
770  ao2_ref(playback_wrapper, -1);
771  return chan;
772 }
Main Channel structure associated with a channel.
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
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ao2_container * app_bridges_playback
Definition: res_stasis.c:108
const ast_string_field channel_id
Definition: res_stasis.c:425
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

◆ stasis_app_bridge_playback_channel_remove()

void stasis_app_bridge_playback_channel_remove ( char *  bridge_id,
struct stasis_app_control control 
)

remove channel from list of ARI playback channels for bridges.

Parameters
bridge_idThe unique ID of the bridge the playback channel is in.
controlThe app control structure for the playback channel

Definition at line 743 of file res_stasis.c.

References ao2_find, ao2_ref, ao2_unlink, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by ari_bridges_play_new(), and bridge_channel_control_thread().

745 {
746  struct stasis_app_bridge_channel_wrapper *wrapper;
747 
749  if (wrapper) {
750  /* If wrapper is not found, then that means the after bridge callback has been
751  * called or is in progress. No need to unlink the control here since that has
752  * been done or is about to be done in the after bridge callback
753  */
754  ao2_unlink(app_controls, control);
755  ao2_ref(wrapper, -1);
756  }
757 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const ast_string_field bridge_id
Definition: res_stasis.c:425
struct ao2_container * app_controls
Definition: res_stasis.c:102
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ao2_container * app_bridges_playback
Definition: res_stasis.c:108
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ stasis_app_channel_is_internal()

int stasis_app_channel_is_internal ( struct ast_channel chan)

Is this channel internal to Stasis?

Parameters
chanThe channel to check.
Return values
0No
1Yes

Definition at line 2322 of file res_stasis.c.

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, and NULL.

Referenced by bridge_stasis_push().

2323 {
2324  struct ast_datastore *datastore;
2325  int res = 0;
2326 
2327  ast_channel_lock(chan);
2329  if (datastore) {
2330  res = 1;
2331  }
2332  ast_channel_unlock(chan);
2333 
2334  return res;
2335 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
static const struct ast_datastore_info stasis_internal_channel_info
Definition: res_stasis.c:2269
#define ast_channel_unlock(chan)
Definition: channel.h:2946

◆ stasis_app_channel_is_stasis_end_published()

int stasis_app_channel_is_stasis_end_published ( struct ast_channel chan)

Has this channel had a StasisEnd published on it?

Parameters
chanThe channel upon which the query rests.
Return values
0No
1Yes

Definition at line 1299 of file res_stasis.c.

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, and NULL.

Referenced by internal_bridge_after_cb(), and stasis_app_exec().

1300 {
1301  struct ast_datastore *datastore;
1302 
1303  ast_channel_lock(chan);
1305  ast_channel_unlock(chan);
1306 
1307  return datastore ? 1 : 0;
1308 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
struct ast_datastore_info set_end_published_info
Definition: res_stasis.c:1283
#define NULL
Definition: resample.c:96
#define ast_channel_unlock(chan)
Definition: channel.h:2946

◆ stasis_app_channel_set_internal()

int stasis_app_channel_set_internal ( struct ast_channel chan)

Mark this channel as being internal to Stasis.

Parameters
chanThe channel to mark.
Return values
zeroSuccess
non-zeroFailure

Definition at line 2311 of file res_stasis.c.

References ast_channel_lock, ast_channel_unlock, and set_internal_datastore().

2312 {
2313  int res;
2314 
2315  ast_channel_lock(chan);
2316  res = set_internal_datastore(chan);
2317  ast_channel_unlock(chan);
2318 
2319  return res;
2320 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static int set_internal_datastore(struct ast_channel *chan)
Definition: res_stasis.c:2273

◆ stasis_app_channel_set_stasis_end_published()

void stasis_app_channel_set_stasis_end_published ( struct ast_channel chan)

Indicate that this channel has had a StasisEnd published for it.

Parameters
Thechannel that is exiting Stasis.

Definition at line 1287 of file res_stasis.c.

References ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, and NULL.

Referenced by bridge_stasis_moving(), and channel_stolen_cb().

1288 {
1289  struct ast_datastore *datastore;
1290 
1292  if (datastore) {
1293  ast_channel_lock(chan);
1294  ast_channel_datastore_add(chan, datastore);
1295  ast_channel_unlock(chan);
1296  }
1297 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore_info set_end_published_info
Definition: res_stasis.c:1283
#define NULL
Definition: resample.c:96
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ stasis_app_channel_unreal_set_internal()

int stasis_app_channel_unreal_set_internal ( struct ast_channel chan)

Mark this unreal channel and it's other half as being internal to Stasis.

Parameters
chanThe channel to mark.
Return values
zeroSuccess
non-zeroFailure

Definition at line 2288 of file res_stasis.c.

References ao2_ref, ao2_unlock, ast_channel_tech_pvt(), ast_channel_unlock, ast_channel_unref, ast_unreal_lock_all(), NULL, and set_internal_datastore().

Referenced by bridge_moh_create(), and prepare_bridge_media_channel().

2289 {
2290  struct ast_channel *outchan = NULL, *outowner = NULL;
2291  int res = 0;
2292  struct ast_unreal_pvt *unreal_pvt = ast_channel_tech_pvt(chan);
2293 
2294  ao2_ref(unreal_pvt, +1);
2295  ast_unreal_lock_all(unreal_pvt, &outowner, &outchan);
2296  if (outowner) {
2297  res |= set_internal_datastore(outowner);
2298  ast_channel_unlock(outowner);
2299  ast_channel_unref(outowner);
2300  }
2301  if (outchan) {
2302  res |= set_internal_datastore(outchan);
2303  ast_channel_unlock(outchan);
2304  ast_channel_unref(outchan);
2305  }
2306  ao2_unlock(unreal_pvt);
2307  ao2_ref(unreal_pvt, -1);
2308  return res;
2309 }
Main Channel structure associated with a channel.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static int set_internal_datastore(struct ast_channel *chan)
Definition: res_stasis.c:2273
void ast_unreal_lock_all(struct ast_unreal_pvt *p, struct ast_channel **outchan, struct ast_channel **outowner)
Send an unreal pvt in with no locks held and get all locks.
Definition: core_unreal.c:47

◆ stasis_app_control_create()

struct stasis_app_control* stasis_app_control_create ( struct ast_channel chan)

Creates a control handler for a channel that isn't in a stasis app.

Since
12.0.0
Parameters
chanChannel to create controller handle for
Returns
NULL on failure to create the handle
Pointer to res_stasis handler.

Definition at line 333 of file res_stasis.c.

References control_create(), and NULL.

Referenced by ari_bridges_play_new(), and ast_ari_bridges_record().

334 {
335  return control_create(chan, NULL);
336 }
#define NULL
Definition: resample.c:96
struct stasis_app_control * control_create(struct ast_channel *channel, struct stasis_app *app)
Create a control object.
Definition: control.c:123

◆ stasis_app_control_execute_until_exhausted()

void stasis_app_control_execute_until_exhausted ( struct ast_channel chan,
struct stasis_app_control control 
)

Act on a stasis app control queue until it is empty.

Since
12.0.0
Parameters
chanChannel to handle
controlControl object to execute

Definition at line 1250 of file res_stasis.c.

References ao2_lock, ao2_unlock, ast_channel_fdno(), control_command_count(), control_dispatch_all(), control_is_done(), and control_mark_done().

Referenced by bridge_channel_control_thread().

1251 {
1252  while (!control_is_done(control)) {
1253  int command_count;
1254  command_count = control_dispatch_all(control, chan);
1255 
1256  ao2_lock(control);
1257 
1258  if (control_command_count(control)) {
1259  /* If the command queue isn't empty, something added to the queue before it was locked. */
1260  ao2_unlock(control);
1261  continue;
1262  }
1263 
1264  if (command_count == 0 || ast_channel_fdno(chan) == -1) {
1265  control_mark_done(control);
1266  ao2_unlock(control);
1267  break;
1268  }
1269  ao2_unlock(control);
1270  }
1271 }
void control_mark_done(struct stasis_app_control *control)
Definition: control.c:354
#define ao2_unlock(a)
Definition: astobj2.h:730
int control_command_count(struct stasis_app_control *control)
Returns the count of items in a control&#39;s command queue.
Definition: control.c:343
int control_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all commands enqueued to this control.
Definition: control.c:1495
#define ao2_lock(a)
Definition: astobj2.h:718
int ast_channel_fdno(const struct ast_channel *chan)
int control_is_done(struct stasis_app_control *control)
Returns true if control_continue() has been called on this control.
Definition: control.c:348

◆ stasis_app_control_find_by_channel()

struct stasis_app_control* stasis_app_control_find_by_channel ( const struct ast_channel chan)

Returns the handler for the given channel.

Parameters
chanChannel to handle.
Returns
NULL channel not in Stasis application.
Pointer to res_stasis handler.

Definition at line 338 of file res_stasis.c.

References ast_channel_uniqueid(), NULL, and stasis_app_control_find_by_channel_id().

Referenced by ari_bridges_play_found(), bridge_stasis_moving(), bridge_stasis_push(), bridge_stasis_push_peek(), and bridge_timeout().

340 {
341  if (chan == NULL) {
342  return NULL;
343  }
344 
346  ast_channel_uniqueid(chan));
347 }
#define NULL
Definition: resample.c:96
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_app_control * stasis_app_control_find_by_channel_id(const char *channel_id)
Returns the handler for the channel with the given id.
Definition: res_stasis.c:349

◆ stasis_app_control_find_by_channel_id()

struct stasis_app_control* stasis_app_control_find_by_channel_id ( const char *  channel_id)

Returns the handler for the channel with the given id.

Parameters
channel_idUniqueid of the channel.
Returns
NULL channel not in Stasis application, or channel does not exist.
Pointer to res_stasis handler.

Definition at line 349 of file res_stasis.c.

References ao2_find, and OBJ_SEARCH_KEY.

Referenced by find_channel_control(), find_control(), remove_bridge_playback(), and stasis_app_control_find_by_channel().

351 {
352  return ao2_find(app_controls, channel_id, OBJ_SEARCH_KEY);
353 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ao2_container * app_controls
Definition: res_stasis.c:102
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ stasis_app_control_flush_queue()

void stasis_app_control_flush_queue ( struct stasis_app_control control)

Flush the control command queue.

Since
13.9.0
Parameters
controlControl object to flush command queue.
Returns
Nothing

Definition at line 1278 of file res_stasis.c.

References control_flush_queue().

Referenced by bridge_channel_control_thread().

1279 {
1280  control_flush_queue(control);
1281 }
void control_flush_queue(struct stasis_app_control *control)
Flush the control command queue.
Definition: control.c:1482

◆ stasis_app_control_is_done()

int stasis_app_control_is_done ( struct stasis_app_control control)

Check if a control is marked as done.

Since
12.2.0
Parameters
controlWhich control object is being evaluated

Definition at line 1273 of file res_stasis.c.

References control_is_done().

Referenced by ari_bridges_play_found().

1274 {
1275  return control_is_done(control);
1276 }
int control_is_done(struct stasis_app_control *control)
Returns true if control_continue() has been called on this control.
Definition: control.c:348

◆ stasis_app_exec()

int stasis_app_exec ( struct ast_channel chan,
const char *  app_name,
int  argc,
char *  argv[] 
)

Control a channel using stasis_app.

/brief Stasis dialplan application callback

Definition at line 1324 of file res_stasis.c.

References add_masquerade_store(), ao2_bump, ao2_cleanup, ao2_find, ao2_link, ao2_ref, app, app_is_active(), app_send(), app_send_end_msg(), app_subscribe_bridge(), app_unsubscribe_bridge(), ast_assert, ast_bridge_depart(), ast_channel_clear_softhangup(), ast_channel_fdno(), ast_channel_internal_bridge_channel(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_snapshot_get_latest(), ast_channel_snapshot_to_json(), ast_channel_uniqueid(), ast_channel_unlock, ast_check_hangup(), ast_check_hangup_locked(), AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CONTROL, ast_frame_dtor(), ast_free, ast_json_array_append(), ast_json_object_get(), ast_json_pack(), ast_json_string_create(), ast_json_timeval(), ast_json_unref(), ast_log, ast_pbx_run_args(), ast_read(), AST_SOFTHANGUP_ASYNCGOTO, ast_tvnow(), ast_waitfor(), cleanup(), control_app(), control_create(), control_dispatch_all(), control_flush_queue(), control_is_done(), control_mark_done(), control_move_cleanup(), control_next_app(), control_next_app_args(), control_next_app_args_size(), control_prestart_dispatch_all(), control_set_app(), control_silence_stop_now(), control_unlink(), control_wait(), has_masquerade_store(), LOG_ERROR, MAX_WAIT_MS, ast_pbx_args::no_hangup_chan, NULL, OBJ_SEARCH_KEY, RAII_VAR, remove_masquerade_store(), remove_stasis_end_published(), send_start_msg(), stasis_app_channel_is_stasis_end_published(), stasis_app_get_bridge(), and stasis_app_name().

Referenced by app_exec().

1326 {
1327  RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
1328  RAII_VAR(struct stasis_app_control *, control, NULL, control_unlink);
1329  struct ast_bridge *bridge = NULL;
1330  int res = 0;
1331  int needs_depart;
1332 
1333  ast_assert(chan != NULL);
1334 
1335  /* Just in case there's a lingering indication that the channel has had a stasis
1336  * end published on it, remove that now.
1337  */
1339 
1340  if (!apps_registry) {
1341  return -1;
1342  }
1343 
1345  if (!app) {
1347  "Stasis app '%s' not registered\n", app_name);
1348  return -1;
1349  }
1350  if (!app_is_active(app)) {
1352  "Stasis app '%s' not active\n", app_name);
1353  return -1;
1354  }
1355 
1356  control = control_create(chan, app);
1357  if (!control) {
1358  ast_log(LOG_ERROR, "Control allocation failed or Stasis app '%s' not registered\n", app_name);
1359  return -1;
1360  }
1361 
1362  if (!control_app(control)) {
1363  ast_log(LOG_ERROR, "Stasis app '%s' not registered\n", app_name);
1364  return -1;
1365  }
1366 
1367  if (!app_is_active(control_app(control))) {
1368  ast_log(LOG_ERROR, "Stasis app '%s' not active\n", app_name);
1369  return -1;
1370  }
1371  ao2_link(app_controls, control);
1372 
1373  if (add_masquerade_store(chan)) {
1374  ast_log(LOG_ERROR, "Failed to attach masquerade detector\n");
1375  return -1;
1376  }
1377 
1378  res = send_start_msg(control_app(control), chan, argc, argv);
1379  if (res != 0) {
1381  "Error sending start message to '%s'\n", app_name);
1383  return -1;
1384  }
1385 
1386  /* Pull queued prestart commands and execute */
1387  control_prestart_dispatch_all(control, chan);
1388 
1389  while (!control_is_done(control)) {
1390  RAII_VAR(struct ast_frame *, f, NULL, ast_frame_dtor);
1391  int r;
1392  int command_count;
1393  RAII_VAR(struct ast_bridge *, last_bridge, NULL, ao2_cleanup);
1394 
1395  /* Check to see if a bridge absorbed our hangup frame */
1396  if (ast_check_hangup_locked(chan)) {
1397  control_mark_done(control);
1398  break;
1399  }
1400 
1401  /* control->next_app is only modified within the control thread, so this is safe */
1402  if (control_next_app(control)) {
1403  struct stasis_app *next_app = ao2_find(apps_registry, control_next_app(control), OBJ_SEARCH_KEY);
1404 
1405  if (next_app && app_is_active(next_app)) {
1406  int idx;
1407  int next_argc;
1408  char **next_argv;
1409 
1410  /* If something goes wrong in this conditional, res will need to be non-zero
1411  * so that the code below the exec loop knows something went wrong during a move.
1412  */
1414  res = has_masquerade_store(chan) && app_send_end_msg(control_app(control), chan);
1415  if (res != 0) {
1417  "Error sending end message to %s\n", stasis_app_name(control_app(control)));
1418  control_mark_done(control);
1419  ao2_ref(next_app, -1);
1420  break;
1421  }
1422  } else {
1424  }
1425 
1426  /* This will ao2_bump next_app, and unref the previous app by 1 */
1427  control_set_app(control, next_app);
1428 
1429  /* There's a chance that the previous application is ready for clean up, so go ahead
1430  * and do that now.
1431  */
1432  cleanup();
1433 
1434  /* We need to add another masquerade store, otherwise the leave message will
1435  * not show up for the correct application.
1436  */
1437  if (add_masquerade_store(chan)) {
1438  ast_log(LOG_ERROR, "Failed to attach masquerade detector\n");
1439  res = -1;
1440  control_mark_done(control);
1441  ao2_ref(next_app, -1);
1442  break;
1443  }
1444 
1445  /* We MUST get the size before the list, as control_next_app_args steals the elements
1446  * from the string vector.
1447  */
1448  next_argc = control_next_app_args_size(control);
1449  next_argv = control_next_app_args(control);
1450 
1451  res = send_start_msg(control_app(control), chan, next_argc, next_argv);
1452 
1453  /* Even if res != 0, we still need to free the memory we got from control_argv */
1454  if (next_argv) {
1455  for (idx = 0; idx < next_argc; idx++) {
1456  ast_free(next_argv[idx]);
1457  }
1458  ast_free(next_argv);
1459  }
1460 
1461  if (res != 0) {
1463  "Error sending start message to '%s'\n", stasis_app_name(control_app(control)));
1465  control_mark_done(control);
1466  ao2_ref(next_app, -1);
1467  break;
1468  }
1469 
1470  /* Done switching applications, free memory and clean up */
1471  control_move_cleanup(control);
1472  } else {
1473  /* If we can't switch applications, do nothing */
1474  struct ast_json *msg;
1475  RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1476 
1477  if (!next_app) {
1478  ast_log(LOG_ERROR, "Could not move to Stasis app '%s' - not registered\n",
1479  control_next_app(control));
1480  } else {
1481  ast_log(LOG_ERROR, "Could not move to Stasis app '%s' - not active\n",
1482  control_next_app(control));
1483  }
1484 
1486  if (!snapshot) {
1487  ast_log(LOG_ERROR, "Could not get channel shapshot for '%s'\n",
1488  ast_channel_name(chan));
1489  } else {
1490  struct ast_json *json_args;
1491  int next_argc = control_next_app_args_size(control);
1492  char **next_argv = control_next_app_args(control);
1493 
1494  msg = ast_json_pack("{s: s, s: o, s: o, s: s, s: []}",
1495  "type", "ApplicationMoveFailed",
1496  "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1497  "channel", ast_channel_snapshot_to_json(snapshot, NULL),
1498  "destination", control_next_app(control),
1499  "args");
1500  if (!msg) {
1501  ast_log(LOG_ERROR, "Failed to pack JSON for ApplicationMoveFailed message\n");
1502  } else {
1503  json_args = ast_json_object_get(msg, "args");
1504  if (!json_args) {
1505  ast_log(LOG_ERROR, "Could not get args json array");
1506  } else {
1507  int r = 0;
1508  int idx;
1509  for (idx = 0; idx < next_argc; ++idx) {
1510  r = ast_json_array_append(json_args,
1511  ast_json_string_create(next_argv[idx]));
1512  if (r != 0) {
1513  ast_log(LOG_ERROR, "Error appending to ApplicationMoveFailed message\n");
1514  break;
1515  }
1516  }
1517  if (r == 0) {
1518  app_send(control_app(control), msg);
1519  }
1520  }
1521  ast_json_unref(msg);
1522  }
1523  }
1524  }
1525  control_move_cleanup(control);
1526  ao2_cleanup(next_app);
1527  }
1528 
1529  last_bridge = bridge;
1530  bridge = ao2_bump(stasis_app_get_bridge(control));
1531 
1532  if (bridge != last_bridge) {
1533  if (last_bridge) {
1534  app_unsubscribe_bridge(control_app(control), last_bridge);
1535  }
1536  if (bridge) {
1537  app_subscribe_bridge(control_app(control), bridge);
1538  }
1539  }
1540 
1541  if (bridge) {
1542  /* Bridge/dial is handling channel frames */
1543  control_wait(control);
1544  control_dispatch_all(control, chan);
1545  continue;
1546  }
1547 
1548  r = ast_waitfor(chan, MAX_WAIT_MS);
1549 
1550  if (r < 0) {
1551  ast_debug(3, "%s: Poll error\n",
1552  ast_channel_uniqueid(chan));
1553  control_mark_done(control);
1554  break;
1555  }
1556 
1557  command_count = control_dispatch_all(control, chan);
1558 
1559  if (command_count > 0 && ast_channel_fdno(chan) == -1) {
1560  /* Command drained the channel; wait for next frame */
1561  continue;
1562  }
1563 
1564  if (r == 0) {
1565  /* Timeout */
1566  continue;
1567  }
1568 
1569  f = ast_read(chan);
1570  if (!f) {
1571  /* Continue on in the dialplan */
1572  ast_debug(3, "%s: Hangup (no more frames)\n",
1573  ast_channel_uniqueid(chan));
1574  control_mark_done(control);
1575  break;
1576  }
1577 
1578  if (f->frametype == AST_FRAME_CONTROL) {
1579  if (f->subclass.integer == AST_CONTROL_HANGUP) {
1580  /* Continue on in the dialplan */
1581  ast_debug(3, "%s: Hangup\n",
1582  ast_channel_uniqueid(chan));
1583  control_mark_done(control);
1584  break;
1585  }
1586  }
1587  }
1588 
1589  ast_channel_lock(chan);
1590  needs_depart = (ast_channel_internal_bridge_channel(chan) != NULL);
1591  ast_channel_unlock(chan);
1592  if (needs_depart) {
1593  ast_bridge_depart(chan);
1594  }
1595 
1596  if (stasis_app_get_bridge(control)) {
1598  }
1599  ao2_cleanup(bridge);
1600 
1601  /* Only publish a stasis_end event if it hasn't already been published */
1602  if (!res && !stasis_app_channel_is_stasis_end_published(chan)) {
1603  /* A masquerade has occurred and this message will be wrong so it
1604  * has already been sent elsewhere. */
1605  res = has_masquerade_store(chan) && app_send_end_msg(control_app(control), chan);
1606  if (res != 0) {
1608  "Error sending end message to %s\n", stasis_app_name(control_app(control)));
1609  return res;
1610  }
1611  } else {
1613  }
1614 
1615  control_flush_queue(control);
1616 
1617  /* Stop any lingering silence generator */
1618  control_silence_stop_now(control);
1619 
1620  /* There's an off chance that app is ready for cleanup. Go ahead
1621  * and clean up, just in case
1622  */
1623  cleanup();
1624 
1625  /* The control needs to be removed from the controls container in
1626  * case a new PBX is started and ends up coming back into Stasis.
1627  */
1628  control_unlink(control);
1629  control = NULL;
1630 
1631  if (!res && !ast_channel_pbx(chan)) {
1632  int chan_hungup;
1633 
1634  /* The ASYNCGOTO softhangup flag may have broken the channel out of
1635  * its bridge to run dialplan, so if there's no pbx on the channel
1636  * let it run dialplan here. Otherwise, it will run when this
1637  * application exits. */
1638  ast_channel_lock(chan);
1640  chan_hungup = ast_check_hangup(chan);
1641  ast_channel_unlock(chan);
1642 
1643  if (!chan_hungup) {
1644  struct ast_pbx_args pbx_args;
1645 
1646  memset(&pbx_args, 0, sizeof(pbx_args));
1647  pbx_args.no_hangup_chan = 1;
1648 
1649  res = ast_pbx_run_args(chan, &pbx_args);
1650  }
1651  }
1652 
1653  return res;
1654 }
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition: control.c:931
Options for ast_pbx_run()
Definition: pbx.h:391
#define ast_channel_lock(chan)
Definition: channel.h:2945
char * control_next_app(struct stasis_app_control *control)
Returns the name of the application we are moving to.
Definition: control.c:1697
char ** control_next_app_args(struct stasis_app_control *control)
Returns the list of arguments to pass to the application we are moving to.
Definition: control.c:1710
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
void control_mark_done(struct stasis_app_control *control)
Definition: control.c:354
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:459
void control_flush_queue(struct stasis_app_control *control)
Flush the control command queue.
Definition: control.c:1482
Structure representing a snapshot of channel state.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
static int has_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1211
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_assert(a)
Definition: utils.h:695
static void remove_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1236
#define NULL
Definition: resample.c:96
struct stasis_app * control_app(struct stasis_app_control *control)
Returns the pointer (non-reffed) to the app associated with this control.
Definition: control.c:1563
int app_is_active(struct stasis_app *app)
Checks whether an app is active.
int control_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all commands enqueued to this control.
Definition: control.c:1495
int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Add a bridge subscription to an existing channel subscription.
void ast_frame_dtor(struct ast_frame *frame)
NULL-safe wrapper for ast_frfree, good for RAII_VAR.
Definition: main/frame.c:187
struct ao2_container * app_controls
Definition: res_stasis.c:102
int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
Send StasisEnd message to the listening app.
Definition: res_stasis.c:1083
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static void cleanup(void)
Clean up any old apps that we don&#39;t need any more.
Definition: res_stasis.c:327
int stasis_app_channel_is_stasis_end_published(struct ast_channel *chan)
Has this channel had a StasisEnd published on it?
Definition: res_stasis.c:1299
void control_move_cleanup(struct stasis_app_control *control)
Free any memory that was allocated for switching applications via /channels/{channelId}/move.
Definition: control.c:1702
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2437
#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
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:4739
int control_next_app_args_size(struct stasis_app_control *control)
Returns the number of arguments to be passed to the application we are moving to. ...
Definition: control.c:1715
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_bridge_channel * ast_channel_internal_bridge_channel(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:649
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:368
int ast_channel_fdno(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
Structure that contains information about a bridge.
Definition: bridge.h:357
static int send_start_msg(struct stasis_app *app, struct ast_channel *chan, int argc, char *argv[])
Definition: res_stasis.c:1057
void app_send(struct stasis_app *app, struct ast_json *message)
Send a message to the given application.
#define LOG_ERROR
Definition: logger.h:285
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition: bridge.c:1952
struct stasis_app_control * control_create(struct ast_channel *channel, struct stasis_app *app)
Create a control object.
Definition: control.c:123
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
#define ast_free(a)
Definition: astmm.h:182
static void control_unlink(struct stasis_app_control *control)
In addition to running ao2_cleanup(), this function also removes the object from the app_controls con...
Definition: res_stasis.c:785
#define MAX_WAIT_MS
Definition: res_stasis.c:77
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
void control_set_app(struct stasis_app_control *control, struct stasis_app *app)
Set the application the control object belongs to.
Definition: control.c:1691
void control_silence_stop_now(struct stasis_app_control *control)
Stop playing silence to a channel right now.
Definition: control.c:837
int control_is_done(struct stasis_app_control *control)
Returns true if control_continue() has been called on this control.
Definition: control.c:348
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
#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
int app_unsubscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Cancel the bridge subscription for an application.
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
const char * ast_channel_name(const struct ast_channel *chan)
Data structure associated with a single frame of data.
Abstract JSON element (object, array, string, int, ...).
static int add_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1217
static const char app[]
Definition: app_mysql.c:62
static void remove_stasis_end_published(struct ast_channel *chan)
Definition: res_stasis.c:1310
int control_prestart_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all queued prestart commands.
Definition: control.c:1535
void control_wait(struct stasis_app_control *control)
Blocks until control&#39;s command queue has a command available.
Definition: control.c:1515
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ stasis_app_get_all()

struct ao2_container* stasis_app_get_all ( void  )

Gets the names of all registered Stasis applications.

Returns
ast_str_container of container names.
NULL on error.

Definition at line 1708 of file res_stasis.c.

References ao2_callback, append_name(), apps, ast_str_container_alloc, NULL, and OBJ_NODATA.

Referenced by ari_show_apps(), ast_ari_applications_list(), complete_ari_app(), and stasis_app_set_global_debug().

1709 {
1710  struct ao2_container *apps;
1711 
1712  if (!apps_registry) {
1713  return NULL;
1714  }
1715 
1716  apps = ast_str_container_alloc(1);
1717  if (!apps) {
1718  return NULL;
1719  }
1720 
1722 
1723  return apps;
1724 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
Definition: strings.h:1312
#define NULL
Definition: resample.c:96
static struct apps apps
static int append_name(void *obj, void *arg, int flags)
Definition: res_stasis.c:1699
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
Generic container type.

◆ stasis_app_get_by_name()

struct stasis_app* stasis_app_get_by_name ( const char *  name)

Retrieve a handle to a Stasis application by its name.

Parameters
nameThe name of the registered Stasis application
Returns
stasis_app on success.
NULL on error.

Definition at line 1694 of file res_stasis.c.

References find_app_by_name().

Referenced by ari_set_debug(), ari_show_app(), ast_ari_applications_filter(), stasis_app_event_allowed(), stasis_app_get_debug_by_name(), stasis_app_set_debug_by_name(), and stasis_app_set_global_debug().

1695 {
1696  return find_app_by_name(name);
1697 }
static const char name[]
Definition: cdr_mysql.c:74
static struct stasis_app * find_app_by_name(const char *app_name)
Definition: res_stasis.c:1679

◆ stasis_app_get_sanitizer()

struct stasis_message_sanitizer* stasis_app_get_sanitizer ( void  )

◆ stasis_app_object_to_json()

struct ast_json* stasis_app_object_to_json ( struct stasis_app app)

Return the JSON representation of a Stasis application.

Since
16.3.0
Parameters
appThe application.
Returns
JSON representation of app with given name.
NULL on error.

Definition at line 1866 of file res_stasis.c.

References app_event_sources_to_json(), app_to_json(), NULL, and stasis_app_event_filter_to_json().

Referenced by app_handle_subscriptions(), ast_ari_applications_filter(), and stasis_app_to_json().

1867 {
1868  if (!app) {
1869  return NULL;
1870  }
1871 
1873  app, app_event_sources_to_json(app, app_to_json(app)));
1874 }
#define NULL
Definition: resample.c:96
struct ast_json * stasis_app_event_filter_to_json(struct stasis_app *app, struct ast_json *json)
Convert and add the app&#39;s event type filter(s) to the given json object.
struct ast_json * app_to_json(const struct stasis_app *app)
Create a JSON representation of a stasis_app.
static struct ast_json * app_event_sources_to_json(const struct stasis_app *app, struct ast_json *json)
Definition: res_stasis.c:1850

◆ stasis_app_register()

int stasis_app_register ( const char *  app_name,
stasis_app_cb  handler,
void *  data 
)

Register a new Stasis application.

If an application is already registered with the given name, the old application is sent a 'replaced' message and unregistered.

Parameters
app_nameName of this application.
handlerCallback for application messages.
dataData blob to pass to the callback. Must be AO2 managed.
Returns
0 for success
-1 for error.

Definition at line 1777 of file res_stasis.c.

References __stasis_app_register().

Referenced by AST_TEST_DEFINE(), and event_session_alloc().

1778 {
1779  return __stasis_app_register(app_name, handler, data, 0);
1780 }
static int __stasis_app_register(const char *app_name, stasis_app_cb handler, void *data, int all_events)
Definition: res_stasis.c:1726
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
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

◆ stasis_app_register_all()

int stasis_app_register_all ( const char *  app_name,
stasis_app_cb  handler,
void *  data 
)

Register a new Stasis application that receives all Asterisk events.

If an application is already registered with the given name, the old application is sent a 'replaced' message and unregistered.

Parameters
app_nameName of this application.
handlerCallback for application messages.
dataData blob to pass to the callback. Must be AO2 managed.
Returns
0 for success
-1 for error.

Definition at line 1782 of file res_stasis.c.

References __stasis_app_register().

Referenced by event_session_alloc().

1783 {
1784  return __stasis_app_register(app_name, handler, data, 1);
1785 }
static int __stasis_app_register(const char *app_name, stasis_app_cb handler, void *data, int all_events)
Definition: res_stasis.c:1726
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
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

◆ stasis_app_register_event_source()

void stasis_app_register_event_source ( struct stasis_app_event_source obj)

Register an application event source.

Parameters
objthe event source to register

Definition at line 1816 of file res_stasis.c.

References AST_LIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and stasis_app_register_event_sources().

1817 {
1819  AST_LIST_INSERT_TAIL(&event_sources, obj, next);
1821 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730

◆ stasis_app_send()

int stasis_app_send ( const char *  app_name,
struct ast_json message 
)

Send a message to the given Stasis application.

The message given to the handler is a borrowed copy. If you want to keep a reference to it, you should use ao2_ref() to keep it around.

Parameters
app_nameName of the application to invoke.
messageMessage to send (borrowed reference)
Returns
0 for success.
-1 for error.

Definition at line 1656 of file res_stasis.c.

References ao2_find, ao2_ref, app, app_send(), ast_log, LOG_WARNING, and OBJ_SEARCH_KEY.

Referenced by AST_TEST_DEFINE(), and send_device_state().

1657 {
1658  struct stasis_app *app;
1659 
1660  if (!apps_registry) {
1661  return -1;
1662  }
1663 
1665  if (!app) {
1666  /* XXX We can do a better job handling late binding, queueing up
1667  * the call for a few seconds to wait for the app to register.
1668  */
1670  "Stasis app '%s' not registered\n", app_name);
1671  return -1;
1672  }
1673  app_send(app, message);
1674  ao2_ref(app, -1);
1675 
1676  return 0;
1677 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void app_send(struct stasis_app *app, struct ast_json *message)
Send a message to the given application.
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
static const char app[]
Definition: app_mysql.c:62

◆ stasis_app_subscribe()

enum stasis_app_subscribe_res stasis_app_subscribe ( const char *  app_name,
const char **  event_source_uris,
int  event_sources_count,
struct ast_json **  json 
)

Subscribes an application to a list of event sources.

Parameters
app_nameName of the application to subscribe.
event_source_urisURIs for the event sources to subscribe to.
event_sources_countArray size of event_source_uris.
jsonOptional output pointer for JSON representation of the app after adding the subscription.
Returns
stasis_app_subscribe_res return code.
Note
Do not hold any channel locks if subscribing to a channel.

Definition at line 2045 of file res_stasis.c.

References app_handle_subscriptions(), and app_subscribe().

Referenced by ast_ari_applications_subscribe().

2048 {
2049  return app_handle_subscriptions(
2050  app_name, event_source_uris, event_sources_count,
2051  json, app_subscribe);
2052 }
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
static enum stasis_app_subscribe_res app_subscribe(struct stasis_app *app, const char *uri, struct stasis_app_event_source *event_source)
Definition: res_stasis.c:2019
static enum stasis_app_subscribe_res app_handle_subscriptions(const char *app_name, const char **event_source_uris, int event_sources_count, struct ast_json **json, app_subscription_handler handler)
Definition: res_stasis.c:1939

◆ stasis_app_subscribe_channel()

enum stasis_app_subscribe_res stasis_app_subscribe_channel ( const char *  app_name,
struct ast_channel chan 
)

Directly subscribe an application to a channel.

Parameters
app_nameName of the application to subscribe.
chanThe channel to subscribe to
Returns
stasis_app_subscribe_res return code.
Note
This method can be used when you already hold a channel and its lock. This bypasses the channel lookup that would normally be performed by stasis_app_subscribe.

Definition at line 1984 of file res_stasis.c.

References ao2_ref, app_subscribe_channel(), ast_channel_uniqueid(), ast_debug, ast_log, find_app_by_name(), LOG_ERROR, STASIS_ASR_APP_NOT_FOUND, STASIS_ASR_INTERNAL_ERROR, and STASIS_ASR_OK.

Referenced by ari_channels_handle_originate_with_id(), and ast_ari_channels_create().

1986 {
1988  int res;
1989 
1990  if (!app) {
1991  return STASIS_ASR_APP_NOT_FOUND;
1992  }
1993 
1994  ast_debug(3, "%s: Subscribing to %s\n", app_name, ast_channel_uniqueid(chan));
1995 
1996  res = app_subscribe_channel(app, chan);
1997  ao2_ref(app, -1);
1998 
1999  if (res != 0) {
2000  ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
2003  }
2004 
2005  return STASIS_ASR_OK;
2006 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define LOG_ERROR
Definition: logger.h:285
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan)
Subscribes an application to a channel.
static struct stasis_app * find_app_by_name(const char *app_name)
Definition: res_stasis.c:1679
static const char app[]
Definition: app_mysql.c:62

◆ stasis_app_to_json()

struct ast_json* stasis_app_to_json ( const char *  app_name)

Return the JSON representation of a Stasis application.

Parameters
app_nameName of the application.
Returns
JSON representation of app with given name.
NULL on error.

Definition at line 1876 of file res_stasis.c.

References ao2_cleanup, app, find_app_by_name(), and stasis_app_object_to_json().

Referenced by append_json(), and ast_ari_applications_get().

1877 {
1879  struct ast_json *json = stasis_app_object_to_json(app);
1880 
1881  ao2_cleanup(app);
1882 
1883  return json;
1884 }
struct ast_json * stasis_app_object_to_json(struct stasis_app *app)
Return the JSON representation of a Stasis application.
Definition: res_stasis.c:1866
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Abstract JSON element (object, array, string, int, ...).
static struct stasis_app * find_app_by_name(const char *app_name)
Definition: res_stasis.c:1679
static const char app[]
Definition: app_mysql.c:62

◆ stasis_app_unregister()

void stasis_app_unregister ( const char *  app_name)

Unregister a Stasis application.

Parameters
app_nameName of the application to unregister.

Definition at line 1787 of file res_stasis.c.

References ao2_find, ao2_ref, app, app_deactivate(), ast_log, cleanup(), LOG_ERROR, and OBJ_SEARCH_KEY.

Referenced by AST_TEST_DEFINE(), and event_session_shutdown().

1788 {
1789  struct stasis_app *app;
1790 
1791  if (!app_name) {
1792  return;
1793  }
1794 
1795  if (!apps_registry) {
1796  return;
1797  }
1798 
1800  if (!app) {
1802  "Stasis app '%s' not registered\n", app_name);
1803  return;
1804  }
1805 
1806  app_deactivate(app);
1807 
1808  /* There's a decent chance that app is ready for cleanup. Go ahead
1809  * and clean up, just in case
1810  */
1811  cleanup();
1812 
1813  ao2_ref(app, -1);
1814 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
void app_deactivate(struct stasis_app *app)
Deactivates an application.
#define ast_log
Definition: astobj2.c:42
static void cleanup(void)
Clean up any old apps that we don&#39;t need any more.
Definition: res_stasis.c:327
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define LOG_ERROR
Definition: logger.h:285
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
static const char app[]
Definition: app_mysql.c:62

◆ stasis_app_unregister_event_source()

void stasis_app_unregister_event_source ( struct stasis_app_event_source obj)

Unregister an application event source.

Parameters
objthe event source to unregister

Definition at line 1823 of file res_stasis.c.

References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and stasis_app_event_source::next.

Referenced by stasis_app_unregister_event_sources(), and unload_module().

1824 {
1825  struct stasis_app_event_source *source;
1826 
1829  if (source == obj) {
1831  break;
1832  }
1833  }
1836 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Event source information and callbacks.
Definition: stasis_app.h:174
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
struct stasis_app_event_source * next
Definition: stasis_app.h:227
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ stasis_app_unsubscribe()

enum stasis_app_subscribe_res stasis_app_unsubscribe ( const char *  app_name,
const char **  event_source_uris,
int  event_sources_count,
struct ast_json **  json 
)

Unsubscribes an application from a list of event sources.

Parameters
app_nameName of the application to subscribe.
event_source_urisURIs for the event sources to subscribe to.
event_sources_countArray size of event_source_uris.
jsonOptional output pointer for JSON representation of the app after adding the subscription.
Returns
stasis_app_subscribe_res return code.

Definition at line 2086 of file res_stasis.c.

References app_handle_subscriptions(), and app_unsubscribe().

Referenced by ast_ari_applications_unsubscribe().

2089 {
2090  return app_handle_subscriptions(
2091  app_name, event_source_uris, event_sources_count,
2092  json, app_unsubscribe);
2093 }
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
static enum stasis_app_subscribe_res app_handle_subscriptions(const char *app_name, const char **event_source_uris, int event_sources_count, struct ast_json **json, app_subscription_handler handler)
Definition: res_stasis.c:1939
static enum stasis_app_subscribe_res app_unsubscribe(struct stasis_app *app, const char *uri, struct stasis_app_event_source *event_source)
Definition: res_stasis.c:2064

◆ stasis_app_user_event()

enum stasis_app_user_event_res stasis_app_user_event ( const char *  app_name,
const char *  event_name,
const char **  source_uris,
int  sources_count,
struct ast_json json_variables 
)

Generate a Userevent for stasis app (echo to AMI)

Parameters
app_nameName of the application to generate event for/to.
event_nameName of the Userevent.
source_urisURIs for the source objects to attach to event.
sources_countArray size of source_uris.
json_variablesevent blob variables.
Returns
stasis_app_user_event_res return code.

Definition at line 2095 of file res_stasis.c.

References ao2_cleanup, ao2_ref, ast_app_get_topic(), ast_begins_with(), ast_bridge_get_snapshot_by_uniqueid(), ast_channel_snapshot_get_latest(), ast_endpoint_latest_snapshot(), ast_json_object_set(), ast_json_pack(), ast_json_ref(), ast_json_string_create(), ast_json_unref(), ast_log, ast_manager_get_topic(), ast_multi_object_blob_add(), ast_multi_object_blob_create(), ast_multi_user_event_type(), start_message_blob::blob, find_app_by_name(), LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, STASIS_APP_USER_APP_NOT_FOUND, STASIS_APP_USER_EVENT_SOURCE_BAD_SCHEME, STASIS_APP_USER_EVENT_SOURCE_NOT_FOUND, STASIS_APP_USER_INTERNAL_ERROR, STASIS_APP_USER_OK, stasis_message_create(), stasis_publish(), STASIS_UMOS_BRIDGE, STASIS_UMOS_CHANNEL, STASIS_UMOS_ENDPOINT, and type.

Referenced by ast_ari_events_user_event().

2099 {
2101  struct ast_json *blob = NULL;
2102  struct ast_multi_object_blob *multi;
2103  struct stasis_message *message;
2105  int have_channel = 0;
2106  int i;
2107 
2108  if (!app) {
2109  ast_log(LOG_WARNING, "App %s not found\n", app_name);
2111  }
2112 
2113  if (!ast_multi_user_event_type()) {
2114  return res;
2115  }
2116 
2117  if (json_variables) {
2118  struct ast_json *json_value = ast_json_string_create(event_name);
2119 
2120  if (json_value && !ast_json_object_set(json_variables, "eventname", json_value)) {
2121  blob = ast_json_ref(json_variables);
2122  }
2123  } else {
2124  blob = ast_json_pack("{s: s}", "eventname", event_name);
2125  }
2126 
2127  if (!blob) {
2128  ast_log(LOG_ERROR, "Failed to initialize blob\n");
2129 
2130  return res;
2131  }
2132 
2133  multi = ast_multi_object_blob_create(blob);
2134  ast_json_unref(blob);
2135  if (!multi) {
2136  ast_log(LOG_ERROR, "Failed to initialize multi\n");
2137 
2138  return res;
2139  }
2140 
2141  for (i = 0; i < sources_count; ++i) {
2142  const char *uri = source_uris[i];
2143  void *snapshot=NULL;
2145 
2146  if (ast_begins_with(uri, "channel:")) {
2147  type = STASIS_UMOS_CHANNEL;
2148  snapshot = ast_channel_snapshot_get_latest(uri + 8);
2149  have_channel = 1;
2150  } else if (ast_begins_with(uri, "bridge:")) {
2151  type = STASIS_UMOS_BRIDGE;
2152  snapshot = ast_bridge_get_snapshot_by_uniqueid(uri + 7);
2153  } else if (ast_begins_with(uri, "endpoint:")) {
2154  type = STASIS_UMOS_ENDPOINT;
2155  snapshot = ast_endpoint_latest_snapshot(uri + 9, NULL);
2156  } else {
2157  ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);
2158  ao2_ref(multi, -1);
2159 
2161  }
2162  if (!snapshot) {
2163  ast_log(LOG_ERROR, "Unable to get snapshot for %s\n", uri);
2164  ao2_ref(multi, -1);
2165 
2167  }
2168  ast_multi_object_blob_add(multi, type, snapshot);
2169  }
2170 
2172  ao2_ref(multi, -1);
2173 
2174  if (!message) {
2175  ast_log(LOG_ERROR, "Unable to create stasis user event message\n");
2176  return res;
2177  }
2178 
2179  /*
2180  * Publishing to two different topics is normally to be avoided -- except
2181  * in this case both are final destinations with no forwards (only listeners).
2182  * The message has to be delivered to the application topic for ARI, but a
2183  * copy is also delivered directly to the manager for AMI if there is a channel.
2184  */
2186 
2187  if (have_channel) {
2189  }
2190  ao2_ref(message, -1);
2191 
2192  return STASIS_APP_USER_OK;
2193 }
static const char type[]
Definition: chan_ooh323.c:109
struct stasis_topic * ast_app_get_topic(struct stasis_app *app)
Returns the stasis topic for an app.
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
struct ast_multi_object_blob * ast_multi_object_blob_create(struct ast_json *blob)
Create a stasis multi object blob.
Definition: stasis.c:1975
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
#define LOG_WARNING
Definition: logger.h:274
struct ast_endpoint_snapshot * ast_endpoint_latest_snapshot(const char *tech, const char *resource)
Retrieve the most recent snapshot for the endpoint with the given name.
#define NULL
Definition: resample.c:96
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 ast_log
Definition: astobj2.c:42
A multi object blob data structure to carry user event stasis messages.
Definition: stasis.c:1950
#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
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
#define ao2_ref(o, delta)
Definition: astobj2.h:464
stasis_user_multi_object_snapshot_type
Object type code for multi user object snapshots.
Definition: stasis.h:1357
#define LOG_ERROR
Definition: logger.h:285
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1720
void ast_multi_object_blob_add(struct ast_multi_object_blob *multi, enum stasis_user_multi_object_snapshot_type type, void *object)
Add an object to a multi object blob previously created.
Definition: stasis.c:2001
struct stasis_message_type * ast_multi_user_event_type(void)
Message type for custom user defined events with multi object blobs.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
stasis_app_user_event_res
Return code for stasis_app_user_event.
Definition: stasis_app.h:255
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Definition: strings.h:94
Abstract JSON element (object, array, string, int, ...).
static struct stasis_app * find_app_by_name(const char *app_name)
Definition: res_stasis.c:1679
static const char app[]
Definition: app_mysql.c:62
struct ast_bridge_snapshot * ast_bridge_get_snapshot_by_uniqueid(const char *bridge_id)
Returns the current snapshot for the bridge.

◆ stasis_end_to_json()

static struct ast_json* stasis_end_to_json ( struct stasis_message message,
const struct stasis_message_sanitizer sanitize 
)
static

Definition at line 115 of file res_stasis.c.

References ast_channel_snapshot_to_json(), ast_json_object_get(), ast_json_pack(), ast_log, ast_channel_blob::blob, stasis_message_sanitizer::channel_snapshot, LOG_ERROR, NULL, ast_channel_blob::snapshot, stasis_message_data(), and STASIS_MESSAGE_TYPE_DEFN_LOCAL().

117 {
118  struct ast_channel_blob *payload = stasis_message_data(message);
119  struct ast_json *msg;
120 
121  if (sanitize && sanitize->channel_snapshot &&
122  sanitize->channel_snapshot(payload->snapshot)) {
123  return NULL;
124  }
125 
126  msg = ast_json_pack("{s: s, s: O, s: o}",
127  "type", "StasisEnd",
128  "timestamp", ast_json_object_get(payload->blob, "timestamp"),
129  "channel", ast_channel_snapshot_to_json(payload->snapshot, sanitize));
130  if (!msg) {
131  ast_log(LOG_ERROR, "Failed to pack JSON for StasisEnd message\n");
132  return NULL;
133  }
134 
135  return msg;
136 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
int(* channel_snapshot)(const struct ast_channel_snapshot *snapshot)
Callback which determines whether a channel should be sanitized from a message based on the channel&#39;s...
Definition: stasis.h:221
struct ast_json * blob
struct ast_channel_snapshot * snapshot
#define NULL
Definition: resample.c:96
Blob of data associated with a channel.
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
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, ...).

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [1/2]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( end_message_type  ,
to_json = stasis_end_to_json 
)

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [2/2]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( start_message_type  ,
to_json = stasis_start_to_json 
)

◆ stasis_start_to_json()

static struct ast_json* stasis_start_to_json ( struct stasis_message message,
const struct stasis_message_sanitizer sanitize 
)
static

Definition at line 147 of file res_stasis.c.

References ast_channel_snapshot_to_json(), ast_json_object_get(), ast_json_object_set(), ast_json_pack(), ast_json_unref(), ast_log, start_message_blob::blob, start_message_blob::channel, stasis_message_sanitizer::channel_snapshot, LOG_ERROR, NULL, start_message_blob::replace_channel, stasis_message_data(), and STASIS_MESSAGE_TYPE_DEFN_LOCAL().

149 {
150  struct start_message_blob *payload = stasis_message_data(message);
151  struct ast_json *msg;
152 
153  if (sanitize && sanitize->channel_snapshot &&
154  sanitize->channel_snapshot(payload->channel)) {
155  return NULL;
156  }
157 
158  msg = ast_json_pack("{s: s, s: O, s: O, s: o}",
159  "type", "StasisStart",
160  "timestamp", ast_json_object_get(payload->blob, "timestamp"),
161  "args", ast_json_object_get(payload->blob, "args"),
162  "channel", ast_channel_snapshot_to_json(payload->channel, NULL));
163  if (!msg) {
164  ast_log(LOG_ERROR, "Failed to pack JSON for StasisStart message\n");
165  return NULL;
166  }
167 
168  if (payload->replace_channel) {
169  int res = ast_json_object_set(msg, "replace_channel",
171 
172  if (res) {
173  ast_json_unref(msg);
174  ast_log(LOG_ERROR, "Failed to append JSON for StasisStart message\n");
175  return NULL;
176  }
177  }
178 
179  return msg;
180 }
struct ast_channel_snapshot * replace_channel
Definition: res_stasis.c:143
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
int(* channel_snapshot)(const struct ast_channel_snapshot *snapshot)
Callback which determines whether a channel should be sanitized from a message based on the channel&#39;s...
Definition: stasis.h:221
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define NULL
Definition: resample.c:96
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 ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
struct ast_channel_snapshot * channel
Definition: res_stasis.c:142
struct ast_json * blob
Definition: res_stasis.c:144
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, ...).

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2195 of file res_stasis.c.

References ao2_cleanup, cleanup(), messaging_cleanup(), NULL, stasis_app_control_shutdown(), stasis_app_unregister_event_sources(), and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module().

2196 {
2198 
2200 
2201  cleanup();
2202 
2204 
2206  apps_registry = NULL;
2207 
2209  app_controls = NULL;
2210 
2212  app_bridges = NULL;
2213 
2216 
2219 
2220  STASIS_MESSAGE_TYPE_CLEANUP(end_message_type);
2221  STASIS_MESSAGE_TYPE_CLEANUP(start_message_type);
2222 
2223  return 0;
2224 }
int messaging_cleanup(void)
Tidy up the messaging layer.
Definition: messaging.c:529
struct ao2_container * app_bridges_moh
Definition: res_stasis.c:106
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
#define NULL
Definition: resample.c:96
struct ao2_container * app_bridges
Definition: res_stasis.c:104
struct ao2_container * app_controls
Definition: res_stasis.c:102
static void cleanup(void)
Clean up any old apps that we don&#39;t need any more.
Definition: res_stasis.c:327
void stasis_app_control_shutdown(void)
Let Stasis app internals shut down.
Definition: control.c:1680
struct ao2_container * app_bridges_playback
Definition: res_stasis.c:108
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
void stasis_app_unregister_event_sources(void)
Unregister core event sources.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Stasis application support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load_pri = AST_MODPRI_APP_DEPEND - 1, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, }
static

Definition at line 2379 of file res_stasis.c.

◆ app_bridges

struct ao2_container* app_bridges

Definition at line 104 of file res_stasis.c.

◆ app_bridges_moh

struct ao2_container* app_bridges_moh

Definition at line 106 of file res_stasis.c.

◆ app_bridges_playback

struct ao2_container* app_bridges_playback

Definition at line 108 of file res_stasis.c.

◆ app_controls

struct ao2_container* app_controls

Definition at line 102 of file res_stasis.c.

◆ app_sanitizer

struct stasis_message_sanitizer app_sanitizer
Initial value:
= {
.channel_id = channel_id_sanitizer,
.channel_snapshot = channel_snapshot_sanitizer,
.channel = channel_sanitizer,
}
static int channel_snapshot_sanitizer(const struct ast_channel_snapshot *snapshot)
Definition: res_stasis.c:2227
static int channel_id_sanitizer(const char *id)
Definition: res_stasis.c:2245
static int channel_sanitizer(const struct ast_channel *chan)
Definition: res_stasis.c:2236

Definition at line 2258 of file res_stasis.c.

Referenced by stasis_app_get_sanitizer().

◆ apps_registry

struct ao2_container* apps_registry

Stasis application container.

Definition at line 100 of file res_stasis.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2379 of file res_stasis.c.

◆ event_sources

struct event_sources event_sources = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }

◆ masquerade_store_info

const struct ast_datastore_info masquerade_store_info
static
Initial value:
= {
.type = "stasis-masqerade",
.chan_fixup = channel_stolen_cb,
.chan_breakdown = channel_replaced_cb,
}
static void channel_stolen_cb(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: res_stasis.c:1128
static void channel_replaced_cb(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: res_stasis.c:1159

Definition at line 1205 of file res_stasis.c.

◆ replace_channel_store_info

const struct ast_datastore_info replace_channel_store_info
static
Initial value:
= {
.type = "replace-channel-store",
}
static void replace_channel_destroy(void *obj)
Definition: res_stasis.c:876

Definition at line 885 of file res_stasis.c.

◆ set_end_published_info

struct ast_datastore_info set_end_published_info
Initial value:
= {
.type = "stasis_end_published",
}

Definition at line 1283 of file res_stasis.c.

◆ stasis_internal_channel_info

const struct ast_datastore_info stasis_internal_channel_info
static
Initial value:
= {
.type = "stasis-internal-channel",
}

Definition at line 2269 of file res_stasis.c.