Asterisk - The Open Source Telephony Project GIT-master-d856a3e
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)
 Sanitization callback for channel unique IDs. More...
 
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)
 Sanitization callback for channels. More...
 
static int channel_snapshot_sanitizer (const struct ast_channel_snapshot *snapshot)
 Sanitization callback for channel snapshots. More...
 
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[])
 Stasis dialplan application callback. 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
 Sanitization callbacks for communication to Stasis applications. More...
 
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.

◆ 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.

◆ 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.

◆ 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.

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

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2382 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 1729 of file res_stasis.c.

1730{
1731 RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
1732
1733 if (!apps_registry) {
1734 return -1;
1735 }
1736
1739 if (app) {
1740 /*
1741 * We need to unlock the apps_registry before calling app_update to
1742 * prevent the possibility of a deadlock with the session.
1743 */
1745 app_update(app, handler, data);
1746 cleanup();
1747 return 0;
1748 }
1749
1751 if (!app) {
1753 return -1;
1754 }
1755
1756 if (all_events) {
1757 struct stasis_app_event_source *source;
1758
1761 if (!source->subscribe) {
1762 continue;
1763 }
1764
1765 source->subscribe(app, NULL);
1766 }
1768 }
1770
1772
1773 /* We lazily clean up the apps_registry, because it's good enough to
1774 * prevent memory leaks, and we're lazy.
1775 */
1776 cleanup();
1777 return 0;
1778}
static const char app[]
Definition: app_adsiprog.c:56
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
void app_update(struct stasis_app *app, stasis_app_cb handler, void *data)
Update the handler and data for a res_stasis application.
struct stasis_app * app_create(const char *name, stasis_app_cb handler, void *data, enum stasis_app_subscription_model subscription_model)
Create a res_stasis application.
@ STASIS_APP_SUBSCRIBE_MANUAL
An application must manually subscribe to each resource that it cares about. This is the default appr...
@ STASIS_APP_SUBSCRIBE_ALL
An application is automatically subscribed to all resources in Asterisk, even if it does not control ...
static void cleanup(void)
Clean up any old apps that we don't need any more.
Definition: res_stasis.c:327
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
#define NULL
Definition: resample.c:96
Event source information and callbacks.
Definition: stasis_app.h:174
struct stasis_app_event_source * next
Definition: stasis_app.h:227
int(* subscribe)(struct stasis_app *app, void *obj)
Subscribe an application to an event source.
Definition: stasis_app.h:196
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ao2_find, ao2_link_flags, ao2_lock, ao2_unlock, app, app_create(), app_name(), app_update(), apps_registry, AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, cleanup(), handler(), 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().

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2382 of file res_stasis.c.

◆ add_masquerade_store()

static int add_masquerade_store ( struct ast_channel chan)
static

Definition at line 1220 of file res_stasis.c.

1221{
1222 struct ast_datastore *datastore;
1223
1224 SCOPED_CHANNELLOCK(lock, chan);
1226 return 0;
1227 }
1228
1230 if (!datastore) {
1231 return -1;
1232 }
1233
1234 ast_channel_datastore_add(chan, datastore);
1235
1236 return 0;
1237}
ast_mutex_t lock
Definition: app_sla.c:331
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2404
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:2418
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
static const struct ast_datastore_info masquerade_store_info
Definition: res_stasis.c:1208
Structure for a data store object.
Definition: datastore.h:64

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

Referenced by stasis_app_exec().

◆ 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.

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) {
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}
@ CMP_MATCH
Definition: astobj2.h:1027
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application's name.

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

Referenced by load_module().

◆ app_event_source_find()

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

Definition at line 1900 of file res_stasis.c.

1901{
1902 struct stasis_app_event_source *source;
1903
1906 if (ast_begins_with(uri, source->scheme)) {
1907 break;
1908 }
1909 }
1911
1912 return source;
1913}
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
const char * scheme
The scheme to match against on [un]subscribes.
Definition: stasis_app.h:176

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

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

1855{
1856 struct stasis_app_event_source *source;
1857
1860 if (source->to_json) {
1861 source->to_json(app, json);
1862 }
1863 }
1865
1866 return json;
1867}
void(* to_json)(const struct stasis_app *app, struct ast_json *json)
Convert event source data to json.
Definition: stasis_app.h:224

References app, 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().

◆ app_get_replace_channel_app()

char * app_get_replace_channel_app ( struct ast_channel chan)

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

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

Definition at line 970 of file res_stasis.c.

971{
973 char *replace_channel_app;
974
975 if (!replace) {
976 return NULL;
977 }
978
979 replace_channel_app = replace->app;
980 replace->app = NULL;
981
982 return replace_channel_app;
983}
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:888
static struct replace_channel_store * get_replace_channel_store(struct ast_channel *chan, int no_create)
Definition: res_stasis.c:893

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

Referenced by bridge_stasis_run_cb().

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

1946{
1948 int i;
1949
1951
1952 if (!app) {
1954 }
1955
1956 for (i = 0; i < event_sources_count; ++i) {
1957 const char *uri = event_source_uris[i];
1958 struct stasis_app_event_source *event_source;
1959 enum stasis_app_subscribe_res res;
1960
1961 event_source = app_event_source_find(uri);
1962 if (!event_source) {
1963 ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);
1964 ao2_ref(app, -1);
1965
1967 }
1968
1969 res = handler(app, uri, event_source);
1970 if (res != STASIS_ASR_OK) {
1971 ao2_ref(app, -1);
1972
1973 return res;
1974 }
1975 }
1976
1977 if (json) {
1978 ast_debug(3, "%s: Successful; setting results\n", app_name);
1980 }
1981
1982 ao2_ref(app, -1);
1983
1984 return STASIS_ASR_OK;
1985}
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
struct ast_json * stasis_app_object_to_json(struct stasis_app *app)
Return the JSON representation of a Stasis application.
Definition: res_stasis.c:1869
static struct stasis_app * find_app_by_name(const char *app_name)
Definition: res_stasis.c:1682
static struct stasis_app_event_source * app_event_source_find(const char *uri)
Definition: res_stasis.c:1900
stasis_app_subscribe_res
Return code for stasis_app_[un]subscribe.
Definition: stasis_app.h:282
@ STASIS_ASR_OK
Definition: stasis_app.h:283
@ STASIS_ASR_EVENT_SOURCE_BAD_SCHEME
Definition: stasis_app.h:286
@ STASIS_ASR_APP_NOT_FOUND
Definition: stasis_app.h:284
#define ast_assert(a)
Definition: utils.h:739

References ao2_ref, app, app_event_source_find(), app_name(), 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().

◆ 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.

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;
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}
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259

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

Referenced by load_module().

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

1087{
1089 struct ast_json *blob;
1090 struct stasis_message *msg;
1091
1092 if (sanitize && sanitize->channel
1093 && sanitize->channel(chan)) {
1094 return 0;
1095 }
1096
1097 blob = ast_json_pack("{s: s, s: o}",
1098 "app", stasis_app_name(app),
1099 "timestamp", ast_json_timeval(ast_tvnow(), NULL)
1100 );
1101 if (!blob) {
1102 ast_log(LOG_ERROR, "Error packing JSON for StasisEnd message\n");
1103 return -1;
1104 }
1105
1108 msg = ast_channel_blob_create(chan, end_message_type(), blob);
1109 if (msg) {
1111 }
1112 ao2_cleanup(msg);
1113 ast_json_unref(blob);
1114
1115 return 0;
1116}
struct stasis_message * ast_channel_blob_create(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Creates a ast_channel_blob message.
#define LOG_ERROR
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:670
int app_unsubscribe_channel(struct stasis_app *app, struct ast_channel *chan)
Cancel the subscription an app has for a channel.
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
Definition: res_stasis.c:2267
static void remove_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1239
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1512
struct stasis_topic * ast_app_get_topic(struct stasis_app *app)
Returns the stasis topic for an app.
Abstract JSON element (object, array, string, int, ...).
Structure containing callbacks for Stasis message sanitization.
Definition: stasis.h:200
int(* channel)(const struct ast_channel *chan)
Callback which determines whether a channel should be sanitized from a message based on the channel.
Definition: stasis.h:232
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

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

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

◆ app_set_replace_channel_app()

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

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

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

Definition at line 934 of file res_stasis.c.

935{
937
938 if (!replace) {
939 return -1;
940 }
941
942 ast_free(replace->app);
943 replace->app = NULL;
944
945 if (replace_app) {
946 replace->app = ast_strdup(replace_app);
947 if (!replace->app) {
948 return -1;
949 }
950 }
951
952 return 0;
953}
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241

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

Referenced by bridge_stasis_push_peek().

◆ app_set_replace_channel_snapshot()

int app_set_replace_channel_snapshot ( struct ast_channel chan,
struct ast_channel_snapshot replace_snapshot 
)

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

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

Definition at line 922 of file res_stasis.c.

923{
925
926 if (!replace) {
927 return -1;
928 }
929
930 ao2_replace(replace->snapshot, replace_snapshot);
931 return 0;
932}
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501

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

Referenced by bridge_stasis_push_peek().

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

2025{
2026 const char *app_name = stasis_app_name(app);
2027 RAII_VAR(void *, obj, NULL, ao2_cleanup);
2028
2029 ast_debug(3, "%s: Checking %s\n", app_name, uri);
2030
2031 if (!ast_strlen_zero(uri + strlen(event_source->scheme)) &&
2032 (!event_source->find || (!(obj = event_source->find(app, uri + strlen(event_source->scheme)))))) {
2033 ast_log(LOG_WARNING, "Event source not found: %s\n", uri);
2035 }
2036
2037 ast_debug(3, "%s: Subscribing to %s\n", app_name, uri);
2038
2039 if (!event_source->subscribe || (event_source->subscribe(app, obj))) {
2040 ast_log(LOG_WARNING, "Error subscribing app '%s' to '%s'\n",
2041 app_name, uri);
2043 }
2044
2045 return STASIS_ASR_OK;
2046}
@ STASIS_ASR_INTERNAL_ERROR
Definition: stasis_app.h:287
@ STASIS_ASR_EVENT_SOURCE_NOT_FOUND
Definition: stasis_app.h:285
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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

References ao2_cleanup, app, 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().

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

2070{
2071 const char *app_name = stasis_app_name(app);
2072 const char *id = uri + strlen(event_source->scheme);
2073
2074 if (!event_source->is_subscribed ||
2075 (!event_source->is_subscribed(app, id))) {
2077 }
2078
2079 ast_debug(3, "%s: Unsubscribing from %s\n", app_name, uri);
2080
2081 if (!event_source->unsubscribe || (event_source->unsubscribe(app, id))) {
2082 ast_log(LOG_WARNING, "Error unsubscribing app '%s' to '%s'\n",
2083 app_name, uri);
2084 return -1;
2085 }
2086 return 0;
2087}
int(* unsubscribe)(struct stasis_app *app, const char *id)
Cancel the subscription an app has to an event source.
Definition: stasis_app.h:206
int(* is_subscribed)(struct stasis_app *app, const char *id)
Find an event source by the given id/name.
Definition: stasis_app.h:216

References app, 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().

◆ append_name()

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

Definition at line 1702 of file res_stasis.c.

1703{
1704 struct stasis_app *app = obj;
1705 struct ao2_container *apps = arg;
1706
1708 return 0;
1709}
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:205
Generic container type.
Registered applications container.
Definition: pbx_app.c:67

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

Referenced by stasis_app_get_all().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 2382 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.

796{
797 struct ast_bridge *bridge;
798 char *requested_type, *requested_types = ast_strdupa(S_OR(type, "mixing"));
799 int capabilities = 0;
804 int send_sdp_label = 0;
805
806 if (invisible) {
808 }
809
810 while ((requested_type = strsep(&requested_types, ","))) {
811 requested_type = ast_strip(requested_type);
812
813 if (!strcmp(requested_type, "mixing")) {
814 capabilities |= STASIS_BRIDGE_MIXING_CAPABILITIES;
815 flags |= AST_BRIDGE_FLAG_SMART;
816 } else if (!strcmp(requested_type, "holding")) {
817 capabilities |= AST_BRIDGE_CAPABILITY_HOLDING;
818 } else if (!strcmp(requested_type, "dtmf_events") ||
819 !strcmp(requested_type, "proxy_media")) {
820 capabilities &= ~AST_BRIDGE_CAPABILITY_NATIVE;
821 } else if (!strcmp(requested_type, "video_sfu")) {
822 video_mode = AST_BRIDGE_VIDEO_MODE_SFU;
823 } else if (!strcmp(requested_type, "video_single")) {
825 } else if (!strcmp(requested_type, "sdp_label")) {
826 send_sdp_label = 1;
827 }
828 }
829
830 /* For an SFU video bridge we ensure it always remains in multimix for the best experience. */
831 if (video_mode == AST_BRIDGE_VIDEO_MODE_SFU) {
832 capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
833 flags &= ~AST_BRIDGE_FLAG_SMART;
834 }
835
836 if (!capabilities
837 /* Holding and mixing capabilities don't mix. */
838 || ((capabilities & AST_BRIDGE_CAPABILITY_HOLDING)
839 && (capabilities & (STASIS_BRIDGE_MIXING_CAPABILITIES)))) {
840 return NULL;
841 }
842
843 bridge = bridge_stasis_new(capabilities, flags, name, id, video_mode, send_sdp_label);
844 if (bridge) {
845 if (!ao2_link(app_bridges, bridge)) {
846 ast_bridge_destroy(bridge, 0);
847 bridge = NULL;
848 }
849 }
850
851 return bridge;
852}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944
@ AST_BRIDGE_CAPABILITY_MULTIMIX
Definition: bridge.h:94
@ AST_BRIDGE_CAPABILITY_HOLDING
Definition: bridge.h:86
ast_bridge_video_mode_type
Video source modes.
Definition: bridge.h:98
@ AST_BRIDGE_VIDEO_MODE_SINGLE_SRC
Definition: bridge.h:102
@ AST_BRIDGE_VIDEO_MODE_TALKER_SRC
Definition: bridge.h:105
@ AST_BRIDGE_VIDEO_MODE_SFU
Definition: bridge.h:109
@ AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY
@ AST_BRIDGE_FLAG_SWAP_INHIBIT_TO
@ AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO
@ AST_BRIDGE_FLAG_SMART
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
@ AST_BRIDGE_FLAG_INVISIBLE
static const char type[]
Definition: chan_ooh323.c:109
static const char name[]
Definition: format_mp3.c:68
char * strsep(char **str, const char *delims)
struct ao2_container * app_bridges
Definition: res_stasis.c:104
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, unsigned int send_sdp_label)
#define STASIS_BRIDGE_MIXING_CAPABILITIES
Definition: stasis_bridge.h:39
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
Structure that contains information about a bridge.
Definition: bridge.h:349

References ao2_link, app_bridges, AST_BRIDGE_CAPABILITY_HOLDING, AST_BRIDGE_CAPABILITY_MULTIMIX, 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(), name, NULL, S_OR, STASIS_BRIDGE_MIXING_CAPABILITIES, strsep(), and type.

Referenced by stasis_app_bridge_create(), and stasis_app_bridge_create_invisible().

◆ bridge_moh_create()

static struct ast_channel * bridge_moh_create ( struct ast_bridge bridge)
static

Definition at line 574 of file res_stasis.c.

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
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}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
@ AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE
@ AST_BRIDGE_CHANNEL_FLAG_LONELY
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2560
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define AST_CHANNEL_NAME
Definition: channel.h:173
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
static void stasis_app_bridge_channel_wrapper_destructor(void *obj)
Definition: res_stasis.c:455
struct ao2_container * app_bridges_moh
Definition: res_stasis.c:106
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.
Definition: res_stasis.c:2291
static struct ast_channel * prepare_bridge_moh_channel(void)
Definition: res_stasis.c:510
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:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
const ast_string_field uniqueid
Definition: bridge.h:401
Main Channel structure associated with a channel.
struct ast_bridge * bridge
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588
#define AST_UUID_STR_LEN
Definition: uuid.h:27

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_link_flags, ao2_ref, ao2_unlink_flags, app_bridges_moh, 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, ast_channel::bridge, 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().

◆ 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.

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) {
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}
const ast_string_field bridge_id
Definition: res_stasis.c:425

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

◆ 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.

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

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

◆ 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.

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) {
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}

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

◆ 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.

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) {
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}

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

Referenced by load_module().

◆ 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.

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

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

Referenced by load_module().

◆ channel_id_sanitizer()

static int channel_id_sanitizer ( const char *  id)
static

Sanitization callback for channel unique IDs.

Definition at line 2248 of file res_stasis.c.

2249{
2250 struct ast_channel_snapshot *snapshot;
2251 int ret;
2252
2253 snapshot = ast_channel_snapshot_get_latest(id);
2254 ret = channel_snapshot_sanitizer(snapshot);
2255 ao2_cleanup(snapshot);
2256
2257 return ret;
2258}
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,...
static int channel_snapshot_sanitizer(const struct ast_channel_snapshot *snapshot)
Sanitization callback for channel snapshots.
Definition: res_stasis.c:2230
Structure representing a snapshot of channel state.

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

◆ channel_replaced_cb()

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

Definition at line 1162 of file res_stasis.c.

1163{
1164 RAII_VAR(struct ast_channel_snapshot *, new_snapshot, NULL, ao2_cleanup);
1165 RAII_VAR(struct ast_channel_snapshot *, old_snapshot, NULL, ao2_cleanup);
1166 struct stasis_app_control *control;
1167
1168 /* At this point, new_chan is the channel pointer that is in Stasis() and
1169 * has the unknown channel's name in it while old_chan is the channel pointer
1170 * that is not in Stasis(), but has the guts of the channel that Stasis() knows
1171 * about */
1172
1173 /* grab a snapshot for the channel that is jumping into Stasis() */
1174 new_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(new_chan));
1175 if (!new_snapshot) {
1176 ast_log(LOG_ERROR, "Could not get snapshot for masquerading channel\n");
1177 return;
1178 }
1179
1180 /* grab a snapshot for the channel that has been kicked out of Stasis() */
1181 old_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(old_chan));
1182 if (!old_snapshot) {
1183 ast_log(LOG_ERROR, "Could not get snapshot for masqueraded channel\n");
1184 return;
1185 }
1186
1187 /*
1188 * Find, unlink, and relink control since the channel has a new
1189 * name/uniqueid and its hash has changed.
1190 */
1191 control = ao2_callback(app_controls, OBJ_UNLINK, masq_match_cb, new_chan);
1192 if (!control) {
1193 ast_log(LOG_ERROR, "Could not find control for masquerading channel\n");
1194 return;
1195 }
1196 ao2_link(app_controls, control);
1197
1198
1199 /* send the StasisStart with replace_channel to the app */
1200 send_start_msg_snapshots(new_chan, control_app(control), 0, NULL, new_snapshot,
1201 old_snapshot);
1202 /* send the StasisEnd message to the app */
1203 app_send_end_msg(control_app(control), old_chan);
1204
1205 ao2_cleanup(control);
1206}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
@ OBJ_UNLINK
Definition: astobj2.h:1039
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:1572
struct ao2_container * app_controls
Definition: res_stasis.c:102
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:994
int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
Send StasisEnd message to the listening app.
Definition: res_stasis.c:1086
static int masq_match_cb(void *obj, void *data, int flags)
Definition: res_stasis.c:1118

References ao2_callback, ao2_cleanup, ao2_link, app_controls, 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().

◆ channel_sanitizer()

static int channel_sanitizer ( const struct ast_channel chan)
static

Sanitization callback for channels.

Definition at line 2239 of file res_stasis.c.

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

References AST_CHAN_TP_INTERNAL, and ast_channel_tech().

◆ channel_snapshot_sanitizer()

static int channel_snapshot_sanitizer ( const struct ast_channel_snapshot snapshot)
static

Sanitization callback for channel snapshots.

Definition at line 2230 of file res_stasis.c.

2231{
2232 if (!snapshot || !(snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL)) {
2233 return 0;
2234 }
2235 return 1;
2236}
struct ast_channel_snapshot_base * base

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

Referenced by channel_id_sanitizer().

◆ channel_stolen_cb()

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

Definition at line 1131 of file res_stasis.c.

1132{
1133 struct stasis_app_control *control;
1134
1135 /*
1136 * At this point, old_chan is the channel pointer that is in Stasis() and
1137 * has the unknown channel's name in it while new_chan is the channel pointer
1138 * that is not in Stasis(), but has the guts of the channel that Stasis() knows
1139 * about.
1140 *
1141 * Find and unlink control since the channel has a new name/uniqueid
1142 * and its hash has changed. Since the channel is leaving stasis don't
1143 * bother putting it back into the container. Nobody is going to
1144 * remove it from the container later.
1145 */
1146 control = ao2_callback(app_controls, OBJ_UNLINK, masq_match_cb, old_chan);
1147 if (!control) {
1148 ast_log(LOG_ERROR, "Could not find control for masqueraded channel\n");
1149 return;
1150 }
1151
1152 /* send the StasisEnd message to the app */
1154 app_send_end_msg(control_app(control), new_chan);
1155
1156 /* remove the datastore */
1157 remove_masquerade_store(old_chan);
1158
1159 ao2_cleanup(control);
1160}
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:1290

References ao2_callback, ao2_cleanup, app_controls, 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().

◆ 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.

328{
331}
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
static int cleanup_cb(void *obj, void *arg, int flags)
Definition: res_stasis.c:309

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

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

◆ cleanup_cb()

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

Definition at line 309 of file res_stasis.c.

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));
319
320 return CMP_MATCH;
321
322}
#define ast_verb(level,...)
void app_shutdown(struct stasis_app *app)
Tears down an application.
int app_is_finished(struct stasis_app *app)
Checks whether a deactivated app has no channels.

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

Referenced by ast_sched_clean_by_callback(), and cleanup().

◆ 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.

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) {
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}
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:1439

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

◆ 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.

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;
258 control = obj;
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}

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

◆ 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.

786{
787 if (!control) {
788 return;
789 }
790
791 ao2_unlink(app_controls, control);
792 ao2_cleanup(control);
793}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578

References ao2_cleanup, ao2_unlink, and app_controls.

Referenced by stasis_app_exec().

◆ find_app_by_name()

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

Definition at line 1682 of file res_stasis.c.

1683{
1684 struct stasis_app *res = NULL;
1685
1686 if (!apps_registry) {
1687 return NULL;
1688 }
1689
1690 if (!ast_strlen_zero(app_name)) {
1692 }
1693
1694 return res;
1695}

References ao2_find, app_name(), apps_registry, 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().

◆ get_replace_channel_snapshot()

static struct ast_channel_snapshot * get_replace_channel_snapshot ( struct ast_channel chan)
static

Definition at line 955 of file res_stasis.c.

956{
958 struct ast_channel_snapshot *replace_channel_snapshot;
959
960 if (!replace) {
961 return NULL;
962 }
963
964 replace_channel_snapshot = replace->snapshot;
965 replace->snapshot = NULL;
966
967 return replace_channel_snapshot;
968}

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

Referenced by send_start_msg().

◆ get_replace_channel_store()

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

Definition at line 893 of file res_stasis.c.

894{
895 struct ast_datastore *datastore;
896 struct replace_channel_store *ret;
897
898 ast_channel_lock(chan);
900 if (!datastore && !no_create) {
902 if (datastore) {
903 ast_channel_datastore_add(chan, datastore);
904 }
905 }
906
907 if (!datastore) {
908 ast_channel_unlock(chan);
909 return NULL;
910 }
911
912 if (!datastore->data) {
913 datastore->data = ast_calloc(1, sizeof(struct replace_channel_store));
914 }
915
916 ret = datastore->data;
917 ast_channel_unlock(chan);
918
919 return ret;
920}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_channel_lock(chan)
Definition: channel.h:2968
#define ast_channel_unlock(chan)
Definition: channel.h:2969
static const struct ast_datastore_info replace_channel_store_info
Definition: res_stasis.c:888
void * data
Definition: datastore.h:66

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

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

◆ has_masquerade_store()

static int has_masquerade_store ( struct ast_channel chan)
static

Definition at line 1214 of file res_stasis.c.

1215{
1216 SCOPED_CHANNELLOCK(lock, chan);
1218}

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

Referenced by stasis_app_exec().

◆ load_module()

static int load_module ( void  )
static

Definition at line 2340 of file res_stasis.c.

2341{
2342 if (STASIS_MESSAGE_TYPE_INIT(start_message_type) != 0) {
2344 }
2345 if (STASIS_MESSAGE_TYPE_INIT(end_message_type) != 0) {
2347 }
2361 unload_module();
2363 }
2364
2365 if (messaging_init()) {
2366 unload_module();
2368 }
2369
2371
2373
2375}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
Definition: astobj2.h:1188
int messaging_init(void)
Initialize the messaging layer.
Definition: messaging.c:539
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
struct ao2_container * app_bridges_playback
Definition: res_stasis.c:108
#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
static int bridges_compare(void *obj, void *arg, int flags)
Definition: res_stasis.c:378
static int app_compare(void *obj, void *arg, int flags)
Definition: res_stasis.c:208
static int bridges_hash(const void *obj, const int flags)
Definition: res_stasis.c:356
static int app_hash(const void *obj, const int flags)
Definition: res_stasis.c:186
#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
static int control_hash(const void *obj, const int flags)
Definition: res_stasis.c:248
#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
static int bridges_channel_sort_fn(const void *obj_left, const void *obj_right, const int flags)
Definition: res_stasis.c:483
static int bridges_channel_compare(void *obj, void *arg, int flags)
Definition: res_stasis.c:429
static int unload_module(void)
Definition: res_stasis.c:2198
static int bridges_channel_hash_fn(const void *obj, const int flags)
Definition: res_stasis.c:462
static int control_compare(void *obj, void *arg, int flags)
Definition: res_stasis.c:270
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
void stasis_app_register_event_sources(void)
Register core event sources.
void bridge_stasis_init(void)

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, app_bridges, app_bridges_moh, app_bridges_playback, app_compare(), app_controls, app_hash(), APPS_NUM_BUCKETS, apps_registry, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, 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().

◆ masq_match_cb()

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

Definition at line 1118 of file res_stasis.c.

1119{
1120 struct stasis_app_control *control = obj;
1121 struct ast_channel *chan = data;
1122
1123 if (!strcmp(ast_channel_uniqueid(chan),
1125 return CMP_MATCH;
1126 }
1127
1128 return 0;
1129}
const char * data

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

◆ 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.

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}
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3181
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4276
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1473
#define ast_frfree(fr)
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7798
Data structure associated with a single frame of data.
const ast_string_field channel_id
Definition: res_stasis.c:425

References ao2_ref, ao2_unlink, app_bridges_moh, 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().

◆ 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.

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

References remove_bridge_playback().

Referenced by stasis_app_bridge_playback_channel_add().

◆ 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.

692{
693 char *bridge_id = data;
694
695 remove_bridge_playback(bridge_id);
696}

References remove_bridge_playback().

Referenced by stasis_app_bridge_playback_channel_add().

◆ 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.

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}
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:6373
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54

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

◆ 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.

674{
675 struct stasis_app_bridge_channel_wrapper *wrapper;
676 struct stasis_app_control *control;
677
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}
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

References ao2_find, ao2_ref, ao2_unlink, app_bridges_playback, app_controls, 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().

◆ remove_masquerade_store()

static void remove_masquerade_store ( struct ast_channel chan)
static

Definition at line 1239 of file res_stasis.c.

1240{
1241 struct ast_datastore *datastore;
1242
1243 SCOPED_CHANNELLOCK(lock, chan);
1245 if (!datastore) {
1246 return;
1247 }
1248
1249 ast_channel_datastore_remove(chan, datastore);
1250 ast_datastore_free(datastore);
1251}
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2413
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68

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

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

◆ remove_stasis_end_published()

static void remove_stasis_end_published ( struct ast_channel chan)
static

Definition at line 1313 of file res_stasis.c.

1314{
1315 struct ast_datastore *datastore;
1316
1317 ast_channel_lock(chan);
1319 if (datastore) {
1320 ast_channel_datastore_remove(chan, datastore);
1321 ast_datastore_free(datastore);
1322 }
1323 ast_channel_unlock(chan);
1324}
struct ast_datastore_info set_end_published_info
Definition: res_stasis.c:1286

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

Referenced by stasis_app_exec().

◆ replace_channel_destroy()

static void replace_channel_destroy ( void *  obj)
static

Definition at line 879 of file res_stasis.c.

880{
881 struct replace_channel_store *replace = obj;
882
883 ao2_cleanup(replace->snapshot);
884 ast_free(replace->app);
886}

References ao2_cleanup, ast_free, and replace().

◆ send_start_msg()

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

Definition at line 1060 of file res_stasis.c.

1062{
1063 int ret = -1;
1064 struct ast_channel_snapshot *snapshot;
1065 struct ast_channel_snapshot *replace_channel_snapshot;
1066
1067 ast_assert(chan != NULL);
1068
1069 replace_channel_snapshot = get_replace_channel_snapshot(chan);
1070
1071 /* Set channel info */
1072 ast_channel_lock(chan);
1073 snapshot = ast_channel_snapshot_create(chan);
1074 ast_channel_unlock(chan);
1075 if (snapshot) {
1076 ret = send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot);
1077 ao2_ref(snapshot, -1);
1078 }
1079 ao2_cleanup(replace_channel_snapshot);
1080
1081 return ret;
1082}
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 struct ast_channel_snapshot * get_replace_channel_snapshot(struct ast_channel *chan)
Definition: res_stasis.c:955

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

Referenced by stasis_app_exec().

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

997{
998 struct ast_json *json_blob;
999 struct ast_json *json_args;
1000 struct start_message_blob *payload;
1001 struct stasis_message *msg;
1002 int i;
1003
1004 if (app_subscribe_channel(app, chan)) {
1005 ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
1007 return -1;
1008 }
1009
1010 payload = ao2_alloc(sizeof(*payload), start_message_blob_dtor);
1011 if (!payload) {
1012 ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
1013 return -1;
1014 }
1015
1016 payload->channel = ao2_bump(snapshot);
1017 payload->replace_channel = ao2_bump(replace_channel_snapshot);
1018
1019 json_blob = ast_json_pack("{s: s, s: o, s: []}",
1020 "app", stasis_app_name(app),
1021 "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1022 "args");
1023 if (!json_blob) {
1024 ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
1025 ao2_ref(payload, -1);
1026 return -1;
1027 }
1028 payload->blob = json_blob;
1029
1030
1031 /* Append arguments to args array */
1032 json_args = ast_json_object_get(json_blob, "args");
1033 ast_assert(json_args != NULL);
1034 for (i = 0; i < argc; ++i) {
1035 int r = ast_json_array_append(json_args,
1036 ast_json_string_create(argv[i]));
1037 if (r != 0) {
1038 ast_log(LOG_ERROR, "Error appending to StasisStart message\n");
1039 ao2_ref(payload, -1);
1040 return -1;
1041 }
1042 }
1043
1044
1045 msg = stasis_message_create(start_message_type(), payload);
1046 ao2_ref(payload, -1);
1047 if (!msg) {
1048 ast_log(LOG_ERROR, "Error sending StasisStart message\n");
1049 return -1;
1050 }
1051
1052 if (replace_channel_snapshot) {
1053 app_unsubscribe_channel_id(app, replace_channel_snapshot->base->uniqueid);
1054 }
1056 ao2_ref(msg, -1);
1057 return 0;
1058}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan)
Subscribes an application to a channel.
int app_unsubscribe_channel_id(struct stasis_app *app, const char *channel_id)
Cancel the subscription an app has for a channel.
static void start_message_blob_dtor(void *obj)
Definition: res_stasis.c:985
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
const ast_string_field uniqueid
struct ast_channel_snapshot * replace_channel
Definition: res_stasis.c:143
struct ast_channel_snapshot * channel
Definition: res_stasis.c:142
struct ast_json * blob
Definition: res_stasis.c:144

References ao2_alloc, ao2_bump, ao2_ref, app, 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().

◆ set_internal_datastore()

static int set_internal_datastore ( struct ast_channel chan)
static

Definition at line 2276 of file res_stasis.c.

2277{
2278 struct ast_datastore *datastore;
2279
2281 if (!datastore) {
2283 if (!datastore) {
2284 return -1;
2285 }
2286 ast_channel_datastore_add(chan, datastore);
2287 }
2288 return 0;
2289}
static const struct ast_datastore_info stasis_internal_channel_info
Definition: res_stasis.c:2272

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

Referenced by stasis_app_channel_set_internal(), and stasis_app_channel_unreal_set_internal().

◆ start_message_blob_dtor()

static void start_message_blob_dtor ( void *  obj)
static

Definition at line 985 of file res_stasis.c.

986{
987 struct start_message_blob *payload = obj;
988
989 ao2_cleanup(payload->channel);
991 ast_json_unref(payload->blob);
992}

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

◆ 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.

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:374

References ast_string_field_free_memory.

Referenced by bridge_moh_create(), and stasis_app_bridge_playback_channel_add().

◆ 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.
Return values
NULLon error.

Definition at line 854 of file res_stasis.c.

855{
856 return bridge_create_common(type, name, id, 0);
857}
static struct ast_bridge * bridge_create_common(const char *type, const char *name, const char *id, int invisible)
Definition: res_stasis.c:795

References bridge_create_common(), name, and type.

Referenced by ast_ari_bridges_create(), and ast_ari_bridges_create_with_id().

◆ 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.
Return values
NULLon error.

Definition at line 859 of file res_stasis.c.

860{
861 return bridge_create_common(type, name, id, 1);
862}

References bridge_create_common(), name, and type.

Referenced by get_dial_bridge().

◆ stasis_app_bridge_destroy()

void stasis_app_bridge_destroy ( const char *  bridge_id)

Destroy the bridge.

Parameters
bridge_idUniqueid of bridge to be destroyed

Definition at line 864 of file res_stasis.c.

865{
866 struct ast_bridge *bridge = stasis_app_bridge_find_by_id(bridge_id);
867 if (!bridge) {
868 return;
869 }
870 ao2_unlink(app_bridges, bridge);
871 ast_bridge_destroy(bridge, 0);
872}
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

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

Referenced by ast_ari_bridges_destroy().

◆ 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.

776{
777 return ao2_find(app_bridges, bridge_id, OBJ_SEARCH_KEY);
778}

References ao2_find, app_bridges, and OBJ_SEARCH_KEY.

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

◆ 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.

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}
static struct ast_channel * bridge_moh_create(struct ast_bridge *bridge)
Definition: res_stasis.c:574

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, app_bridges_moh, 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().

◆ 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.

650{
651 struct stasis_app_bridge_channel_wrapper *moh_wrapper;
652 struct ast_channel *chan;
653
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}
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2490

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

Referenced by ast_ari_bridges_stop_moh().

◆ 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)
controlThe app control structure for the playback channel
Return values
-1failed to add channel for any reason
0on success

Definition at line 705 of file res_stasis.c.

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}
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:251
static void playback_after_bridge_cb(struct ast_channel *chan, void *data)
Definition: res_stasis.c:698
static void playback_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition: res_stasis.c:691

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_link, app_bridges_playback, app_controls, ast_bridge_set_after_callback(), ast_channel_uniqueid(), ast_free, ast_strdup, ast_string_field_init, ast_string_field_set, stasis_app_control::bridge, 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().

◆ 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.

760{
761 struct stasis_app_bridge_channel_wrapper *playback_wrapper;
762 struct ast_channel *chan;
763
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}

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

Referenced by ari_bridges_handle_play().

◆ 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.

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}

References ao2_find, ao2_ref, ao2_unlink, app_bridges_playback, app_controls, stasis_app_bridge_channel_wrapper::bridge_id, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by ari_bridges_play_new(), and bridge_channel_control_thread().

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

2326{
2327 struct ast_datastore *datastore;
2328 int res = 0;
2329
2330 ast_channel_lock(chan);
2332 if (datastore) {
2333 res = 1;
2334 }
2335 ast_channel_unlock(chan);
2336
2337 return res;
2338}

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

Referenced by bridge_stasis_push().

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

1303{
1304 struct ast_datastore *datastore;
1305
1306 ast_channel_lock(chan);
1308 ast_channel_unlock(chan);
1309
1310 return datastore ? 1 : 0;
1311}

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

Referenced by internal_bridge_after_cb(), and stasis_app_exec().

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

2315{
2316 int res;
2317
2318 ast_channel_lock(chan);
2319 res = set_internal_datastore(chan);
2320 ast_channel_unlock(chan);
2321
2322 return res;
2323}
static int set_internal_datastore(struct ast_channel *chan)
Definition: res_stasis.c:2276

References ast_channel_lock, ast_channel_unlock, ast_unreal_pvt::chan, and set_internal_datastore().

◆ 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
chanThe channel that is exiting Stasis.

Definition at line 1290 of file res_stasis.c.

1291{
1292 struct ast_datastore *datastore;
1293
1295 if (datastore) {
1296 ast_channel_lock(chan);
1297 ast_channel_datastore_add(chan, datastore);
1298 ast_channel_unlock(chan);
1299 }
1300}

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

Referenced by bridge_stasis_moving(), and channel_stolen_cb().

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

2292{
2293 struct ast_channel *outchan = NULL, *outowner = NULL;
2294 int res = 0;
2295 struct ast_unreal_pvt *unreal_pvt = ast_channel_tech_pvt(chan);
2296
2297 ao2_ref(unreal_pvt, +1);
2298 ast_unreal_lock_all(unreal_pvt, &outowner, &outchan);
2299 if (outowner) {
2300 res |= set_internal_datastore(outowner);
2301 ast_channel_unlock(outowner);
2302 ast_channel_unref(outowner);
2303 }
2304 if (outchan) {
2305 res |= set_internal_datastore(outchan);
2306 ast_channel_unlock(outchan);
2307 ast_channel_unref(outchan);
2308 }
2309 ao2_unlock(unreal_pvt);
2310 ao2_ref(unreal_pvt, -1);
2311 return res;
2312}
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
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
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
struct ast_channel * chan
Definition: core_unreal.h:94

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

Referenced by bridge_moh_create(), and prepare_bridge_media_channel().

◆ 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.

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

References control_create(), and NULL.

Referenced by ari_bridges_play_new(), and ast_ari_bridges_record().

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

1254{
1255 while (!control_is_done(control)) {
1256 int command_count;
1257 command_count = control_dispatch_all(control, chan);
1258
1259 ao2_lock(control);
1260
1261 if (control_command_count(control)) {
1262 /* If the command queue isn't empty, something added to the queue before it was locked. */
1263 ao2_unlock(control);
1264 continue;
1265 }
1266
1267 if (command_count == 0 || ast_channel_fdno(chan) == -1) {
1268 control_mark_done(control);
1269 ao2_unlock(control);
1270 break;
1271 }
1272 ao2_unlock(control);
1273 }
1274}
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:357
int control_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all commands enqueued to this control.
Definition: control.c:1504
int control_command_count(struct stasis_app_control *control)
Returns the count of items in a control's command queue.
Definition: control.c:352
void control_mark_done(struct stasis_app_control *control)
Definition: control.c:363

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

◆ 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.

340{
341 if (chan == NULL) {
342 return NULL;
343 }
344
347}

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

◆ 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.

351{
352 return ao2_find(app_controls, channel_id, OBJ_SEARCH_KEY);
353}

References ao2_find, app_controls, and OBJ_SEARCH_KEY.

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

◆ 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.

Definition at line 1281 of file res_stasis.c.

1282{
1283 control_flush_queue(control);
1284}
void control_flush_queue(struct stasis_app_control *control)
Flush the control command queue.
Definition: control.c:1491

References control_flush_queue().

Referenced by bridge_channel_control_thread().

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

1277{
1278 return control_is_done(control);
1279}

References control_is_done().

Referenced by ari_bridges_play_found().

◆ stasis_app_exec()

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

Stasis dialplan application callback.

Control a channel using stasis_app.

Definition at line 1327 of file res_stasis.c.

1329{
1330 RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
1331 RAII_VAR(struct stasis_app_control *, control, NULL, control_unlink);
1332 struct ast_bridge *bridge = NULL;
1333 int res = 0;
1334 int needs_depart;
1335
1336 ast_assert(chan != NULL);
1337
1338 /* Just in case there's a lingering indication that the channel has had a stasis
1339 * end published on it, remove that now.
1340 */
1342
1343 if (!apps_registry) {
1344 return -1;
1345 }
1346
1348 if (!app) {
1350 "Stasis app '%s' not registered\n", app_name);
1351 return -1;
1352 }
1353 if (!app_is_active(app)) {
1355 "Stasis app '%s' not active\n", app_name);
1356 return -1;
1357 }
1358
1359 control = control_create(chan, app);
1360 if (!control) {
1361 ast_log(LOG_ERROR, "Control allocation failed or Stasis app '%s' not registered\n", app_name);
1362 return -1;
1363 }
1364
1365 if (!control_app(control)) {
1366 ast_log(LOG_ERROR, "Stasis app '%s' not registered\n", app_name);
1367 return -1;
1368 }
1369
1370 if (!app_is_active(control_app(control))) {
1371 ast_log(LOG_ERROR, "Stasis app '%s' not active\n", app_name);
1372 return -1;
1373 }
1374 ao2_link(app_controls, control);
1375
1376 if (add_masquerade_store(chan)) {
1377 ast_log(LOG_ERROR, "Failed to attach masquerade detector\n");
1378 return -1;
1379 }
1380
1381 res = send_start_msg(control_app(control), chan, argc, argv);
1382 if (res != 0) {
1384 "Error sending start message to '%s'\n", app_name);
1386 return -1;
1387 }
1388
1389 /* Pull queued prestart commands and execute */
1390 control_prestart_dispatch_all(control, chan);
1391
1392 while (!control_is_done(control)) {
1393 RAII_VAR(struct ast_frame *, f, NULL, ast_frame_dtor);
1394 int r;
1395 int command_count;
1396 RAII_VAR(struct ast_bridge *, last_bridge, NULL, ao2_cleanup);
1397
1398 /* Check to see if a bridge absorbed our hangup frame */
1399 if (ast_check_hangup_locked(chan)) {
1400 control_mark_done(control);
1401 break;
1402 }
1403
1404 /* control->next_app is only modified within the control thread, so this is safe */
1405 if (control_next_app(control)) {
1406 struct stasis_app *next_app = ao2_find(apps_registry, control_next_app(control), OBJ_SEARCH_KEY);
1407
1408 if (next_app && app_is_active(next_app)) {
1409 int idx;
1410 int next_argc;
1411 char **next_argv;
1412
1413 /* If something goes wrong in this conditional, res will need to be non-zero
1414 * so that the code below the exec loop knows something went wrong during a move.
1415 */
1417 res = has_masquerade_store(chan) && app_send_end_msg(control_app(control), chan);
1418 if (res != 0) {
1420 "Error sending end message to %s\n", stasis_app_name(control_app(control)));
1421 control_mark_done(control);
1422 ao2_ref(next_app, -1);
1423 break;
1424 }
1425 } else {
1427 }
1428
1429 /* This will ao2_bump next_app, and unref the previous app by 1 */
1430 control_set_app(control, next_app);
1431
1432 /* There's a chance that the previous application is ready for clean up, so go ahead
1433 * and do that now.
1434 */
1435 cleanup();
1436
1437 /* We need to add another masquerade store, otherwise the leave message will
1438 * not show up for the correct application.
1439 */
1440 if (add_masquerade_store(chan)) {
1441 ast_log(LOG_ERROR, "Failed to attach masquerade detector\n");
1442 res = -1;
1443 control_mark_done(control);
1444 ao2_ref(next_app, -1);
1445 break;
1446 }
1447
1448 /* We MUST get the size before the list, as control_next_app_args steals the elements
1449 * from the string vector.
1450 */
1451 next_argc = control_next_app_args_size(control);
1452 next_argv = control_next_app_args(control);
1453
1454 res = send_start_msg(control_app(control), chan, next_argc, next_argv);
1455
1456 /* Even if res != 0, we still need to free the memory we got from control_argv */
1457 if (next_argv) {
1458 for (idx = 0; idx < next_argc; idx++) {
1459 ast_free(next_argv[idx]);
1460 }
1461 ast_free(next_argv);
1462 }
1463
1464 if (res != 0) {
1466 "Error sending start message to '%s'\n", stasis_app_name(control_app(control)));
1468 control_mark_done(control);
1469 ao2_ref(next_app, -1);
1470 break;
1471 }
1472
1473 /* Done switching applications, free memory and clean up */
1474 control_move_cleanup(control);
1475 } else {
1476 /* If we can't switch applications, do nothing */
1477 struct ast_json *msg;
1478 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1479
1480 if (!next_app) {
1481 ast_log(LOG_ERROR, "Could not move to Stasis app '%s' - not registered\n",
1482 control_next_app(control));
1483 } else {
1484 ast_log(LOG_ERROR, "Could not move to Stasis app '%s' - not active\n",
1485 control_next_app(control));
1486 }
1487
1489 if (!snapshot) {
1490 ast_log(LOG_ERROR, "Could not get channel shapshot for '%s'\n",
1491 ast_channel_name(chan));
1492 } else {
1493 struct ast_json *json_args;
1494 int next_argc = control_next_app_args_size(control);
1495 char **next_argv = control_next_app_args(control);
1496
1497 msg = ast_json_pack("{s: s, s: o, s: o, s: s, s: []}",
1498 "type", "ApplicationMoveFailed",
1499 "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1500 "channel", ast_channel_snapshot_to_json(snapshot, NULL),
1501 "destination", control_next_app(control),
1502 "args");
1503 if (!msg) {
1504 ast_log(LOG_ERROR, "Failed to pack JSON for ApplicationMoveFailed message\n");
1505 } else {
1506 json_args = ast_json_object_get(msg, "args");
1507 if (!json_args) {
1508 ast_log(LOG_ERROR, "Could not get args json array");
1509 } else {
1510 int r = 0;
1511 int idx;
1512 for (idx = 0; idx < next_argc; ++idx) {
1513 r = ast_json_array_append(json_args,
1514 ast_json_string_create(next_argv[idx]));
1515 if (r != 0) {
1516 ast_log(LOG_ERROR, "Error appending to ApplicationMoveFailed message\n");
1517 break;
1518 }
1519 }
1520 if (r == 0) {
1521 app_send(control_app(control), msg);
1522 }
1523 }
1524 ast_json_unref(msg);
1525 }
1526 }
1527 }
1528 control_move_cleanup(control);
1529 ao2_cleanup(next_app);
1530 }
1531
1532 last_bridge = bridge;
1533 bridge = ao2_bump(stasis_app_get_bridge(control));
1534
1535 if (bridge != last_bridge) {
1536 if (last_bridge) {
1537 app_unsubscribe_bridge(control_app(control), last_bridge);
1538 }
1539 if (bridge) {
1540 app_subscribe_bridge(control_app(control), bridge);
1541 }
1542 }
1543
1544 if (bridge) {
1545 /* Bridge/dial is handling channel frames */
1546 control_wait(control);
1547 control_dispatch_all(control, chan);
1548 continue;
1549 }
1550
1551 r = ast_waitfor(chan, MAX_WAIT_MS);
1552
1553 if (r < 0) {
1554 ast_debug(3, "%s: Poll error\n",
1555 ast_channel_uniqueid(chan));
1556 control_mark_done(control);
1557 break;
1558 }
1559
1560 command_count = control_dispatch_all(control, chan);
1561
1562 if (command_count > 0 && ast_channel_fdno(chan) == -1) {
1563 /* Command drained the channel; wait for next frame */
1564 continue;
1565 }
1566
1567 if (r == 0) {
1568 /* Timeout */
1569 continue;
1570 }
1571
1572 f = ast_read(chan);
1573 if (!f) {
1574 /* Continue on in the dialplan */
1575 ast_debug(3, "%s: Hangup (no more frames)\n",
1576 ast_channel_uniqueid(chan));
1577 control_mark_done(control);
1578 break;
1579 }
1580
1581 if (f->frametype == AST_FRAME_CONTROL) {
1582 if (f->subclass.integer == AST_CONTROL_HANGUP) {
1583 /* Continue on in the dialplan */
1584 ast_debug(3, "%s: Hangup\n",
1585 ast_channel_uniqueid(chan));
1586 control_mark_done(control);
1587 break;
1588 }
1589 }
1590 }
1591
1592 ast_channel_lock(chan);
1593 needs_depart = (ast_channel_internal_bridge_channel(chan) != NULL);
1594 ast_channel_unlock(chan);
1595 if (needs_depart) {
1596 ast_bridge_depart(chan);
1597 }
1598
1599 if (stasis_app_get_bridge(control)) {
1601 }
1602 ao2_cleanup(bridge);
1603
1604 /* Only publish a stasis_end event if it hasn't already been published */
1605 if (!res && !stasis_app_channel_is_stasis_end_published(chan)) {
1606 /* A masquerade has occurred and this message will be wrong so it
1607 * has already been sent elsewhere. */
1608 res = has_masquerade_store(chan) && app_send_end_msg(control_app(control), chan);
1609 if (res != 0) {
1611 "Error sending end message to %s\n", stasis_app_name(control_app(control)));
1612 return res;
1613 }
1614 } else {
1616 }
1617
1618 control_flush_queue(control);
1619
1620 /* Stop any lingering silence generator */
1621 control_silence_stop_now(control);
1622
1623 /* There's an off chance that app is ready for cleanup. Go ahead
1624 * and clean up, just in case
1625 */
1626 cleanup();
1627
1628 /* The control needs to be removed from the controls container in
1629 * case a new PBX is started and ends up coming back into Stasis.
1630 */
1631 control_unlink(control);
1632 control = NULL;
1633
1634 if (!res && !ast_channel_pbx(chan)) {
1635 int chan_hungup;
1636
1637 /* The ASYNCGOTO softhangup flag may have broken the channel out of
1638 * its bridge to run dialplan, so if there's no pbx on the channel
1639 * let it run dialplan here. Otherwise, it will run when this
1640 * application exits. */
1641 ast_channel_lock(chan);
1643 chan_hungup = ast_check_hangup(chan);
1644 ast_channel_unlock(chan);
1645
1646 if (!chan_hungup) {
1647 struct ast_pbx_args pbx_args;
1648
1649 memset(&pbx_args, 0, sizeof(pbx_args));
1650 pbx_args.no_hangup_chan = 1;
1651
1652 res = ast_pbx_run_args(chan, &pbx_args);
1653 }
1654 }
1655
1656 return res;
1657}
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition: bridge.c:1906
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2451
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:459
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
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1146
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
int control_prestart_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all queued prestart commands.
Definition: control.c:1544
void control_wait(struct stasis_app_control *control)
Blocks until control's command queue has a command available.
Definition: control.c:1524
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:1719
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:1724
void control_set_app(struct stasis_app_control *control, struct stasis_app *app)
Set the application the control object belongs to.
Definition: control.c:1700
void control_silence_stop_now(struct stasis_app_control *control)
Stop playing silence to a channel right now.
Definition: control.c:846
char * control_next_app(struct stasis_app_control *control)
Returns the name of the application we are moving to.
Definition: control.c:1706
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:1711
void ast_frame_dtor(struct ast_frame *frame)
NULL-safe wrapper for ast_frfree, good for RAII_VAR.
Definition: main/frame.c:187
@ AST_FRAME_CONTROL
@ AST_CONTROL_HANGUP
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:4735
int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Add a bridge subscription to an existing channel subscription.
int app_unsubscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Cancel the bridge subscription for an application.
int app_is_active(struct stasis_app *app)
Checks whether an app is active.
void app_send(struct stasis_app *app, struct ast_json *message)
Send a message to an application.
static int send_start_msg(struct stasis_app *app, struct ast_channel *chan, int argc, char *argv[])
Definition: res_stasis.c:1060
static void remove_stasis_end_published(struct ast_channel *chan)
Definition: res_stasis.c:1313
static int add_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1220
static int has_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1214
#define MAX_WAIT_MS
Definition: res_stasis.c:77
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
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:1302
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition: control.c:940
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.
Options for ast_pbx_run()
Definition: pbx.h:407

References add_masquerade_store(), ao2_bump, ao2_cleanup, ao2_find, ao2_link, ao2_ref, app, app_controls, app_is_active(), app_name(), app_send(), app_send_end_msg(), app_subscribe_bridge(), app_unsubscribe_bridge(), apps_registry, 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().

◆ 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.
Return values
NULLon error.

Definition at line 1711 of file res_stasis.c.

1712{
1713 struct ao2_container *apps;
1714
1715 if (!apps_registry) {
1716 return NULL;
1717 }
1718
1720 if (!apps) {
1721 return NULL;
1722 }
1723
1725
1726 return apps;
1727}
static struct apps apps
static int append_name(void *obj, void *arg, int flags)
Definition: res_stasis.c:1702
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
Definition: strings.h:1365

References ao2_callback, append_name(), apps, apps_registry, 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().

◆ 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.
Return values
NULLon error.

Definition at line 1697 of file res_stasis.c.

1698{
1699 return find_app_by_name(name);
1700}

References find_app_by_name(), and 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().

◆ stasis_app_get_sanitizer()

struct stasis_message_sanitizer * stasis_app_get_sanitizer ( void  )

Get the Stasis message sanitizer for app_stasis applications.

Return values
Thestasis message sanitizer

Definition at line 2267 of file res_stasis.c.

2268{
2269 return &app_sanitizer;
2270}
struct stasis_message_sanitizer app_sanitizer
Sanitization callbacks for communication to Stasis applications.
Definition: res_stasis.c:2261

References app_sanitizer.

Referenced by app_send_end_msg(), ast_ari_bridges_create(), ast_ari_bridges_create_with_id(), ast_ari_bridges_get(), ast_ari_bridges_list(), ast_ari_channels_list(), ast_ari_endpoints_get(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), channel_callerid(), channel_connected_line(), channel_destroyed_event(), channel_dialplan(), message_received_handler(), simple_bridge_event(), simple_channel_event(), and simple_endpoint_event().

◆ 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.
Return values
NULLon error.

Definition at line 1869 of file res_stasis.c.

1870{
1871 if (!app) {
1872 return NULL;
1873 }
1874
1877}
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:1853
struct ast_json * stasis_app_event_filter_to_json(struct stasis_app *app, struct ast_json *json)
Convert and add the app's event type filter(s) to the given json object.

References app, 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().

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

1781{
1782 return __stasis_app_register(app_name, handler, data, 0);
1783}
static int __stasis_app_register(const char *app_name, stasis_app_cb handler, void *data, int all_events)
Definition: res_stasis.c:1729

References __stasis_app_register(), app_name(), and handler().

Referenced by AST_TEST_DEFINE(), and event_session_alloc().

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

1786{
1787 return __stasis_app_register(app_name, handler, data, 1);
1788}

References __stasis_app_register(), app_name(), and handler().

Referenced by event_session_alloc().

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

1820{
1824}
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731

References AST_LIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and stasis_app_register_event_sources().

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

1660{
1661 struct stasis_app *app;
1662
1663 if (!apps_registry) {
1664 return -1;
1665 }
1666
1668 if (!app) {
1669 /* XXX We can do a better job handling late binding, queueing up
1670 * the call for a few seconds to wait for the app to register.
1671 */
1673 "Stasis app '%s' not registered\n", app_name);
1674 return -1;
1675 }
1677 ao2_ref(app, -1);
1678
1679 return 0;
1680}

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

Referenced by AST_TEST_DEFINE(), and send_device_state().

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

2051{
2053 app_name, event_source_uris, event_sources_count,
2054 json, app_subscribe);
2055}
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:2022
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:1942

References app_handle_subscriptions(), app_name(), and app_subscribe().

Referenced by ast_ari_applications_subscribe().

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

1989{
1991 int res;
1992
1993 if (!app) {
1995 }
1996
1997 ast_debug(3, "%s: Subscribing to %s\n", app_name, ast_channel_uniqueid(chan));
1998
1999 res = app_subscribe_channel(app, chan);
2000 ao2_ref(app, -1);
2001
2002 if (res != 0) {
2003 ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
2006 }
2007
2008 return STASIS_ASR_OK;
2009}

References ao2_ref, app, app_name(), 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().

◆ 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.
Return values
NULLon error.

Definition at line 1879 of file res_stasis.c.

1880{
1882 struct ast_json *json = stasis_app_object_to_json(app);
1883
1885
1886 return json;
1887}

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

Referenced by append_json(), and ast_ari_applications_get().

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

1791{
1792 struct stasis_app *app;
1793
1794 if (!app_name) {
1795 return;
1796 }
1797
1798 if (!apps_registry) {
1799 return;
1800 }
1801
1803 if (!app) {
1805 "Stasis app '%s' not registered\n", app_name);
1806 return;
1807 }
1808
1810
1811 /* There's a decent chance that app is ready for cleanup. Go ahead
1812 * and clean up, just in case
1813 */
1814 cleanup();
1815
1816 ao2_ref(app, -1);
1817}
void app_deactivate(struct stasis_app *app)
Deactivates an application.

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

Referenced by AST_TEST_DEFINE(), and event_session_shutdown().

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

1827{
1828 struct stasis_app_event_source *source;
1829
1832 if (source == obj) {
1834 break;
1835 }
1836 }
1839}
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617

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

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

2092{
2094 app_name, event_source_uris, event_sources_count,
2095 json, app_unsubscribe);
2096}
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:2067

References app_handle_subscriptions(), app_name(), and app_unsubscribe().

Referenced by ast_ari_applications_unsubscribe().

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

2102{
2104 struct ast_json *blob = NULL;
2105 struct ast_multi_object_blob *multi;
2106 struct stasis_message *message;
2108 int have_channel = 0;
2109 int i;
2110
2111 if (!app) {
2112 ast_log(LOG_WARNING, "App %s not found\n", app_name);
2114 }
2115
2117 return res;
2118 }
2119
2120 if (json_variables) {
2121 struct ast_json *json_value = ast_json_string_create(event_name);
2122
2123 if (json_value && !ast_json_object_set(json_variables, "eventname", json_value)) {
2124 blob = ast_json_ref(json_variables);
2125 }
2126 } else {
2127 blob = ast_json_pack("{s: s}", "eventname", event_name);
2128 }
2129
2130 if (!blob) {
2131 ast_log(LOG_ERROR, "Failed to initialize blob\n");
2132
2133 return res;
2134 }
2135
2136 multi = ast_multi_object_blob_create(blob);
2137 ast_json_unref(blob);
2138 if (!multi) {
2139 ast_log(LOG_ERROR, "Failed to initialize multi\n");
2140
2141 return res;
2142 }
2143
2144 for (i = 0; i < sources_count; ++i) {
2145 const char *uri = source_uris[i];
2146 void *snapshot=NULL;
2148
2149 if (ast_begins_with(uri, "channel:")) {
2151 snapshot = ast_channel_snapshot_get_latest(uri + 8);
2152 have_channel = 1;
2153 } else if (ast_begins_with(uri, "bridge:")) {
2155 snapshot = ast_bridge_get_snapshot_by_uniqueid(uri + 7);
2156 } else if (ast_begins_with(uri, "endpoint:")) {
2158 snapshot = ast_endpoint_latest_snapshot(uri + 9, NULL);
2159 } else {
2160 ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);
2161 ao2_ref(multi, -1);
2162
2164 }
2165 if (!snapshot) {
2166 ast_log(LOG_ERROR, "Unable to get snapshot for %s\n", uri);
2167 ao2_ref(multi, -1);
2168
2170 }
2171 ast_multi_object_blob_add(multi, type, snapshot);
2172 }
2173
2175 ao2_ref(multi, -1);
2176
2177 if (!message) {
2178 ast_log(LOG_ERROR, "Unable to create stasis user event message\n");
2179 return res;
2180 }
2181
2182 /*
2183 * Publishing to two different topics is normally to be avoided -- except
2184 * in this case both are final destinations with no forwards (only listeners).
2185 * The message has to be delivered to the application topic for ARI, but a
2186 * copy is also delivered directly to the manager for AMI if there is a channel.
2187 */
2189
2190 if (have_channel) {
2192 }
2193 ao2_ref(message, -1);
2194
2195 return STASIS_APP_USER_OK;
2196}
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:453
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:2002
stasis_user_multi_object_snapshot_type
Object type code for multi user object snapshots.
Definition: stasis.h:1353
struct ast_multi_object_blob * ast_multi_object_blob_create(struct ast_json *blob)
Create a stasis multi object blob.
Definition: stasis.c:1976
struct ast_endpoint_snapshot * ast_endpoint_latest_snapshot(const char *tech, const char *resource)
Retrieve the most recent snapshot for the endpoint with the given name.
struct stasis_message_type * ast_multi_user_event_type(void)
Message type for custom user defined events with multi object blobs.
@ STASIS_UMOS_ENDPOINT
Definition: stasis.h:1356
@ STASIS_UMOS_BRIDGE
Definition: stasis.h:1355
@ STASIS_UMOS_CHANNEL
Definition: stasis.h:1354
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
stasis_app_user_event_res
Return code for stasis_app_user_event.
Definition: stasis_app.h:255
@ STASIS_APP_USER_APP_NOT_FOUND
Definition: stasis_app.h:257
@ STASIS_APP_USER_EVENT_SOURCE_NOT_FOUND
Definition: stasis_app.h:258
@ STASIS_APP_USER_EVENT_SOURCE_BAD_SCHEME
Definition: stasis_app.h:259
@ STASIS_APP_USER_OK
Definition: stasis_app.h:256
@ STASIS_APP_USER_INTERNAL_ERROR
Definition: stasis_app.h:261
struct ast_bridge_snapshot * ast_bridge_get_snapshot_by_uniqueid(const char *bridge_id)
Returns the current snapshot for the bridge.
A multi object blob data structure to carry user event stasis messages.
Definition: stasis.c:1951

References ao2_cleanup, ao2_ref, app, app_name(), 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(), 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().

◆ 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.

117{
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}
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
Blob of data associated with a channel.
struct ast_channel_snapshot * snapshot
struct ast_json * blob
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's...
Definition: stasis.h:221

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, and stasis_message_data().

◆ 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.

149{
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}

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, and stasis_message_data().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2198 of file res_stasis.c.

2199{
2201
2203
2204 cleanup();
2205
2207
2210
2213
2215 app_bridges = NULL;
2216
2219
2222
2223 STASIS_MESSAGE_TYPE_CLEANUP(end_message_type);
2224 STASIS_MESSAGE_TYPE_CLEANUP(start_message_type);
2225
2226 return 0;
2227}
int messaging_cleanup(void)
Tidy up the messaging layer.
Definition: messaging.c:529
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
void stasis_app_unregister_event_sources(void)
Unregister core event sources.
void stasis_app_control_shutdown(void)
Let Stasis app internals shut down.
Definition: control.c:1689

References ao2_cleanup, app_bridges, app_bridges_moh, app_bridges_playback, app_controls, apps_registry, cleanup(), messaging_cleanup(), NULL, stasis_app_control_shutdown(), stasis_app_unregister_event_sources(), and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module().

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

◆ app_bridges

struct ao2_container* app_bridges

◆ app_bridges_moh

struct ao2_container* app_bridges_moh

◆ app_bridges_playback

struct ao2_container* app_bridges_playback

◆ app_controls

struct ao2_container* app_controls

◆ 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_sanitizer(const struct ast_channel *chan)
Sanitization callback for channels.
Definition: res_stasis.c:2239
static int channel_id_sanitizer(const char *id)
Sanitization callback for channel unique IDs.
Definition: res_stasis.c:2248

Sanitization callbacks for communication to Stasis applications.

Definition at line 2261 of file res_stasis.c.

Referenced by stasis_app_get_sanitizer().

◆ apps_registry

struct ao2_container* apps_registry

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2382 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-masquerade",
.chan_fixup = channel_stolen_cb,
.chan_breakdown = channel_replaced_cb,
}
static void channel_replaced_cb(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: res_stasis.c:1162
static void channel_stolen_cb(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: res_stasis.c:1131

Definition at line 1208 of file res_stasis.c.

Referenced by add_masquerade_store(), has_masquerade_store(), and remove_masquerade_store().

◆ 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:879

Definition at line 888 of file res_stasis.c.

Referenced by get_replace_channel_store().

◆ set_end_published_info

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

Definition at line 1286 of file res_stasis.c.

Referenced by remove_stasis_end_published(), stasis_app_channel_is_stasis_end_published(), and stasis_app_channel_set_stasis_end_published().

◆ stasis_internal_channel_info

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

Definition at line 2272 of file res_stasis.c.

Referenced by set_internal_datastore(), and stasis_app_channel_is_internal().