Asterisk - The Open Source Telephony Project GIT-master-6144b6b
Loading...
Searching...
No Matches
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!
 
#define BRIDGES_NUM_BUCKETS   127
 Number of buckets for the Stasis bridges hash table. Remember to keep it a prime number!
 
#define CONTROLS_NUM_BUCKETS   127
 Number of buckets for the Stasis application hash table. Remember to keep it a prime number!
 
#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.
 
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.
 
int app_set_replace_channel_app (struct ast_channel *chan, const char *replace_app)
 Set the app that the replacement channel will be controlled by.
 
int app_set_replace_channel_snapshot (struct ast_channel *chan, struct ast_channel_snapshot *replace_snapshot)
 Set the snapshot of the channel that this channel will replace.
 
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 bridges_sort (const void *left, const void *right, const int flags)
 
static int channel_id_sanitizer (const char *id)
 Sanitization callback for channel unique IDs.
 
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.
 
static int channel_snapshot_sanitizer (const struct ast_channel_snapshot *snapshot)
 Sanitization callback for channel snapshots.
 
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.
 
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.
 
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.
 
struct ast_bridgestasis_app_bridge_create_invisible (const char *type, const char *name, const char *id)
 Create an invisible bridge of the specified type.
 
void stasis_app_bridge_destroy (const char *bridge_id)
 Destroy the bridge.
 
struct ast_bridgestasis_app_bridge_find_by_id (const char *bridge_id)
 Returns the bridge with the given id.
 
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.
 
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.
 
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.
 
void stasis_app_bridge_playback_channel_control_remove (const char *bridge_id, struct stasis_app_control *control)
 Remove a bridge playback channel's control from the app controls list.
 
struct ast_channelstasis_app_bridge_playback_channel_find (struct ast_bridge *bridge)
 Finds an existing ARI playback channel in a bridge.
 
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.
 
int stasis_app_bridge_set_var_reportable (const char *bridge_id, const char *variable, const char *value, int report_events)
 Set or clear a variable on a bridge and control ARI event reporting for it.
 
int stasis_app_channel_is_internal (struct ast_channel *chan)
 Is this channel internal to Stasis?
 
int stasis_app_channel_is_stasis_end_published (struct ast_channel *chan)
 Has this channel had a StasisEnd published on it?
 
int stasis_app_channel_set_internal (struct ast_channel *chan)
 Mark this channel as being internal to Stasis.
 
void stasis_app_channel_set_stasis_end_published (struct ast_channel *chan)
 Indicate that this channel has had a StasisEnd published for it.
 
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.
 
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.
 
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.
 
struct stasis_app_controlstasis_app_control_find_by_channel (const struct ast_channel *chan)
 Returns the handler for the given channel.
 
struct stasis_app_controlstasis_app_control_find_by_channel_id (const char *channel_id)
 Returns the handler for the channel with the given id.
 
void stasis_app_control_flush_queue (struct stasis_app_control *control)
 Flush the control command queue.
 
int stasis_app_control_is_done (struct stasis_app_control *control)
 Check if a control is marked as done.
 
int stasis_app_exec (struct ast_channel *chan, const char *app_name, int argc, char *argv[])
 Stasis dialplan application callback.
 
struct ao2_containerstasis_app_get_all (void)
 Gets the names of all registered Stasis applications.
 
struct stasis_appstasis_app_get_by_name (const char *name)
 Retrieve a handle to a Stasis application by its name.
 
struct stasis_message_sanitizerstasis_app_get_sanitizer (void)
 Get the Stasis message sanitizer for app_stasis applications.
 
int stasis_app_is_registered (const char *name)
 Check if a Stasis application is registered.
 
struct ast_jsonstasis_app_object_to_json (struct stasis_app *app)
 Return the JSON representation of a Stasis application.
 
int stasis_app_register (const char *app_name, stasis_app_cb handler, void *data)
 Register a new Stasis application.
 
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.
 
void stasis_app_register_event_source (struct stasis_app_event_source *obj)
 Register an application event source.
 
int stasis_app_send (const char *app_name, struct ast_json *message)
 Send a message to the given Stasis application.
 
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.
 
enum stasis_app_subscribe_res stasis_app_subscribe_channel (const char *app_name, struct ast_channel *chan)
 Directly subscribe an application to a channel.
 
struct ast_jsonstasis_app_to_json (const char *app_name)
 Return the JSON representation of a Stasis application.
 
void stasis_app_unregister (const char *app_name)
 Unregister a Stasis application and unsubscribe from all event sources.
 
void stasis_app_unregister_event_source (struct stasis_app_event_source *obj)
 Unregister an application event source.
 
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.
 
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)
 
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 = ASTERISK_GPL_KEY , .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.
 
struct ao2_containerapps_registry
 Stasis application container.
 
static const struct ast_module_infoast_module_info = &__mod_info
 
struct event_sources event_sources = AST_RWLIST_HEAD_INIT_VALUE
 
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 2003 of file res_stasis.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

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

1815{
1816 RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
1817
1818 if (!apps_registry) {
1819 return -1;
1820 }
1821
1824 if (app) {
1825 /*
1826 * We need to unlock the apps_registry before calling app_update to
1827 * prevent the possibility of a deadlock with the session.
1828 */
1830 app_update(app, handler, data);
1831 cleanup();
1832 return 0;
1833 }
1834
1836 if (!app) {
1838 return -1;
1839 }
1840
1841 if (all_events) {
1842 struct stasis_app_event_source *source;
1843
1846 if (!source->subscribe) {
1847 continue;
1848 }
1849
1850 source->subscribe(app, NULL);
1851 }
1853 }
1855
1857
1858 /* We lazily clean up the apps_registry, because it's good enough to
1859 * prevent memory leaks, and we're lazy.
1860 */
1861 cleanup();
1862 return 0;
1863}
static const char app[]
#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.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
const char * app_name(struct ast_app *app)
Definition pbx_app.c:475
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:184
struct stasis_app_event_source * next
Definition stasis_app.h:237
int(* subscribe)(struct stasis_app *app, void *obj)
Subscribe an application to an event source.
Definition stasis_app.h:206
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition test_ari.c:59
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

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

◆ add_masquerade_store()

static int add_masquerade_store ( struct ast_channel chan)
static

Definition at line 1289 of file res_stasis.c.

1290{
1291 struct ast_datastore *datastore;
1292
1293 SCOPED_CHANNELLOCK(lock, chan);
1295 return 0;
1296 }
1297
1299 if (!datastore) {
1300 return -1;
1301 }
1302
1303 ast_channel_datastore_add(chan, datastore);
1304
1305 return 0;
1306}
ast_mutex_t lock
Definition app_sla.c:337
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2376
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:2390
#define ast_datastore_alloc(info, uid)
Definition datastore.h:85
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition lock.h:626
static const struct ast_datastore_info masquerade_store_info
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 2003 of file res_stasis.c.

2004{
2005 struct stasis_app_event_source *source;
2006
2009 if (ast_begins_with(uri, source->scheme)) {
2010 break;
2011 }
2012 }
2014
2015 return source;
2016}
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:186

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

1958{
1959 struct stasis_app_event_source *source;
1960
1963 if (source->to_json) {
1964 source->to_json(app, json);
1965 }
1966 }
1968
1969 return json;
1970}
void(* to_json)(const struct stasis_app *app, struct ast_json *json)
Convert event source data to json.
Definition stasis_app.h:234

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

1040{
1042 char *replace_channel_app;
1043
1044 if (!replace) {
1045 return NULL;
1046 }
1047
1048 replace_channel_app = replace->app;
1049 replace->app = NULL;
1050
1051 return replace_channel_app;
1052}
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static struct replace_channel_store * get_replace_channel_store(struct ast_channel *chan, int no_create)
Definition res_stasis.c:962

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

2049{
2051 int i;
2052
2054
2055 if (!app) {
2057 }
2058
2059 for (i = 0; i < event_sources_count; ++i) {
2060 const char *uri = event_source_uris[i];
2061 struct stasis_app_event_source *event_source;
2062 enum stasis_app_subscribe_res res;
2063
2064 event_source = app_event_source_find(uri);
2065 if (!event_source) {
2066 ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);
2067 ao2_ref(app, -1);
2068
2070 }
2071
2072 res = handler(app, uri, event_source);
2073 if (res != STASIS_ASR_OK) {
2074 ao2_ref(app, -1);
2075
2076 return res;
2077 }
2078 }
2079
2080 if (json) {
2081 ast_debug(3, "%s: Successful; setting results\n", app_name);
2083 }
2084
2085 ao2_ref(app, -1);
2086
2087 return STASIS_ASR_OK;
2088}
#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.
static struct stasis_app * find_app_by_name(const char *app_name)
static struct stasis_app_event_source * app_event_source_find(const char *uri)
stasis_app_subscribe_res
Return code for stasis_app_[un]subscribe.
Definition stasis_app.h:292
@ STASIS_ASR_OK
Definition stasis_app.h:293
@ STASIS_ASR_EVENT_SOURCE_BAD_SCHEME
Definition stasis_app.h:296
@ STASIS_ASR_APP_NOT_FOUND
Definition stasis_app.h:294
#define ast_assert(a)
Definition utils.h:779

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

1156{
1158 struct ast_json *blob;
1159 struct stasis_message *msg;
1160
1161 if (sanitize && sanitize->channel
1162 && sanitize->channel(chan)) {
1163 return 0;
1164 }
1165
1166 blob = ast_json_pack("{s: s, s: o}",
1167 "app", stasis_app_name(app),
1168 "timestamp", ast_json_timeval(ast_tvnow(), NULL)
1169 );
1170 if (!blob) {
1171 ast_log(LOG_ERROR, "Error packing JSON for StasisEnd message\n");
1172 return -1;
1173 }
1174
1177 msg = ast_channel_blob_create(chan, end_message_type(), blob);
1178 if (msg) {
1180 }
1181 ao2_cleanup(msg);
1182 ast_json_unref(blob);
1183
1184 return 0;
1185}
struct stasis_message * ast_channel_blob_create(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Creates a ast_channel_blob message.
#define LOG_ERROR
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition json.c:670
int app_unsubscribe_channel(struct stasis_app *app, struct ast_channel *chan)
Cancel the subscription an app has for a channel.
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
static void remove_masquerade_store(struct ast_channel *chan)
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1589
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 1003 of file res_stasis.c.

1004{
1006
1007 if (!replace) {
1008 return -1;
1009 }
1010
1011 ast_free(replace->app);
1012 replace->app = NULL;
1013
1014 if (replace_app) {
1015 replace->app = ast_strdup(replace_app);
1016 if (!replace->app) {
1017 return -1;
1018 }
1019 }
1020
1021 return 0;
1022}
#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 991 of file res_stasis.c.

992{
994
995 if (!replace) {
996 return -1;
997 }
998
999 ao2_replace(replace->snapshot, replace_snapshot);
1000 return 0;
1001}
#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 2125 of file res_stasis.c.

2128{
2129 const char *app_name = stasis_app_name(app);
2130 RAII_VAR(void *, obj, NULL, ao2_cleanup);
2131
2132 ast_debug(3, "%s: Checking %s\n", app_name, uri);
2133
2134 if (!ast_strlen_zero(uri + strlen(event_source->scheme)) &&
2135 (!event_source->find || (!(obj = event_source->find(app, uri + strlen(event_source->scheme)))))) {
2136 ast_log(LOG_WARNING, "Event source not found: %s\n", uri);
2138 }
2139
2140 ast_debug(3, "%s: Subscribing to %s\n", app_name, uri);
2141
2142 if (!event_source->subscribe || (event_source->subscribe(app, obj))) {
2143 ast_log(LOG_WARNING, "Error subscribing app '%s' to '%s'\n",
2144 app_name, uri);
2146 }
2147
2148 return STASIS_ASR_OK;
2149}
@ STASIS_ASR_INTERNAL_ERROR
Definition stasis_app.h:297
@ STASIS_ASR_EVENT_SOURCE_NOT_FOUND
Definition stasis_app.h:295
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:196

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

2173{
2174 const char *app_name = stasis_app_name(app);
2175 const char *id = uri + strlen(event_source->scheme);
2176
2177 if (!event_source->is_subscribed ||
2178 (!event_source->is_subscribed(app, id))) {
2180 }
2181
2182 ast_debug(3, "%s: Unsubscribing from %s\n", app_name, uri);
2183
2184 if (!event_source->unsubscribe || (event_source->unsubscribe(app, id))) {
2185 ast_log(LOG_WARNING, "Error unsubscribing app '%s' to '%s'\n",
2186 app_name, uri);
2187 return -1;
2188 }
2189 return 0;
2190}
int(* unsubscribe)(struct stasis_app *app, const char *id)
Cancel the subscription an app has to an event source.
Definition stasis_app.h:216
int(* is_subscribed)(struct stasis_app *app, const char *id)
Find an event source by the given id/name.
Definition stasis_app.h:226

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

1788{
1789 struct stasis_app *app = obj;
1790 struct ao2_container *apps = arg;
1791
1793 return 0;
1794}
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:69

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

829{
830 struct ast_bridge *bridge;
831 char *requested_type, *requested_types = ast_strdupa(S_OR(type, "mixing"));
832 int capabilities = 0;
837 int send_sdp_label = 0;
838
839 ast_debug(1, "Creating bridge of type '%s' with name '%s' and id '%s'\n",
840 type, S_OR(name, "<unknown>"), S_OR(id, "<unknown>"));
841 if (invisible) {
843 }
844
845 if (!ast_strlen_zero(id)) {
846 bridge = stasis_app_bridge_find_by_id(id);
847 if (bridge) {
848 ast_log(LOG_WARNING, "Bridge with id '%s' already exists\n", id);
849 ao2_ref(bridge, -1);
850 return NULL;
851 }
852 }
853
854 while ((requested_type = strsep(&requested_types, ","))) {
855 requested_type = ast_strip(requested_type);
856
857 if (!strcmp(requested_type, "mixing")) {
858 capabilities |= STASIS_BRIDGE_MIXING_CAPABILITIES;
859 flags |= AST_BRIDGE_FLAG_SMART;
860 } else if (!strcmp(requested_type, "holding")) {
861 capabilities |= AST_BRIDGE_CAPABILITY_HOLDING;
862 } else if (!strcmp(requested_type, "dtmf_events") ||
863 !strcmp(requested_type, "proxy_media")) {
864 capabilities &= ~AST_BRIDGE_CAPABILITY_NATIVE;
865 } else if (!strcmp(requested_type, "video_sfu")) {
866 video_mode = AST_BRIDGE_VIDEO_MODE_SFU;
867 } else if (!strcmp(requested_type, "video_single")) {
869 } else if (!strcmp(requested_type, "sdp_label")) {
870 send_sdp_label = 1;
871 }
872 }
873
874 /* For an SFU video bridge we ensure it always remains in multimix for the best experience. */
875 if (video_mode == AST_BRIDGE_VIDEO_MODE_SFU) {
876 capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
877 flags &= ~AST_BRIDGE_FLAG_SMART;
878 }
879
880 if (!capabilities
881 /* Holding and mixing capabilities don't mix. */
882 || ((capabilities & AST_BRIDGE_CAPABILITY_HOLDING)
883 && (capabilities & (STASIS_BRIDGE_MIXING_CAPABILITIES)))) {
884 return NULL;
885 }
886
887 bridge = bridge_stasis_new(capabilities, flags, name, id, video_mode, send_sdp_label);
888 if (bridge) {
889 if (!ao2_link(app_bridges, bridge)) {
890 ast_bridge_destroy(bridge, 0);
891 bridge = NULL;
892 }
893 }
894
895 return bridge;
896}
char * strsep(char **str, const char *delims)
#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:1029
@ AST_BRIDGE_CAPABILITY_MULTIMIX
Definition bridge.h:98
@ AST_BRIDGE_CAPABILITY_HOLDING
Definition bridge.h:90
ast_bridge_video_mode_type
Video source modes.
Definition bridge.h:102
@ AST_BRIDGE_VIDEO_MODE_SINGLE_SRC
Definition bridge.h:106
@ AST_BRIDGE_VIDEO_MODE_TALKER_SRC
Definition bridge.h:109
@ AST_BRIDGE_VIDEO_MODE_SFU
Definition bridge.h:113
@ 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[]
static const char name[]
Definition format_mp3.c:68
struct ast_bridge * stasis_app_bridge_find_by_id(const char *bridge_id)
Returns the bridge with the given id.
Definition res_stasis.c:807
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
#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:355

References ao2_link, ao2_ref, 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_debug, ast_log, ast_strdupa, ast_strip(), ast_strlen_zero(), bridge_stasis_new(), LOG_WARNING, name, NULL, S_OR, stasis_app_bridge_find_by_id(), 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 600 of file res_stasis.c.

601{
602 struct stasis_app_bridge_channel_wrapper *new_wrapper;
603 struct ast_channel *chan;
604 pthread_t threadid;
605
607 if (!chan) {
608 return NULL;
609 }
610
612 ast_hangup(chan);
613 return NULL;
614 }
615
618 ast_hangup(chan);
619 return NULL;
620 }
621
622 new_wrapper = ao2_alloc_options(sizeof(*new_wrapper),
624 if (!new_wrapper) {
625 ast_hangup(chan);
626 return NULL;
627 }
628
630 || ast_string_field_set(new_wrapper, bridge_id, bridge->uniqueid)
631 || ast_string_field_set(new_wrapper, channel_id, ast_channel_uniqueid(chan))) {
632 ao2_ref(new_wrapper, -1);
633 ast_hangup(chan);
634 return NULL;
635 }
636
637 if (!ao2_link_flags(app_bridges_moh, new_wrapper, OBJ_NOLOCK)) {
638 ao2_ref(new_wrapper, -1);
639 ast_hangup(chan);
640 return NULL;
641 }
642
643 /* Pass the new_wrapper ref to moh_channel_thread() */
644 if (ast_pthread_create_detached(&threadid, NULL, moh_channel_thread, new_wrapper)) {
645 ast_log(LOG_ERROR, "Failed to create channel thread. Abandoning MOH channel creation.\n");
647 ao2_ref(new_wrapper, -1);
648 ast_hangup(chan);
649 return NULL;
650 }
651
652 return chan;
653}
@ 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:2540
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.
static void stasis_app_bridge_channel_wrapper_destructor(void *obj)
Definition res_stasis.c:481
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.
static struct ast_channel * prepare_bridge_moh_channel(void)
Definition res_stasis.c:536
static void * moh_channel_thread(void *data)
Definition res_stasis.c:555
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
const ast_string_field uniqueid
Definition bridge.h:407
Main Channel structure associated with a channel.
struct ast_bridge * bridge
#define ast_pthread_create_detached(a, b, c, d)
Definition utils.h:628
#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 455 of file res_stasis.c.

456{
457 const struct stasis_app_bridge_channel_wrapper *object_left = obj;
458 const struct stasis_app_bridge_channel_wrapper *object_right = arg;
459 const char *right_key = arg;
460 int cmp;
461
462 switch (flags & OBJ_SEARCH_MASK) {
464 right_key = object_right->bridge_id;
465 case OBJ_SEARCH_KEY:
466 cmp = strcmp(object_left->bridge_id, right_key);
467 break;
469 cmp = strncmp(object_left->bridge_id, right_key, strlen(right_key));
470 break;
471 default:
472 cmp = 0;
473 break;
474 }
475 if (cmp) {
476 return 0;
477 }
478 return CMP_MATCH;
479}
const ast_string_field bridge_id
Definition res_stasis.c:451

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

489{
490 const struct stasis_app_bridge_channel_wrapper *wrapper;
491 const char *key;
492
493 switch (flags & OBJ_SEARCH_MASK) {
494 case OBJ_SEARCH_KEY:
495 key = obj;
496 break;
498 wrapper = obj;
499 key = wrapper->bridge_id;
500 break;
501 default:
502 /* Hash can only work on something with a full key. */
503 ast_assert(0);
504 return 0;
505 }
506 return ast_str_hash(key);
507}

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

510{
511 const struct stasis_app_bridge_channel_wrapper *left = obj_left;
512 const struct stasis_app_bridge_channel_wrapper *right = obj_right;
513 const char *right_key = obj_right;
514 int cmp;
515
516 switch (flags & OBJ_SEARCH_MASK) {
518 right_key = right->bridge_id;
519 /* Fall through */
520 case OBJ_SEARCH_KEY:
521 cmp = strcmp(left->bridge_id, right_key);
522 break;
524 cmp = strncmp(left->bridge_id, right_key, strlen(right_key));
525 break;
526 default:
527 /* Sort can only work on something with a full or partial key. */
528 ast_assert(0);
529 cmp = 0;
530 break;
531 }
532 return cmp;
533}

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

◆ bridges_sort()

static int bridges_sort ( const void *  left,
const void *  right,
const int  flags 
)
static

AO2 sort function for bridges container

Definition at line 418 of file res_stasis.c.

419{
420 const struct ast_bridge *object_left = left;
421 const struct ast_bridge *object_right = right;
422 const char *right_key = right;
423 int cmp;
424
425 switch (flags & OBJ_SEARCH_MASK) {
427 right_key = object_right->uniqueid;
428 /* Fall through */
429 case OBJ_SEARCH_KEY:
430 cmp = strcmp(object_left->uniqueid, right_key);
431 break;
433 cmp = strncmp(object_left->uniqueid, right_key, strlen(right_key));
434 break;
435 default:
436 ast_assert(0);
437 cmp = 0;
438 break;
439 }
440 return cmp;
441}

References ast_assert, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, 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 2351 of file res_stasis.c.

2352{
2353 struct ast_channel_snapshot *snapshot;
2354 int ret;
2355
2356 snapshot = ast_channel_snapshot_get_latest(id);
2357 ret = channel_snapshot_sanitizer(snapshot);
2358 ao2_cleanup(snapshot);
2359
2360 return ret;
2361}
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.
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 1231 of file res_stasis.c.

1232{
1233 RAII_VAR(struct ast_channel_snapshot *, new_snapshot, NULL, ao2_cleanup);
1234 RAII_VAR(struct ast_channel_snapshot *, old_snapshot, NULL, ao2_cleanup);
1235 struct stasis_app_control *control;
1236
1237 /* At this point, new_chan is the channel pointer that is in Stasis() and
1238 * has the unknown channel's name in it while old_chan is the channel pointer
1239 * that is not in Stasis(), but has the guts of the channel that Stasis() knows
1240 * about */
1241
1242 /* grab a snapshot for the channel that is jumping into Stasis() */
1243 new_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(new_chan));
1244 if (!new_snapshot) {
1245 ast_log(LOG_ERROR, "Could not get snapshot for masquerading channel\n");
1246 return;
1247 }
1248
1249 /* grab a snapshot for the channel that has been kicked out of Stasis() */
1250 old_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(old_chan));
1251 if (!old_snapshot) {
1252 ast_log(LOG_ERROR, "Could not get snapshot for masqueraded channel\n");
1253 return;
1254 }
1255
1256 /*
1257 * Find, unlink, and relink control since the channel has a new
1258 * name/uniqueid and its hash has changed.
1259 */
1260 control = ao2_callback(app_controls, OBJ_UNLINK, masq_match_cb, new_chan);
1261 if (!control) {
1262 ast_log(LOG_ERROR, "Could not find control for masquerading channel\n");
1263 return;
1264 }
1265 ao2_link(app_controls, control);
1266
1267
1268 /* send the StasisStart with replace_channel to the app */
1269 send_start_msg_snapshots(new_chan, control_app(control), 0, NULL, new_snapshot,
1270 old_snapshot);
1271 /* send the StasisEnd message to the app */
1272 app_send_end_msg(control_app(control), old_chan);
1273
1274 ao2_cleanup(control);
1275}
#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:1626
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)
int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
Send StasisEnd message to the listening app.
static int masq_match_cb(void *obj, void *data, int flags)

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

2343{
2344 if (!chan || !(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)) {
2345 return 0;
2346 }
2347 return 1;
2348}
@ AST_CHAN_TP_INTERNAL
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition channel.h:991
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648

References AST_CHAN_TP_INTERNAL.

◆ channel_snapshot_sanitizer()

static int channel_snapshot_sanitizer ( const struct ast_channel_snapshot snapshot)
static

Sanitization callback for channel snapshots.

Definition at line 2333 of file res_stasis.c.

2334{
2335 if (!snapshot || !(snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL)) {
2336 return 0;
2337 }
2338 return 1;
2339}
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 1200 of file res_stasis.c.

1201{
1202 struct stasis_app_control *control;
1203
1204 /*
1205 * At this point, old_chan is the channel pointer that is in Stasis() and
1206 * has the unknown channel's name in it while new_chan is the channel pointer
1207 * that is not in Stasis(), but has the guts of the channel that Stasis() knows
1208 * about.
1209 *
1210 * Find and unlink control since the channel has a new name/uniqueid
1211 * and its hash has changed. Since the channel is leaving stasis don't
1212 * bother putting it back into the container. Nobody is going to
1213 * remove it from the container later.
1214 */
1215 control = ao2_callback(app_controls, OBJ_UNLINK, masq_match_cb, old_chan);
1216 if (!control) {
1217 ast_log(LOG_ERROR, "Could not find control for masqueraded channel\n");
1218 return;
1219 }
1220
1221 /* send the StasisEnd message to the app */
1223 app_send_end_msg(control_app(control), new_chan);
1224
1225 /* remove the datastore */
1226 remove_masquerade_store(old_chan);
1227
1228 ao2_cleanup(control);
1229}
void stasis_app_channel_set_stasis_end_published(struct ast_channel *chan)
Indicate that this channel has had a StasisEnd published for it.

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 __get_from_jb(), __stasis_app_register(), aeap_user_data_create(), ast_aeap_user_data_register(), ast_event_new(), ast_rtcp_write(), ast_rtp_dtmf_end_with_duration(), ast_sockaddr_resolve(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), astobj2_test_1_helper(), broadcast_exec(), build_user(), check_codec(), create_cts(), create_message_types(), digest_create_request_with_auth(), generate_computational_cost(), handle_uri(), invalid_record_test(), load_module(), load_module(), nominal_test(), off_nominal_test(), outbound_sessions_load(), pjsip_outbound_registration_metrics_init(), query_set_test(), sendtext_exec(), set_auth_creds(), set_outbound_initial_authentication_credentials(), sfu_topologies_on_source_change(), softmix_bridge_stream_sources_update(), 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:1493

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

819{
820 if (!control) {
821 return;
822 }
823
824 ao2_unlink(app_controls, control);
825 ao2_cleanup(control);
826}
#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 1754 of file res_stasis.c.

1755{
1756 struct stasis_app *res = NULL;
1757
1758 if (!apps_registry) {
1759 return NULL;
1760 }
1761
1762 if (!ast_strlen_zero(app_name)) {
1764 }
1765
1766 return res;
1767}

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_is_registered(), 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 1024 of file res_stasis.c.

1025{
1027 struct ast_channel_snapshot *replace_channel_snapshot;
1028
1029 if (!replace) {
1030 return NULL;
1031 }
1032
1033 replace_channel_snapshot = replace->snapshot;
1034 replace->snapshot = NULL;
1035
1036 return replace_channel_snapshot;
1037}

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

963{
964 struct ast_datastore *datastore;
965 struct replace_channel_store *ret;
966
967 ast_channel_lock(chan);
969 if (!datastore && !no_create) {
971 if (datastore) {
972 ast_channel_datastore_add(chan, datastore);
973 }
974 }
975
976 if (!datastore) {
977 ast_channel_unlock(chan);
978 return NULL;
979 }
980
981 if (!datastore->data) {
982 datastore->data = ast_calloc(1, sizeof(struct replace_channel_store));
983 }
984
985 ret = datastore->data;
986 ast_channel_unlock(chan);
987
988 return ret;
989}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_channel_lock(chan)
Definition channel.h:2983
#define ast_channel_unlock(chan)
Definition channel.h:2984
static const struct ast_datastore_info replace_channel_store_info
Definition res_stasis.c:957
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 1283 of file res_stasis.c.

1284{
1285 SCOPED_CHANNELLOCK(lock, chan);
1287}

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

2444{
2445 if (STASIS_MESSAGE_TYPE_INIT(start_message_type) != 0) {
2447 }
2448 if (STASIS_MESSAGE_TYPE_INIT(end_message_type) != 0) {
2450 }
2465 unload_module();
2467 }
2468
2469 if (messaging_init()) {
2470 unload_module();
2472 }
2473
2475
2477
2479}
@ 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_sort(const void *left, const void *right, const int flags)
Definition res_stasis.c:418
static int bridges_channel_sort_fn(const void *obj_left, const void *obj_right, const int flags)
Definition res_stasis.c:509
static int bridges_channel_compare(void *obj, void *arg, int flags)
Definition res_stasis.c:455
static int unload_module(void)
static int bridges_channel_hash_fn(const void *obj, const int flags)
Definition res_stasis.c:488
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:1524
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, bridges_sort(), 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 1187 of file res_stasis.c.

1188{
1189 struct stasis_app_control *control = obj;
1190 struct ast_channel *chan = data;
1191
1192 if (!strcmp(ast_channel_uniqueid(chan),
1194 return CMP_MATCH;
1195 }
1196
1197 return 0;
1198}
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 555 of file res_stasis.c.

556{
557 struct stasis_app_bridge_channel_wrapper *moh_wrapper = data;
558 struct ast_channel *moh_channel = ast_channel_get_by_name(moh_wrapper->channel_id);
559 struct ast_frame *f;
560
561 if (!moh_channel) {
562 ao2_unlink(app_bridges_moh, moh_wrapper);
563 ao2_ref(moh_wrapper, -1);
564 return NULL;
565 }
566
567 /* Read and discard any frame coming from the stasis bridge. */
568 for (;;) {
569 if (ast_waitfor(moh_channel, -1) < 0) {
570 /* Error or hungup */
571 break;
572 }
573
574 f = ast_read(moh_channel);
575 if (!f) {
576 /* Hungup */
577 break;
578 }
579 ast_frfree(f);
580 }
581
582 ao2_unlink(app_bridges_moh, moh_wrapper);
583 ao2_ref(moh_wrapper, -1);
584
585 ast_moh_stop(moh_channel);
586 ast_hangup(moh_channel);
587
588 return NULL;
589}
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition channel.c:3166
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition channel.c:4278
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition channel.c:1417
#define ast_frfree(fr)
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition channel.c:7812
Data structure associated with a single frame of data.
const ast_string_field channel_id
Definition res_stasis.c:451

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

732{
733 char *bridge_id = data;
734
735 remove_bridge_playback(bridge_id);
736}
static void remove_bridge_playback(char *bridge_id)
Definition res_stasis.c:699

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

725{
726 char *bridge_id = data;
727
728 remove_bridge_playback(bridge_id);
729}

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

537{
538 struct ast_channel *chan;
539 struct ast_format_cap *cap;
540
542 if (!cap) {
543 return NULL;
544 }
545
547
548 chan = ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL);
549 ao2_ref(cap, -1);
550
551 return chan;
552}
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.
@ 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 699 of file res_stasis.c.

700{
701 struct stasis_app_bridge_channel_wrapper *wrapper;
702 struct stasis_app_control *control;
703
705
706 if (wrapper) {
708 if (control) {
709 ao2_unlink(app_controls, control);
710 ao2_ref(control, -1);
711 }
712 ao2_ref(wrapper, -1);
713 }
714 ast_free(bridge_id);
715}
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 1308 of file res_stasis.c.

1309{
1310 struct ast_datastore *datastore;
1311
1312 SCOPED_CHANNELLOCK(lock, chan);
1314 if (!datastore) {
1315 return;
1316 }
1317
1318 ast_channel_datastore_remove(chan, datastore);
1319 ast_datastore_free(datastore);
1320}
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition channel.c:2385
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 1382 of file res_stasis.c.

1383{
1384 struct ast_datastore *datastore;
1385
1386 ast_channel_lock(chan);
1388 if (datastore) {
1389 ast_channel_datastore_remove(chan, datastore);
1390 ast_datastore_free(datastore);
1391 }
1392 ast_channel_unlock(chan);
1393}
struct ast_datastore_info set_end_published_info

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

949{
950 struct replace_channel_store *replace = obj;
951
952 ao2_cleanup(replace->snapshot);
953 ast_free(replace->app);
955}

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

1131{
1132 int ret = -1;
1133 struct ast_channel_snapshot *snapshot;
1134 struct ast_channel_snapshot *replace_channel_snapshot;
1135
1136 ast_assert(chan != NULL);
1137
1138 replace_channel_snapshot = get_replace_channel_snapshot(chan);
1139
1140 /* Set channel info */
1141 ast_channel_lock(chan);
1142 snapshot = ast_channel_snapshot_create(chan);
1143 ast_channel_unlock(chan);
1144 if (snapshot) {
1145 ret = send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot);
1146 ao2_ref(snapshot, -1);
1147 }
1148 ao2_cleanup(replace_channel_snapshot);
1149
1150 return ret;
1151}
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)

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

1066{
1067 struct ast_json *json_blob;
1068 struct ast_json *json_args;
1069 struct start_message_blob *payload;
1070 struct stasis_message *msg;
1071 int i;
1072
1073 if (app_subscribe_channel(app, chan)) {
1074 ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
1076 return -1;
1077 }
1078
1079 payload = ao2_alloc(sizeof(*payload), start_message_blob_dtor);
1080 if (!payload) {
1081 ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
1082 return -1;
1083 }
1084
1085 payload->channel = ao2_bump(snapshot);
1086 payload->replace_channel = ao2_bump(replace_channel_snapshot);
1087
1088 json_blob = ast_json_pack("{s: s, s: o, s: []}",
1089 "app", stasis_app_name(app),
1090 "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1091 "args");
1092 if (!json_blob) {
1093 ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
1094 ao2_ref(payload, -1);
1095 return -1;
1096 }
1097 payload->blob = json_blob;
1098
1099
1100 /* Append arguments to args array */
1101 json_args = ast_json_object_get(json_blob, "args");
1102 ast_assert(json_args != NULL);
1103 for (i = 0; i < argc; ++i) {
1104 int r = ast_json_array_append(json_args,
1105 ast_json_string_create(argv[i]));
1106 if (r != 0) {
1107 ast_log(LOG_ERROR, "Error appending to StasisStart message\n");
1108 ao2_ref(payload, -1);
1109 return -1;
1110 }
1111 }
1112
1113
1114 msg = stasis_message_create(start_message_type(), payload);
1115 ao2_ref(payload, -1);
1116 if (!msg) {
1117 ast_log(LOG_ERROR, "Error sending StasisStart message\n");
1118 return -1;
1119 }
1120
1121 if (replace_channel_snapshot) {
1122 app_unsubscribe_channel_id(app, replace_channel_snapshot->base->uniqueid);
1123 }
1125 ao2_ref(msg, -1);
1126 return 0;
1127}
#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)
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 2379 of file res_stasis.c.

2380{
2381 struct ast_datastore *datastore;
2382
2384 if (!datastore) {
2386 if (!datastore) {
2387 return -1;
2388 }
2389 ast_channel_datastore_add(chan, datastore);
2390 }
2391 return 0;
2392}
static const struct ast_datastore_info stasis_internal_channel_info

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

1055{
1056 struct start_message_blob *payload = obj;
1057
1058 ao2_cleanup(payload->channel);
1059 ao2_cleanup(payload->replace_channel);
1060 ast_json_unref(payload->blob);
1061}

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

482{
483 struct stasis_app_bridge_channel_wrapper *wrapper = obj;
485}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object

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

899{
900 return bridge_create_common(type, name, id, 0);
901}
static struct ast_bridge * bridge_create_common(const char *type, const char *name, const char *id, int invisible)
Definition res_stasis.c:828

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

904{
905 return bridge_create_common(type, name, id, 1);
906}

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

909{
910 struct ast_bridge *bridge = stasis_app_bridge_find_by_id(bridge_id);
911 if (!bridge) {
912 return;
913 }
914 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": destroying bridge\n",
915 BRIDGE_PRINTF_VARS(bridge));
916
917 ao2_unlink(app_bridges, bridge);
918 ast_debug(1, "Bridge " BRIDGE_PRINTF_SPEC ": unlinked from app_bridges. current refcount: %d\n",
919 BRIDGE_PRINTF_VARS(bridge), ao2_ref(bridge, 0));
920 ast_bridge_destroy(bridge, 0);
921}
#define BRIDGE_PRINTF_VARS(bridge)
Definition bridge.h:80
#define BRIDGE_PRINTF_SPEC
Definition bridge.h:79

References ao2_ref, ao2_unlink, app_bridges, ast_bridge_destroy(), ast_debug, BRIDGE_PRINTF_SPEC, BRIDGE_PRINTF_VARS, 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 807 of file res_stasis.c.

809{
810 return ao2_find(app_bridges, bridge_id, OBJ_SEARCH_KEY);
811}

References ao2_find, app_bridges, and OBJ_SEARCH_KEY.

Referenced by ast_ari_bridges_get_bridge_vars(), ast_ari_bridges_set_bridge_vars(), bridge_create_common(), bridge_find(), find_bridge(), stasis_app_bridge_destroy(), and stasis_app_bridge_set_var_reportable().

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

656{
657 struct ast_channel *chan;
658 struct stasis_app_bridge_channel_wrapper *moh_wrapper;
659
661 moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_NOLOCK);
662 if (!moh_wrapper) {
663 chan = bridge_moh_create(bridge);
664 }
666
667 if (moh_wrapper) {
668 chan = ast_channel_get_by_name(moh_wrapper->channel_id);
669 ao2_ref(moh_wrapper, -1);
670 }
671
672 return chan;
673}
static struct ast_channel * bridge_moh_create(struct ast_bridge *bridge)
Definition res_stasis.c:600

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

676{
677 struct stasis_app_bridge_channel_wrapper *moh_wrapper;
678 struct ast_channel *chan;
679
681 if (!moh_wrapper) {
682 return -1;
683 }
684
685 chan = ast_channel_get_by_name(moh_wrapper->channel_id);
686 ao2_ref(moh_wrapper, -1);
687 if (!chan) {
688 return -1;
689 }
690
691 ast_moh_stop(chan);
693 ao2_cleanup(chan);
694
695 return 0;
696}
#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:2462

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

741{
743 char *bridge_id = ast_strdup(bridge->uniqueid);
744
745 if (!bridge_id) {
746 return -1;
747 }
748
751 ast_free(bridge_id);
752 return -1;
753 }
754
755 new_wrapper = ao2_alloc_options(sizeof(*new_wrapper),
757 if (!new_wrapper) {
758 return -1;
759 }
760
761 if (ast_string_field_init(new_wrapper, 32)) {
762 return -1;
763 }
764
765 ast_string_field_set(new_wrapper, bridge_id, bridge->uniqueid);
766 ast_string_field_set(new_wrapper, channel_id, ast_channel_uniqueid(chan));
767
768 if (!ao2_link(app_bridges_playback, new_wrapper)) {
769 return -1;
770 }
771
772 ao2_link(app_controls, control);
773 return 0;
774}
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.
static void playback_after_bridge_cb(struct ast_channel *chan, void *data)
Definition res_stasis.c:731
static void playback_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition res_stasis.c:724

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

void stasis_app_bridge_playback_channel_control_remove ( const char *  bridge_id,
struct stasis_app_control control 
)

Remove a bridge playback channel's control from the app controls list.

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

Definition at line 717 of file res_stasis.c.

719{
720 ast_assert(!ast_strlen_zero(bridge_id));
721 ao2_unlink(app_controls, control);
722}

References ao2_unlink, app_controls, ast_assert, and ast_strlen_zero().

Referenced by bridge_channel_control_thread(), and stasis_app_bridge_playback_channel_remove().

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

793{
794 struct stasis_app_bridge_channel_wrapper *playback_wrapper;
795 struct ast_channel *chan;
796
798 if (!playback_wrapper) {
799 return NULL;
800 }
801
802 chan = ast_channel_get_by_name(playback_wrapper->channel_id);
803 ao2_ref(playback_wrapper, -1);
804 return chan;
805}

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

778{
779 struct stasis_app_bridge_channel_wrapper *wrapper;
780
782 if (wrapper) {
783 /* If wrapper is not found, then that means the after bridge callback has been
784 * called or is in progress. No need to unlink the control here since that has
785 * been done or is about to be done in the after bridge callback
786 */
788 ao2_ref(wrapper, -1);
789 }
790}
void stasis_app_bridge_playback_channel_control_remove(const char *bridge_id, struct stasis_app_control *control)
Remove a bridge playback channel's control from the app controls list.
Definition res_stasis.c:717

References ao2_find, ao2_ref, app_bridges_playback, stasis_app_bridge_channel_wrapper::bridge_id, OBJ_SEARCH_KEY, OBJ_UNLINK, and stasis_app_bridge_playback_channel_control_remove().

Referenced by ari_bridges_play_new().

◆ stasis_app_bridge_set_var_reportable()

int stasis_app_bridge_set_var_reportable ( const char *  bridge_id,
const char *  variable,
const char *  value,
int  report_events 
)

Set or clear a variable on a bridge and control ARI event reporting for it.

Parameters
bridge_idUniqueid of bridge
variableVariable name
valueVariable value (NULL/empty clears)
report_eventsNon-zero to include in ARI bridge events
Return values
0on success
-1on failure

Definition at line 923 of file res_stasis.c.

925{
926 RAII_VAR(struct ast_bridge *, bridge, stasis_app_bridge_find_by_id(bridge_id), ao2_cleanup);
927
928 if (!bridge) {
929 return -1;
930 }
931
932 ast_bridge_lock(bridge);
933 if (ast_bridge_set_variable(bridge, variable, value, report_events)) {
934 ast_bridge_unlock(bridge);
935 return -1;
936 }
938 ast_bridge_unlock(bridge);
939
940 return 0;
941}
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition bridge.h:491
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition bridge.h:480
int ast_bridge_set_variable(struct ast_bridge *bridge, const char *name, const char *value, int report_events)
Set a variable on the bridge.
Definition bridge.c:1341
void ast_bridge_publish_state(struct ast_bridge *bridge)
Publish the state of a bridge.
int value
Definition syslog.c:37

References ao2_cleanup, ast_bridge_lock, ast_bridge_publish_state(), ast_bridge_set_variable(), ast_bridge_unlock, RAII_VAR, stasis_app_bridge_find_by_id(), and value.

Referenced by ast_ari_bridges_set_bridge_var(), and ast_ari_bridges_set_bridge_vars().

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

2429{
2430 struct ast_datastore *datastore;
2431 int res = 0;
2432
2433 ast_channel_lock(chan);
2435 if (datastore) {
2436 res = 1;
2437 }
2438 ast_channel_unlock(chan);
2439
2440 return res;
2441}

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

1372{
1373 struct ast_datastore *datastore;
1374
1375 ast_channel_lock(chan);
1377 ast_channel_unlock(chan);
1378
1379 return datastore ? 1 : 0;
1380}

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

2418{
2419 int res;
2420
2421 ast_channel_lock(chan);
2422 res = set_internal_datastore(chan);
2423 ast_channel_unlock(chan);
2424
2425 return res;
2426}
static int set_internal_datastore(struct ast_channel *chan)

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

1360{
1361 struct ast_datastore *datastore;
1362
1364 if (datastore) {
1365 ast_channel_lock(chan);
1366 ast_channel_datastore_add(chan, datastore);
1367 ast_channel_unlock(chan);
1368 }
1369}

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

2395{
2396 struct ast_channel *outchan = NULL, *outowner = NULL;
2397 int res = 0;
2398 struct ast_unreal_pvt *unreal_pvt = ast_channel_tech_pvt(chan);
2399
2400 ao2_ref(unreal_pvt, +1);
2401 ast_unreal_lock_all(unreal_pvt, &outowner, &outchan);
2402 if (outowner) {
2403 res |= set_internal_datastore(outowner);
2404 ast_channel_unlock(outowner);
2405 ast_channel_unref(outowner);
2406 }
2407 if (outchan) {
2408 res |= set_internal_datastore(outchan);
2409 ast_channel_unlock(outchan);
2410 ast_channel_unref(outchan);
2411 }
2412 ao2_unlock(unreal_pvt);
2413 ao2_ref(unreal_pvt, -1);
2414 return res;
2415}
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3019
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:131

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

1323{
1324 while (!control_is_done(control)) {
1325 int command_count;
1326 command_count = control_dispatch_all(control, chan);
1327
1328 ao2_lock(control);
1329
1330 if (control_command_count(control)) {
1331 /* If the command queue isn't empty, something added to the queue before it was locked. */
1332 ao2_unlock(control);
1333 continue;
1334 }
1335
1336 if (command_count == 0 || ast_channel_fdno(chan) == -1) {
1337 control_mark_done(control);
1338 ao2_unlock(control);
1339 break;
1340 }
1341 ao2_unlock(control);
1342 }
1343}
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:363
int control_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all commands enqueued to this control.
Definition control.c:1558
int control_command_count(struct stasis_app_control *control)
Returns the count of items in a control's command queue.
Definition control.c:358
void control_mark_done(struct stasis_app_control *control)
Definition control.c:369

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(), outbound_session_handler_thread(), 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 1350 of file res_stasis.c.

1351{
1352 control_flush_queue(control);
1353}
void control_flush_queue(struct stasis_app_control *control)
Flush the control command queue.
Definition control.c:1545

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

1346{
1347 return control_is_done(control);
1348}

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

1398{
1399 RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
1400 RAII_VAR(struct stasis_app_control *, control, NULL, control_unlink);
1401 struct ast_bridge *bridge = NULL;
1402 int res = 0;
1403 int needs_depart;
1404
1405 ast_assert(chan != NULL);
1406
1407 /* Just in case there's a lingering indication that the channel has had a stasis
1408 * end published on it, remove that now.
1409 */
1411
1412 if (!apps_registry) {
1413 return -1;
1414 }
1415
1417 if (!app) {
1419 "Stasis app '%s' not registered\n", app_name);
1420 return -1;
1421 }
1422 if (!app_is_active(app)) {
1424 "Stasis app '%s' not active\n", app_name);
1425 return -1;
1426 }
1427
1428 control = control_create(chan, app);
1429 if (!control) {
1430 ast_log(LOG_ERROR, "Control allocation failed or Stasis app '%s' not registered\n", app_name);
1431 return -1;
1432 }
1433
1434 if (!control_app(control)) {
1435 ast_log(LOG_ERROR, "Stasis app '%s' not registered\n", app_name);
1436 return -1;
1437 }
1438
1439 if (!app_is_active(control_app(control))) {
1440 ast_log(LOG_ERROR, "Stasis app '%s' not active\n", app_name);
1441 return -1;
1442 }
1443 ao2_link(app_controls, control);
1444
1445 if (add_masquerade_store(chan)) {
1446 ast_log(LOG_ERROR, "Failed to attach masquerade detector\n");
1447 return -1;
1448 }
1449
1450 res = send_start_msg(control_app(control), chan, argc, argv);
1451 if (res != 0) {
1453 "Error sending start message to '%s'\n", app_name);
1455 return -1;
1456 }
1457
1458 /* Pull queued prestart commands and execute */
1459 control_prestart_dispatch_all(control, chan);
1460
1461 while (!control_is_done(control)) {
1462 RAII_VAR(struct ast_frame *, f, NULL, ast_frame_dtor);
1463 int r;
1464 int command_count;
1465 RAII_VAR(struct ast_bridge *, last_bridge, NULL, ao2_cleanup);
1466
1467 /* Check to see if a bridge absorbed our hangup frame */
1468 if (ast_check_hangup_locked(chan)) {
1469 control_mark_done(control);
1470 break;
1471 }
1472
1473 /* control->next_app is only modified within the control thread, so this is safe */
1474 if (control_next_app(control)) {
1475 struct stasis_app *next_app = ao2_find(apps_registry, control_next_app(control), OBJ_SEARCH_KEY);
1476
1477 if (next_app && app_is_active(next_app)) {
1478 int idx;
1479 int next_argc;
1480 char **next_argv;
1481
1482 /* If something goes wrong in this conditional, res will need to be non-zero
1483 * so that the code below the exec loop knows something went wrong during a move.
1484 */
1486 res = has_masquerade_store(chan) && app_send_end_msg(control_app(control), chan);
1487 if (res != 0) {
1489 "Error sending end message to %s\n", stasis_app_name(control_app(control)));
1490 control_mark_done(control);
1491 ao2_ref(next_app, -1);
1492 break;
1493 }
1494 } else {
1496 }
1497
1498 /* This will ao2_bump next_app, and unref the previous app by 1 */
1499 control_set_app(control, next_app);
1500
1501 /* There's a chance that the previous application is ready for clean up, so go ahead
1502 * and do that now.
1503 */
1504 cleanup();
1505
1506 /* We need to add another masquerade store, otherwise the leave message will
1507 * not show up for the correct application.
1508 */
1509 if (add_masquerade_store(chan)) {
1510 ast_log(LOG_ERROR, "Failed to attach masquerade detector\n");
1511 res = -1;
1512 control_mark_done(control);
1513 ao2_ref(next_app, -1);
1514 break;
1515 }
1516
1517 /* We MUST get the size before the list, as control_next_app_args steals the elements
1518 * from the string vector.
1519 */
1520 next_argc = control_next_app_args_size(control);
1521 next_argv = control_next_app_args(control);
1522
1523 res = send_start_msg(control_app(control), chan, next_argc, next_argv);
1524
1525 /* Even if res != 0, we still need to free the memory we got from control_argv */
1526 if (next_argv) {
1527 for (idx = 0; idx < next_argc; idx++) {
1528 ast_free(next_argv[idx]);
1529 }
1530 ast_free(next_argv);
1531 }
1532
1533 if (res != 0) {
1535 "Error sending start message to '%s'\n", stasis_app_name(control_app(control)));
1537 control_mark_done(control);
1538 ao2_ref(next_app, -1);
1539 break;
1540 }
1541
1542 /* Done switching applications, free memory and clean up */
1543 control_move_cleanup(control);
1544 } else {
1545 /* If we can't switch applications, do nothing */
1546 struct ast_json *msg;
1547 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1548
1549 if (!next_app) {
1550 ast_log(LOG_ERROR, "Could not move to Stasis app '%s' - not registered\n",
1551 control_next_app(control));
1552 } else {
1553 ast_log(LOG_ERROR, "Could not move to Stasis app '%s' - not active\n",
1554 control_next_app(control));
1555 }
1556
1558 if (!snapshot) {
1559 ast_log(LOG_ERROR, "Could not get channel shapshot for '%s'\n",
1560 ast_channel_name(chan));
1561 } else {
1562 struct ast_json *json_args;
1563 int next_argc = control_next_app_args_size(control);
1564 char **next_argv = control_next_app_args(control);
1565
1566 msg = ast_json_pack("{s: s, s: o, s: o, s: s, s: []}",
1567 "type", "ApplicationMoveFailed",
1568 "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1569 "channel", ast_channel_snapshot_to_json(snapshot, NULL),
1570 "destination", control_next_app(control),
1571 "args");
1572 if (!msg) {
1573 ast_log(LOG_ERROR, "Failed to pack JSON for ApplicationMoveFailed message\n");
1574 } else {
1575 json_args = ast_json_object_get(msg, "args");
1576 if (!json_args) {
1577 ast_log(LOG_ERROR, "Could not get args json array");
1578 } else {
1579 int r = 0;
1580 int idx;
1581 for (idx = 0; idx < next_argc; ++idx) {
1582 r = ast_json_array_append(json_args,
1583 ast_json_string_create(next_argv[idx]));
1584 if (r != 0) {
1585 ast_log(LOG_ERROR, "Error appending to ApplicationMoveFailed message\n");
1586 break;
1587 }
1588 }
1589 if (r == 0) {
1590 app_send(control_app(control), msg);
1591 }
1592 }
1593 ast_json_unref(msg);
1594 }
1595 }
1596 }
1597 control_move_cleanup(control);
1598 ao2_cleanup(next_app);
1599 }
1600
1601 last_bridge = bridge;
1602 bridge = ao2_bump(stasis_app_get_bridge(control));
1603
1604 if (bridge != last_bridge) {
1605 if (last_bridge) {
1606 app_unsubscribe_bridge(control_app(control), last_bridge);
1607 }
1608 if (bridge) {
1609 app_subscribe_bridge(control_app(control), bridge);
1610 }
1611 }
1612
1613 if (bridge) {
1614 /* Bridge/dial is handling channel frames */
1615 control_wait(control);
1616 control_dispatch_all(control, chan);
1617 continue;
1618 }
1619
1620 r = ast_waitfor(chan, MAX_WAIT_MS);
1621
1622 if (r < 0) {
1623 ast_debug(3, "%s: Poll error\n",
1624 ast_channel_uniqueid(chan));
1625 control_mark_done(control);
1626 break;
1627 }
1628
1629 command_count = control_dispatch_all(control, chan);
1630
1631 if (command_count > 0 && ast_channel_fdno(chan) == -1) {
1632 /* Command drained the channel; wait for next frame */
1633 continue;
1634 }
1635
1636 if (r == 0) {
1637 /* Timeout */
1638 continue;
1639 }
1640
1641 f = ast_read(chan);
1642 if (!f) {
1643 /* Continue on in the dialplan */
1644 ast_debug(3, "%s: Hangup (no more frames)\n",
1645 ast_channel_uniqueid(chan));
1646 control_mark_done(control);
1647 break;
1648 }
1649
1650 if (f->frametype == AST_FRAME_CONTROL) {
1651 if (f->subclass.integer == AST_CONTROL_HANGUP) {
1652 /* Continue on in the dialplan */
1653 ast_debug(3, "%s: Hangup\n",
1654 ast_channel_uniqueid(chan));
1655 control_mark_done(control);
1656 break;
1657 }
1658 }
1659 }
1660
1661 ast_channel_lock(chan);
1662 needs_depart = (ast_channel_internal_bridge_channel(chan) != NULL);
1663 ast_channel_unlock(chan);
1664 if (needs_depart) {
1665 ast_bridge_depart(chan);
1666 }
1667
1668 if (stasis_app_get_bridge(control)) {
1670 }
1671 ao2_cleanup(bridge);
1672
1673 /* Only publish a stasis_end event if it hasn't already been published */
1674 if (!res && !stasis_app_channel_is_stasis_end_published(chan)) {
1675 /* A masquerade has occurred and this message will be wrong so it
1676 * has already been sent elsewhere. */
1677 res = has_masquerade_store(chan) && app_send_end_msg(control_app(control), chan);
1678 if (res != 0) {
1680 "Error sending end message to %s\n", stasis_app_name(control_app(control)));
1681 return res;
1682 }
1683 } else {
1685 }
1686
1687 control_flush_queue(control);
1688
1689 /* Stop any lingering silence generator */
1690 control_silence_stop_now(control);
1691
1692 /* There's an off chance that app is ready for cleanup. Go ahead
1693 * and clean up, just in case
1694 */
1695 cleanup();
1696
1697 if (stasis_app_control_is_failed(control)) {
1698 res = -1;
1699 }
1700 /* The control needs to be removed from the controls container in
1701 * case a new PBX is started and ends up coming back into Stasis.
1702 */
1703 control_unlink(control);
1704 control = NULL;
1705
1706 if (!res && !ast_channel_pbx(chan)) {
1707 int chan_hungup;
1708
1709 /* The ASYNCGOTO softhangup flag may have broken the channel out of
1710 * its bridge to run dialplan, so if there's no pbx on the channel
1711 * let it run dialplan here. Otherwise, it will run when this
1712 * application exits. */
1713 ast_channel_lock(chan);
1715 chan_hungup = ast_check_hangup(chan);
1716 ast_channel_unlock(chan);
1717
1718 if (!chan_hungup) {
1719 struct ast_pbx_args pbx_args;
1720
1721 memset(&pbx_args, 0, sizeof(pbx_args));
1722 pbx_args.no_hangup_chan = 1;
1723
1724 res = ast_pbx_run_args(chan, &pbx_args);
1725 }
1726 }
1727
1728 return res;
1729}
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition bridge.c:2105
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition channel.c:2423
int ast_check_hangup_locked(struct ast_channel *chan)
Definition channel.c:460
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:446
@ 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:1598
void control_wait(struct stasis_app_control *control)
Blocks until control's command queue has a command available.
Definition control.c:1578
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:1773
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:1778
void control_set_app(struct stasis_app_control *control, struct stasis_app *app)
Set the application the control object belongs to.
Definition control.c:1754
void control_silence_stop_now(struct stasis_app_control *control)
Stop playing silence to a channel right now.
Definition control.c:889
char * control_next_app(struct stasis_app_control *control)
Returns the name of the application we are moving to.
Definition control.c:1760
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:1765
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:3295
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[])
static void remove_stasis_end_published(struct ast_channel *chan)
static int add_masquerade_store(struct ast_channel *chan)
static int has_masquerade_store(struct ast_channel *chan)
#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:818
int stasis_app_channel_is_stasis_end_published(struct ast_channel *chan)
Has this channel had a StasisEnd published on it?
int stasis_app_control_is_failed(const struct stasis_app_control *control)
Check if a control object is marked as "failed".
Definition control.c:382
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition control.c:983
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:409

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_control_is_failed(), stasis_app_get_bridge(), and stasis_app_name().

Referenced by app_exec(), and stasis_broadcast_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 1796 of file res_stasis.c.

1797{
1798 struct ao2_container *apps;
1799
1800 if (!apps_registry) {
1801 return NULL;
1802 }
1803
1805 if (!apps) {
1806 return NULL;
1807 }
1808
1810
1811 return apps;
1812}
static int append_name(void *obj, void *arg, int flags)
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
Definition strings.h:1365

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

Referenced by ari_set_debug(), ari_show_app(), ari_show_apps(), ast_ari_applications_list(), send_broadcast_event(), stasis_app_claim_channel(), 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 1769 of file res_stasis.c.

1770{
1771 return find_app_by_name(name);
1772}

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

2371{
2372 return &app_sanitizer;
2373}
struct stasis_message_sanitizer app_sanitizer
Sanitization callbacks for communication to Stasis applications.

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

int stasis_app_is_registered ( const char *  name)

Check if a Stasis application is registered.

Parameters
nameThe name of the registered Stasis application
Returns
1 if the application is registered.
0 if the application is not registered.

Definition at line 1774 of file res_stasis.c.

1775{
1777
1778 /*
1779 * It's safe to unref app here because we're not actually
1780 * using it or returning it.
1781 */
1783
1784 return app != NULL;
1785}

References ao2_cleanup, app, find_app_by_name(), name, and NULL.

Referenced by app_exec(), and session_register_apps().

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

1973{
1974 if (!app) {
1975 return NULL;
1976 }
1977
1980}
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)
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 1865 of file res_stasis.c.

1866{
1867 return __stasis_app_register(app_name, handler, data, 0);
1868}
static int __stasis_app_register(const char *app_name, stasis_app_cb handler, void *data, int all_events)

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

Referenced by AST_TEST_DEFINE(), AST_TEST_DEFINE(), and session_register_apps().

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

1871{
1872 return __stasis_app_register(app_name, handler, data, 1);
1873}

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

Referenced by session_register_apps().

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

1923{
1927}
#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.

References AST_LIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and stasis_app_event_source::next.

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

1732{
1733 struct stasis_app *app;
1734
1735 if (!apps_registry) {
1736 return -1;
1737 }
1738
1740 if (!app) {
1741 /* XXX We can do a better job handling late binding, queueing up
1742 * the call for a few seconds to wait for the app to register.
1743 */
1745 "Stasis app '%s' not registered\n", app_name);
1746 return -1;
1747 }
1749 ao2_ref(app, -1);
1750
1751 return 0;
1752}

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(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), send_broadcast_event(), send_device_state(), and stasis_app_claim_channel().

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

2154{
2156 app_name, event_source_uris, event_sources_count,
2157 json, app_subscribe);
2158}
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_handle_subscriptions(const char *app_name, const char **event_source_uris, int event_sources_count, struct ast_json **json, app_subscription_handler handler)

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

2092{
2094 int res;
2095
2096 if (!app) {
2098 }
2099
2100 ast_debug(3, "%s: Subscribing to %s\n", app_name, ast_channel_uniqueid(chan));
2101
2102 res = app_subscribe_channel(app, chan);
2103 ao2_ref(app, -1);
2104
2105 if (res != 0) {
2106 ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
2109 }
2110
2111 return STASIS_ASR_OK;
2112}

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

1983{
1985 struct ast_json *json = stasis_app_object_to_json(app);
1986
1988
1989 return json;
1990}

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 and unsubscribe from all event sources.

Parameters
app_nameName of the application to unregister.

Definition at line 1875 of file res_stasis.c.

1876{
1877 struct stasis_app *app;
1878 struct stasis_app_event_source *source;
1879 int res;
1880
1881 if (!app_name) {
1882 return;
1883 }
1884
1885 if (!apps_registry) {
1886 return;
1887 }
1888
1890 if (!app) {
1892 "Stasis app '%s' not registered\n", app_name);
1893 return;
1894 }
1895
1896 /* Unsubscribe from all event sources. */
1899 if (!source->unsubscribe || !source->is_subscribed
1900 || !source->is_subscribed(app, NULL)) {
1901 continue;
1902 }
1903
1904 res = source->unsubscribe(app, NULL);
1905 if (res) {
1906 ast_log(LOG_WARNING, "%s: Error unsubscribing from event source '%s'\n",
1907 app_name, source->scheme);
1908 }
1909 }
1911
1913
1914 /* There's a decent chance that app is ready for cleanup. Go ahead
1915 * and clean up, just in case
1916 */
1917 cleanup();
1918
1919 ao2_ref(app, -1);
1920}
void app_deactivate(struct stasis_app *app)
Deactivates an application.

References ao2_find, ao2_ref, app, app_deactivate(), app_name(), apps_registry, AST_LIST_TRAVERSE, ast_log, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, cleanup(), stasis_app_event_source::is_subscribed, LOG_ERROR, LOG_WARNING, stasis_app_event_source::next, NULL, OBJ_SEARCH_KEY, stasis_app_event_source::scheme, and stasis_app_event_source::unsubscribe.

Referenced by AST_TEST_DEFINE(), AST_TEST_DEFINE(), and session_unregister_app_cb().

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

1930{
1931 struct stasis_app_event_source *source;
1932
1935 if (source == obj) {
1937 break;
1938 }
1939 }
1942}
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_TRAVERSE_SAFE_END

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

2195{
2197 app_name, event_source_uris, event_sources_count,
2198 json, app_unsubscribe);
2199}
static enum stasis_app_subscribe_res app_unsubscribe(struct stasis_app *app, const char *uri, struct stasis_app_event_source *event_source)

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

2205{
2207 struct ast_json *blob = NULL;
2208 struct ast_multi_object_blob *multi;
2209 struct stasis_message *message;
2211 int have_channel = 0;
2212 int i;
2213
2214 if (!app) {
2215 ast_log(LOG_WARNING, "App %s not found\n", app_name);
2217 }
2218
2220 return res;
2221 }
2222
2223 if (json_variables) {
2224 struct ast_json *json_value = ast_json_string_create(event_name);
2225
2226 if (json_value && !ast_json_object_set(json_variables, "eventname", json_value)) {
2227 blob = ast_json_ref(json_variables);
2228 }
2229 } else {
2230 blob = ast_json_pack("{s: s}", "eventname", event_name);
2231 }
2232
2233 if (!blob) {
2234 ast_log(LOG_ERROR, "Failed to initialize blob\n");
2235
2236 return res;
2237 }
2238
2239 multi = ast_multi_object_blob_create(blob);
2240 ast_json_unref(blob);
2241 if (!multi) {
2242 ast_log(LOG_ERROR, "Failed to initialize multi\n");
2243
2244 return res;
2245 }
2246
2247 for (i = 0; i < sources_count; ++i) {
2248 const char *uri = source_uris[i];
2249 void *snapshot=NULL;
2251
2252 if (ast_begins_with(uri, "channel:")) {
2254 snapshot = ast_channel_snapshot_get_latest(uri + 8);
2255 have_channel = 1;
2256 } else if (ast_begins_with(uri, "bridge:")) {
2258 snapshot = ast_bridge_get_snapshot_by_uniqueid(uri + 7);
2259 } else if (ast_begins_with(uri, "endpoint:")) {
2261 snapshot = ast_endpoint_latest_snapshot(uri + 9, NULL);
2262 } else {
2263 ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);
2264 ao2_ref(multi, -1);
2265
2267 }
2268 if (!snapshot) {
2269 ast_log(LOG_ERROR, "Unable to get snapshot for %s\n", uri);
2270 ao2_ref(multi, -1);
2271
2273 }
2274 ast_multi_object_blob_add(multi, type, snapshot);
2275 }
2276
2278 ao2_ref(multi, -1);
2279
2280 if (!message) {
2281 ast_log(LOG_ERROR, "Unable to create stasis user event message\n");
2282 return res;
2283 }
2284
2285 /*
2286 * Publishing to two different topics is normally to be avoided -- except
2287 * in this case both are final destinations with no forwards (only listeners).
2288 * The message has to be delivered to the application topic for ARI, but a
2289 * copy is also delivered directly to the manager for AMI if there is a channel.
2290 */
2292
2293 if (have_channel) {
2295 }
2296 ao2_ref(message, -1);
2297
2298 return STASIS_APP_USER_OK;
2299}
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition manager.c:450
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:2213
stasis_user_multi_object_snapshot_type
Object type code for multi user object snapshots.
Definition stasis.h:1384
struct ast_multi_object_blob * ast_multi_object_blob_create(struct ast_json *blob)
Create a stasis multi object blob.
Definition stasis.c:2187
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:1387
@ STASIS_UMOS_BRIDGE
Definition stasis.h:1386
@ STASIS_UMOS_CHANNEL
Definition stasis.h:1385
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:265
@ STASIS_APP_USER_APP_NOT_FOUND
Definition stasis_app.h:267
@ STASIS_APP_USER_EVENT_SOURCE_NOT_FOUND
Definition stasis_app.h:268
@ STASIS_APP_USER_EVENT_SOURCE_BAD_SCHEME
Definition stasis_app.h:269
@ STASIS_APP_USER_OK
Definition stasis_app.h:266
@ STASIS_APP_USER_INTERNAL_ERROR
Definition stasis_app.h:271
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:2162

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

2302{
2304
2306
2307 cleanup();
2308
2310
2313
2316
2318 app_bridges = NULL;
2319
2322
2325
2326 STASIS_MESSAGE_TYPE_CLEANUP(end_message_type);
2327 STASIS_MESSAGE_TYPE_CLEANUP(start_message_type);
2328
2329 return 0;
2330}
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:1546
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:1743

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 = ASTERISK_GPL_KEY , .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 2486 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.
static int channel_id_sanitizer(const char *id)
Sanitization callback for channel unique IDs.

Sanitization callbacks for communication to Stasis applications.

Definition at line 2364 of file res_stasis.c.

2364 {
2365 .channel_id = channel_id_sanitizer,
2366 .channel_snapshot = channel_snapshot_sanitizer,
2367 .channel = channel_sanitizer,
2368};

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

◆ event_sources

◆ 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)
static void channel_stolen_cb(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)

Definition at line 1277 of file res_stasis.c.

1277 {
1278 .type = "stasis-masquerade",
1279 .chan_fixup = channel_stolen_cb,
1280 .chan_breakdown = channel_replaced_cb,
1281};

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

Definition at line 957 of file res_stasis.c.

957 {
958 .type = "replace-channel-store",
959 .destroy = replace_channel_destroy,
960};

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

1355 {
1356 .type = "stasis_end_published",
1357};

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

2375 {
2376 .type = "stasis-internal-channel",
2377};

Referenced by set_internal_datastore(), and stasis_app_channel_is_internal().