Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Data Structures | Typedefs | Functions | Variables
control.c File Reference

Stasis application control support. More...

#include "asterisk.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_app.h"
#include "command.h"
#include "control.h"
#include "app.h"
#include "asterisk/dial.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_after.h"
#include "asterisk/bridge_basic.h"
#include "asterisk/bridge_features.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
Include dependency graph for control.c:

Go to the source code of this file.

Data Structures

struct  app_control_rules
 
struct  chanvar
 structure for queuing ARI channel variable setting More...
 
struct  control_dial_args
 
struct  stasis_app_control
 
struct  stasis_app_control_continue_data
 
struct  stasis_app_control_dtmf_data
 
struct  stasis_app_control_move_data
 
struct  stasis_app_control_mute_data
 

Typedefs

typedef int(* app_command_can_exec_cb) (struct stasis_app_control *control)
 

Functions

static int add_to_dial_bridge (struct stasis_app_control *control, struct ast_channel *chan)
 Add a channel to the singleton dial bridge. More...
 
static int app_control_add_role (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_can_add_channel_to_bridge (struct stasis_app_control *control)
 
static int app_control_can_remove_channel_from_bridge (struct stasis_app_control *control)
 
static enum stasis_app_control_channel_result app_control_check_rules (const struct stasis_app_control *control, struct app_control_rules *list)
 
static int app_control_clear_roles (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_continue (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_dial (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_dtmf (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_hold (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_moh_start (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_moh_stop (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_move (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_mute (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_redirect (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static void app_control_register_rule (struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj)
 
static int app_control_remove_channel_from_bridge (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_ring (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_ring_stop (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_set_channel_var (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_silence_start (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_silence_stop (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_unhold (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int app_control_unmute (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static void app_control_unregister_rule (struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj)
 
static int app_send_command_on_condition (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
 
static void bridge_after_cb (struct ast_channel *chan, void *data)
 
static void bridge_after_cb_failed (enum ast_bridge_after_cb_reason reason, void *data)
 
static int bridge_channel_depart (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int bridge_timeout (struct ast_bridge_channel *bridge_channel, void *ignore)
 Dial timeout. More...
 
int control_add_channel_to_bridge (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 Command callback for adding a channel to a bridge. More...
 
struct stasis_appcontrol_app (struct stasis_app_control *control)
 Returns the pointer (non-reffed) to the app associated with this control. More...
 
int control_command_count (struct stasis_app_control *control)
 Returns the count of items in a control's command queue. More...
 
struct stasis_app_controlcontrol_create (struct ast_channel *channel, struct stasis_app *app)
 Create a control object. More...
 
static struct control_dial_argscontrol_dial_args_alloc (const char *dialstring, unsigned int timeout)
 
static void control_dial_args_destroy (void *data)
 
int control_dispatch_all (struct stasis_app_control *control, struct ast_channel *chan)
 Dispatch all commands enqueued to this control. More...
 
static void control_dtor (void *obj)
 
void control_flush_queue (struct stasis_app_control *control)
 Flush the control command queue. More...
 
int control_is_done (struct stasis_app_control *control)
 Returns true if control_continue() has been called on this control. More...
 
void control_mark_done (struct stasis_app_control *control)
 
void control_move_cleanup (struct stasis_app_control *control)
 Free any memory that was allocated for switching applications via /channels/{channelId}/move. More...
 
char * control_next_app (struct stasis_app_control *control)
 Returns the name of the application we are moving to. More...
 
char ** control_next_app_args (struct stasis_app_control *control)
 Returns the list of arguments to pass to the application we are moving to. More...
 
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. More...
 
int control_prestart_dispatch_all (struct stasis_app_control *control, struct ast_channel *chan)
 Dispatch all queued prestart commands. More...
 
void control_set_app (struct stasis_app_control *control, struct stasis_app *app)
 Set the application the control object belongs to. More...
 
void control_set_thread (struct stasis_app_control *control, pthread_t threadid)
 set the control's thread id More...
 
void control_silence_stop_now (struct stasis_app_control *control)
 Stop playing silence to a channel right now. More...
 
int control_swap_channel_in_bridge (struct stasis_app_control *control, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap)
 Command for swapping a channel in a bridge. More...
 
void control_wait (struct stasis_app_control *control)
 Blocks until control's command queue has a command available. More...
 
static int depart_channel (struct stasis_app_control *control, struct ast_channel *chan)
 Depart a channel from a bridge, and potentially add it back to the dial bridge. More...
 
static void dial_bridge_after_cb (struct ast_channel *chan, void *data)
 after bridge callback for the dial bridge More...
 
static void dial_bridge_after_cb_failed (enum ast_bridge_after_cb_reason reason, void *data)
 
static void dtmf_in_bridge (struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
 
static void dtmf_no_bridge (struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
 
static struct stasis_app_commandexec_command (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
 
static struct stasis_app_commandexec_command_on_condition (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
 
static void free_chanvar (void *data)
 
static struct ast_bridgeget_dial_bridge (void)
 Retrieve a reference to the dial bridge. More...
 
static int hangup_channel (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static void internal_bridge_after_cb (struct ast_channel *chan, void *data, enum ast_bridge_after_cb_reason reason)
 
static int noop_cb (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static void set_interval_hook (struct ast_channel *chan)
 Set a dial timeout interval hook on the channel. More...
 
static int set_timeout (struct ast_channel *chan, unsigned int timeout)
 Set dial timeout on a channel to be dialed. More...
 
void stasis_app_control_absorb_dtmf_in_bridge (struct stasis_app_control *control, int absorb)
 Set whether DTMF from the channel is absorbed instead of passing through to the bridge. More...
 
int stasis_app_control_add_channel_to_bridge (struct stasis_app_control *control, struct ast_bridge *bridge)
 Add a channel to the bridge. More...
 
int stasis_app_control_add_role (struct stasis_app_control *control, const char *role)
 Apply a bridge role to a channel controlled by a stasis app control. More...
 
int stasis_app_control_bridge_features_init (struct stasis_app_control *control)
 Initialize bridge features into a channel control. More...
 
void stasis_app_control_clear_roles (struct stasis_app_control *control)
 Clear bridge roles currently applied to a channel controlled by a stasis app control. More...
 
int stasis_app_control_continue (struct stasis_app_control *control, const char *context, const char *extension, int priority)
 Exit res_stasis and continue execution in the dialplan. More...
 
int stasis_app_control_dial (struct stasis_app_control *control, const char *dialstring, unsigned int timeout)
 Dial a channel. More...
 
int stasis_app_control_dtmf (struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
 Send DTMF to the channel associated with this control. More...
 
const char * stasis_app_control_get_channel_id (const struct stasis_app_control *control)
 Returns the uniqueid of the channel associated with this control. More...
 
struct ast_channel_snapshotstasis_app_control_get_snapshot (const struct stasis_app_control *control)
 Returns the most recent snapshot for the associated channel. More...
 
void stasis_app_control_hold (struct stasis_app_control *control)
 Place the channel associated with the control on hold. More...
 
void stasis_app_control_inhibit_colp_in_bridge (struct stasis_app_control *control, int inhibit_colp)
 Set whether COLP frames should be generated when joining the bridge. More...
 
void stasis_app_control_moh_start (struct stasis_app_control *control, const char *moh_class)
 Play music on hold to a channel (does not affect hold status) More...
 
void stasis_app_control_moh_stop (struct stasis_app_control *control)
 Stop playing music on hold to a channel (does not affect hold status) More...
 
int stasis_app_control_move (struct stasis_app_control *control, const char *app_name, const char *app_args)
 Exit res_stasis and move to another Stasis application. More...
 
int stasis_app_control_mute (struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
 Mute the channel associated with this control. More...
 
void stasis_app_control_mute_in_bridge (struct stasis_app_control *control, int mute)
 Set whether audio from the channel is muted instead of passing through to the bridge. More...
 
void stasis_app_control_publish (struct stasis_app_control *control, struct stasis_message *message)
 Publish a message to the control's channel's topic. More...
 
int stasis_app_control_queue_control (struct stasis_app_control *control, enum ast_control_frame_type frame_type)
 Queue a control frame without payload. More...
 
int stasis_app_control_redirect (struct stasis_app_control *control, const char *endpoint)
 Redirect a channel in res_stasis to a particular endpoint. More...
 
void stasis_app_control_register_add_rule (struct stasis_app_control *control, struct stasis_app_control_rule *rule)
 Registers an add channel to bridge rule. More...
 
void stasis_app_control_register_remove_rule (struct stasis_app_control *control, struct stasis_app_control_rule *rule)
 Registers a remove channel from bridge rule. More...
 
int stasis_app_control_remove_channel_from_bridge (struct stasis_app_control *control, struct ast_bridge *bridge)
 Remove a channel from the bridge. More...
 
int stasis_app_control_ring (struct stasis_app_control *control)
 Indicate ringing to the channel associated with this control. More...
 
int stasis_app_control_ring_stop (struct stasis_app_control *control)
 Stop locally generated ringing on the channel associated with this control. More...
 
int stasis_app_control_set_channel_var (struct stasis_app_control *control, const char *variable, const char *value)
 Set a variable on the channel associated with this control to value. More...
 
void stasis_app_control_shutdown (void)
 Let Stasis app internals shut down. More...
 
void stasis_app_control_silence_start (struct stasis_app_control *control)
 Start playing silence to a channel. More...
 
void stasis_app_control_silence_stop (struct stasis_app_control *control)
 Stop playing silence to a channel. More...
 
void stasis_app_control_unhold (struct stasis_app_control *control)
 Remove the channel associated with the control from hold. More...
 
int stasis_app_control_unmute (struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
 Unmute the channel associated with this control. More...
 
void stasis_app_control_unregister_add_rule (struct stasis_app_control *control, struct stasis_app_control_rule *rule)
 UnRegister an add channel to bridge rule. More...
 
void stasis_app_control_unregister_remove_rule (struct stasis_app_control *control, struct stasis_app_control_rule *rule)
 Unregisters a remove channel from bridge rule. More...
 
struct ast_bridgestasis_app_get_bridge (struct stasis_app_control *control)
 Gets the bridge currently associated with a control object. More...
 
int stasis_app_send_command (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
 Invokes a command on a control's channel. More...
 
int stasis_app_send_command_async (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
 Asynchronous version of stasis_app_send_command(). More...
 

Variables

static struct ast_bridgedial_bridge
 Singleton dial bridge. More...
 
static ast_mutex_t dial_bridge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int shutting_down
 Indicates if the Stasis app internals are being shut down. More...
 
struct ast_datastore_info timeout_datastore
 Dial timeout datastore. More...
 

Detailed Description

Stasis application control support.

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

Definition in file control.c.

Typedef Documentation

◆ app_command_can_exec_cb

typedef int(* app_command_can_exec_cb) (struct stasis_app_control *control)

Callback type to see if the command can execute note: command_queue is locked during callback

Definition at line 278 of file control.c.

Function Documentation

◆ add_to_dial_bridge()

static int add_to_dial_bridge ( struct stasis_app_control control,
struct ast_channel chan 
)
static

Add a channel to the singleton dial bridge.

Parameters
controlThe Stasis control structure
chanThe channel to add to the bridge
Return values
-1Failed
0Success

Definition at line 1061 of file control.c.

1062{
1063 struct ast_bridge *bridge;
1064
1065 bridge = get_dial_bridge();
1066 if (!bridge) {
1067 return -1;
1068 }
1069
1070 control->bridge = bridge;
1073 control->bridge = NULL;
1074 ao2_ref(bridge, -1);
1075 return -1;
1076 }
1077
1078 ao2_ref(bridge, -1);
1079
1080 return 0;
1081}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1878
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
Definition: bridge.h:588
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
Setup an after bridge callback for when the channel leaves the bridging system.
Definition: bridge_after.c:251
static void dial_bridge_after_cb(struct ast_channel *chan, void *data)
after bridge callback for the dial bridge
Definition: control.c:1029
static struct ast_bridge * get_dial_bridge(void)
Retrieve a reference to the dial bridge.
Definition: control.c:994
static void dial_bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition: control.c:1045
#define NULL
Definition: resample.c:96
Structure that contains information about a bridge.
Definition: bridge.h:349
struct ast_bridge * bridge
Definition: control.c:64

References ao2_ref, ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_DEPARTABLE, ast_bridge_set_after_callback(), stasis_app_control::bridge, dial_bridge_after_cb(), dial_bridge_after_cb_failed(), get_dial_bridge(), and NULL.

Referenced by app_control_dial(), and depart_channel().

◆ app_control_add_role()

static int app_control_add_role ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 328 of file control.c.

330{
331 char *role = data;
332
333 return ast_channel_add_bridge_role(chan, role);
334}
int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.
Definition: bridge_roles.c:313

References ast_channel_add_bridge_role(), and stasis_app_command::data.

Referenced by stasis_app_control_add_role().

◆ app_control_can_add_channel_to_bridge()

static int app_control_can_add_channel_to_bridge ( struct stasis_app_control control)
static

Definition at line 258 of file control.c.

260{
261 return app_control_check_rules(control, &control->add_rules);
262}
static enum stasis_app_control_channel_result app_control_check_rules(const struct stasis_app_control *control, struct app_control_rules *list)
Definition: control.c:216
struct app_control_rules add_rules
Definition: control.c:76

References stasis_app_control::add_rules, and app_control_check_rules().

Referenced by stasis_app_control_add_channel_to_bridge().

◆ app_control_can_remove_channel_from_bridge()

static int app_control_can_remove_channel_from_bridge ( struct stasis_app_control control)
static

Definition at line 264 of file control.c.

266{
267 return app_control_check_rules(control, &control->remove_rules);
268}
struct app_control_rules remove_rules
Definition: control.c:80

References app_control_check_rules(), and stasis_app_control::remove_rules.

Referenced by stasis_app_control_remove_channel_from_bridge().

◆ app_control_check_rules()

static enum stasis_app_control_channel_result app_control_check_rules ( const struct stasis_app_control control,
struct app_control_rules list 
)
static

Definition at line 216 of file control.c.

219{
220 int res = 0;
222 AST_LIST_TRAVERSE(list, rule, next) {
223 if ((res = rule->check_rule(control))) {
224 return res;
225 }
226 }
227 return res;
228}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
Rule to check to see if an operation is allowed.
Definition: stasis_app.h:345
struct stasis_app_control_rule * next
Definition: stasis_app.h:355

References AST_LIST_TRAVERSE, and stasis_app_control_rule::next.

Referenced by app_control_can_add_channel_to_bridge(), and app_control_can_remove_channel_from_bridge().

◆ app_control_clear_roles()

static int app_control_clear_roles ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 350 of file control.c.

352{
354
355 return 0;
356}
void ast_channel_clear_bridge_roles(struct ast_channel *chan)
Removes all bridge roles currently on a channel.
Definition: bridge_roles.c:356

References ast_channel_clear_bridge_roles().

Referenced by stasis_app_control_clear_roles().

◆ app_control_continue()

static int app_control_continue ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 388 of file control.c.

390{
391 struct stasis_app_control_continue_data *continue_data = data;
392
393 ast_assert(control->channel != NULL);
394
395 /* If we're in a Stasis bridge, depart it before going back to the
396 * dialplan */
397 if (stasis_app_get_bridge(control)) {
398 ast_bridge_depart(control->channel);
399 }
400
401 /* Called from stasis_app_exec thread; no lock needed */
402 ast_explicit_goto(control->channel, continue_data->context, continue_data->extension, continue_data->priority);
403
404 control_mark_done(control);
405
406 return 0;
407}
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition: bridge.c:1906
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition: control.c:951
void control_mark_done(struct stasis_app_control *control)
Definition: control.c:374
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6945
char extension[AST_MAX_EXTENSION]
Definition: control.c:384
char context[AST_MAX_CONTEXT]
Definition: control.c:383
struct ast_channel * channel
Definition: control.c:60
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_bridge_depart(), ast_explicit_goto(), stasis_app_control::channel, stasis_app_control_continue_data::context, control_mark_done(), stasis_app_control_continue_data::extension, NULL, stasis_app_control_continue_data::priority, and stasis_app_get_bridge().

Referenced by stasis_app_control_continue().

◆ app_control_dial()

static int app_control_dial ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 1648 of file control.c.

1650{
1651 struct control_dial_args *args = data;
1652 int bridged;
1653
1654 ast_channel_lock(chan);
1655 bridged = ast_channel_is_bridged(chan);
1656 ast_channel_unlock(chan);
1657
1658 if (!bridged && add_to_dial_bridge(control, chan)) {
1659 return -1;
1660 }
1661
1662 if (args->timeout && set_timeout(chan, args->timeout)) {
1663 return -1;
1664 }
1665
1666 if (ast_call(chan, args->dialstring, 0)) {
1667 /* If call fails normally this channel would then just be normally hung up and destroyed.
1668 * In this case though the channel is being handled by the ARI control thread and dial
1669 * bridge which needs to be notified that the channel should be hung up. To do this we
1670 * queue a soft hangup which will cause each to wake up, see that the channel has been
1671 * hung up, and then destroy it.
1672 */
1673 int hangup_flag;
1675 ast_channel_lock(chan);
1676 ast_softhangup_nolock(chan, hangup_flag);
1677 ast_channel_unlock(chan);
1678 return -1;
1679 }
1680
1681 ast_channel_publish_dial(NULL, chan, args->dialstring, NULL);
1682
1683 return 0;
1684}
int ast_bridge_setup_after_goto(struct ast_channel *chan)
Setup any after bridge goto location to begin execution.
Definition: bridge_after.c:435
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6461
#define ast_channel_lock(chan)
Definition: channel.h:2922
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10545
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1126
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
#define ast_channel_unlock(chan)
Definition: channel.h:2923
static int set_timeout(struct ast_channel *chan, unsigned int timeout)
Set dial timeout on a channel to be dialed.
Definition: control.c:1623
static int add_to_dial_bridge(struct stasis_app_control *control, struct ast_channel *chan)
Add a channel to the singleton dial bridge.
Definition: control.c:1061
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
const char * args

References add_to_dial_bridge(), args, ast_bridge_setup_after_goto(), ast_call(), ast_channel_is_bridged(), ast_channel_lock, ast_channel_publish_dial(), ast_channel_unlock, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), NULL, and set_timeout().

Referenced by stasis_app_control_dial().

◆ app_control_dtmf()

static int app_control_dtmf ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 567 of file control.c.

569{
570 struct stasis_app_control_dtmf_data *dtmf_data = data;
571
572 if (ast_channel_state(chan) != AST_STATE_UP) {
574 }
575
576 if (stasis_app_get_bridge(control)) {
577 dtmf_in_bridge(chan, dtmf_data);
578 } else {
579 dtmf_no_bridge(chan, dtmf_data);
580 }
581
582 return 0;
583}
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
static void dtmf_no_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
Definition: control.c:554
static void dtmf_in_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
Definition: control.c:541
@ AST_CONTROL_PROGRESS

References AST_CONTROL_PROGRESS, ast_indicate(), AST_STATE_UP, dtmf_in_bridge(), dtmf_no_bridge(), and stasis_app_get_bridge().

Referenced by stasis_app_control_dtmf().

◆ app_control_hold()

static int app_control_hold ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 760 of file control.c.

762{
764
765 return 0;
766}
@ AST_CONTROL_HOLD

References AST_CONTROL_HOLD, ast_indicate(), and stasis_app_control::channel.

Referenced by stasis_app_control_hold().

◆ app_control_moh_start()

static int app_control_moh_start ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 786 of file control.c.

788{
789 char *moh_class = data;
790
791 if (ast_channel_state(chan) != AST_STATE_UP) {
793 }
794
795 ast_moh_start(chan, moh_class, NULL);
796
797 return 0;
798}
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7766

References AST_CONTROL_PROGRESS, ast_indicate(), ast_moh_start(), AST_STATE_UP, and NULL.

Referenced by stasis_app_control_moh_start().

◆ app_control_moh_stop()

static int app_control_moh_stop ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 811 of file control.c.

813{
814 ast_moh_stop(chan);
815 return 0;
816}
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776

References ast_moh_stop().

Referenced by stasis_app_control_moh_stop().

◆ app_control_move()

static int app_control_move ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 434 of file control.c.

436{
437 struct stasis_app_control_move_data *move_data = data;
438
439 control->next_app = ast_strdup(move_data->app_name);
440 if (!control->next_app) {
441 ast_log(LOG_ERROR, "Allocation failed for next app\n");
442 return -1;
443 }
444
445 if (move_data->app_args) {
446 char *token;
447
448 while ((token = strtok_r(move_data->app_args, ",", &move_data->app_args))) {
449 int res;
450 char *arg;
451
452 if (!(arg = ast_strdup(token))) {
453 ast_log(LOG_ERROR, "Allocation failed for next app arg\n");
454 control_move_cleanup(control);
455 return -1;
456 }
457
458 res = AST_VECTOR_APPEND(&control->next_app_args, arg);
459 if (res) {
460 ast_log(LOG_ERROR, "Failed to append arg to next app args\n");
461 ast_free(arg);
462 control_move_cleanup(control);
463 return -1;
464 }
465 }
466 }
467
468 return 0;
469}
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
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:1722
#define LOG_ERROR
struct stasis_app_control::@489 next_app_args
char * next_app
Definition: control.c:94
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References stasis_app_control_move_data::app_args, stasis_app_control_move_data::app_name, ast_free, ast_log, ast_strdup, AST_VECTOR_APPEND, control_move_cleanup(), LOG_ERROR, stasis_app_control::next_app, and stasis_app_control::next_app_args.

Referenced by stasis_app_control_move().

◆ app_control_mute()

static int app_control_mute ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 639 of file control.c.

641{
642 struct stasis_app_control_mute_data *mute_data = data;
643
644 ast_channel_lock(chan);
645 ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);
646 ast_channel_unlock(chan);
647
648 return 0;
649}
int ast_channel_suppress(struct ast_channel *chan, unsigned int direction, enum ast_frame_type frametype)
Suppress passing of a frame type on a channel.
Definition: channel.c:10777
enum ast_frame_type frametype
Definition: control.c:635

References ast_channel_lock, ast_channel_suppress(), ast_channel_unlock, stasis_app_control::channel, stasis_app_control_mute_data::direction, and stasis_app_control_mute_data::frametype.

Referenced by stasis_app_control_mute().

◆ app_control_redirect()

static int app_control_redirect ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 501 of file control.c.

503{
504 char *endpoint = data;
505 int res;
506
507 ast_assert(control->channel != NULL);
508 ast_assert(endpoint != NULL);
509
510 res = ast_transfer(control->channel, endpoint);
511 if (!res) {
512 ast_log(LOG_NOTICE, "Unsupported transfer requested on channel '%s'\n",
513 ast_channel_name(control->channel));
514 return 0;
515 }
516
517 return 0;
518}
const char * ast_channel_name(const struct ast_channel *chan)
int ast_transfer(struct ast_channel *chan, char *dest)
Transfer a channel (if supported).
Definition: channel.c:6485
#define LOG_NOTICE

References ast_assert, ast_channel_name(), ast_log, ast_transfer(), stasis_app_control::channel, LOG_NOTICE, and NULL.

Referenced by stasis_app_control_redirect().

◆ app_control_register_rule()

static void app_control_register_rule ( struct stasis_app_control control,
struct app_control_rules list,
struct stasis_app_control_rule obj 
)
static

Definition at line 168 of file control.c.

171{
172 ao2_lock(control->command_queue);
173 AST_LIST_INSERT_TAIL(list, obj, next);
174 ao2_unlock(control->command_queue);
175}
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
struct ao2_container * command_queue
Definition: control.c:54

References ao2_lock, ao2_unlock, AST_LIST_INSERT_TAIL, and stasis_app_control::command_queue.

Referenced by stasis_app_control_register_add_rule(), and stasis_app_control_register_remove_rule().

◆ app_control_remove_channel_from_bridge()

static int app_control_remove_channel_from_bridge ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 1414 of file control.c.

1417{
1418 struct ast_bridge *bridge = data;
1419
1420 if (!control) {
1421 return -1;
1422 }
1423
1424 /* We should only depart from our own bridge */
1425 ast_debug(3, "%s: Departing bridge %s\n",
1427 bridge->uniqueid);
1428
1429 if (bridge != stasis_app_get_bridge(control)) {
1430 ast_log(LOG_WARNING, "%s: Not in bridge %s; not removing\n",
1432 bridge->uniqueid);
1433 return -1;
1434 }
1435
1436 depart_channel(control, chan);
1437 return 0;
1438}
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:1450
static int depart_channel(struct stasis_app_control *control, struct ast_channel *chan)
Depart a channel from a bridge, and potentially add it back to the dial bridge.
Definition: control.c:1089
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
const ast_string_field uniqueid
Definition: bridge.h:401

References ast_debug, ast_log, depart_channel(), LOG_WARNING, stasis_app_control_get_channel_id(), stasis_app_get_bridge(), and ast_bridge::uniqueid.

Referenced by stasis_app_control_remove_channel_from_bridge().

◆ app_control_ring()

static int app_control_ring ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 604 of file control.c.

606{
608
609 return 0;
610}
@ AST_CONTROL_RINGING

References AST_CONTROL_RINGING, ast_indicate(), and stasis_app_control::channel.

Referenced by stasis_app_control_ring().

◆ app_control_ring_stop()

static int app_control_ring_stop ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 619 of file control.c.

621{
622 ast_indicate(control->channel, -1);
623
624 return 0;
625}

References ast_indicate(), and stasis_app_control::channel.

Referenced by stasis_app_control_ring_stop().

◆ app_control_set_channel_var()

static int app_control_set_channel_var ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 721 of file control.c.

723{
724 struct chanvar *var = data;
725
726 pbx_builtin_setvar_helper(control->channel, var->name, var->value);
727
728 return 0;
729}
#define var
Definition: ast_expr2f.c:605
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
structure for queuing ARI channel variable setting
Definition: control.c:705

References stasis_app_control::channel, pbx_builtin_setvar_helper(), and var.

Referenced by stasis_app_control_set_channel_var().

◆ app_control_silence_start()

static int app_control_silence_start ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 823 of file control.c.

825{
826 if (ast_channel_state(chan) != AST_STATE_UP) {
828 }
829
830 if (control->silgen) {
831 /* We have a silence generator, but it may have been implicitly
832 * disabled by media actions (music on hold, playing media,
833 * etc.) Just stop it and restart a new one.
834 */
836 control->channel, control->silgen);
837 }
838
839 ast_debug(3, "%s: Starting silence generator\n",
842
843 if (!control->silgen) {
845 "%s: Failed to start silence generator.\n",
847 }
848
849 return 0;
850}
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8164
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8210
struct ast_silence_generator * silgen
Definition: control.c:84

References ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), AST_CONTROL_PROGRESS, ast_debug, ast_indicate(), ast_log, AST_STATE_UP, stasis_app_control::channel, LOG_WARNING, stasis_app_control::silgen, and stasis_app_control_get_channel_id().

Referenced by stasis_app_control_silence_start().

◆ app_control_silence_stop()

static int app_control_silence_stop ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 868 of file control.c.

870{
872 return 0;
873}
void control_silence_stop_now(struct stasis_app_control *control)
Stop playing silence to a channel right now.
Definition: control.c:857

References control_silence_stop_now().

Referenced by stasis_app_control_silence_stop().

◆ app_control_unhold()

static int app_control_unhold ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 773 of file control.c.

775{
777
778 return 0;
779}
@ AST_CONTROL_UNHOLD

References AST_CONTROL_UNHOLD, ast_indicate(), and stasis_app_control::channel.

Referenced by stasis_app_control_unhold().

◆ app_control_unmute()

static int app_control_unmute ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 667 of file control.c.

669{
670 struct stasis_app_control_mute_data *mute_data = data;
671
672 ast_channel_lock(chan);
673 ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);
674 ast_channel_unlock(chan);
675
676 return 0;
677}
int ast_channel_unsuppress(struct ast_channel *chan, unsigned int direction, enum ast_frame_type frametype)
Stop suppressing of a frame type on a channel.
Definition: channel.c:10839

References ast_channel_lock, ast_channel_unlock, ast_channel_unsuppress(), stasis_app_control::channel, stasis_app_control_mute_data::direction, and stasis_app_control_mute_data::frametype.

Referenced by stasis_app_control_unmute().

◆ app_control_unregister_rule()

static void app_control_unregister_rule ( struct stasis_app_control control,
struct app_control_rules list,
struct stasis_app_control_rule obj 
)
static

◆ app_send_command_on_condition()

static int app_send_command_on_condition ( struct stasis_app_control control,
stasis_app_command_cb  command_fn,
void *  data,
command_data_destructor_fn  data_destructor,
app_command_can_exec_cb  can_exec_fn 
)
static

Definition at line 886 of file control.c.

890{
891 int ret;
892 struct stasis_app_command *command;
893
894 if (control == NULL || control->is_done) {
895 /* If exec_command_on_condition fails, it calls the data_destructor.
896 * In order to provide consistent behavior, we'll also call the data_destructor
897 * on this error path. This way, callers never have to call the
898 * data_destructor themselves.
899 */
900 if (data_destructor) {
902 }
903 return -1;
904 }
905
907 control, command_fn, data, data_destructor, can_exec_fn);
908 if (!command) {
909 return -1;
910 }
911
912 ret = command_join(command);
913 ao2_ref(command, -1);
914
915 return ret;
916}
int command_join(struct stasis_app_command *command)
Definition: command.c:86
static struct stasis_app_command * exec_command_on_condition(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
Definition: control.c:280
command_data_destructor_fn data_destructor
Definition: command.c:38
unsigned int is_done
Definition: control.c:106

References ao2_ref, command_join(), stasis_app_command::data, stasis_app_command::data_destructor, exec_command_on_condition(), stasis_app_control::is_done, and NULL.

Referenced by stasis_app_control_add_channel_to_bridge(), stasis_app_control_remove_channel_from_bridge(), and stasis_app_send_command().

◆ bridge_after_cb()

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

Definition at line 1183 of file control.c.

1184{
1185 struct stasis_app_control *control = data;
1186
1188}
@ AST_BRIDGE_AFTER_CB_REASON_DEPART
Definition: bridge_after.h:45
static void internal_bridge_after_cb(struct ast_channel *chan, void *data, enum ast_bridge_after_cb_reason reason)
Definition: control.c:1128

References AST_BRIDGE_AFTER_CB_REASON_DEPART, stasis_app_control::channel, and internal_bridge_after_cb().

Referenced by control_swap_channel_in_bridge().

◆ bridge_after_cb_failed()

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

Definition at line 1190 of file control.c.

1192{
1193 struct stasis_app_control *control = data;
1194
1195 internal_bridge_after_cb(control->channel, data, reason);
1196
1197 ast_debug(3, " reason: %s\n",
1199}
const char * ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason)
Get a string representation of an after bridge callback reason.
Definition: bridge_after.c:288

References ast_bridge_after_cb_reason_string(), ast_debug, stasis_app_control::channel, and internal_bridge_after_cb().

Referenced by control_swap_channel_in_bridge().

◆ bridge_channel_depart()

static int bridge_channel_depart ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 1105 of file control.c.

1107{
1108 struct ast_bridge_channel *bridge_channel;
1109
1111 bridge_channel = ast_channel_internal_bridge_channel(chan);
1113
1114 if (bridge_channel != data) {
1115 ast_debug(3, "%s: Channel is no longer in departable state\n",
1117 return -1;
1118 }
1119
1120 ast_debug(3, "%s: Channel departing bridge\n",
1122
1123 depart_channel(control, chan);
1124
1125 return 0;
1126}
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_internal_bridge_channel(const struct ast_channel *chan)
Structure that contains information regarding a channel in a bridge.
struct ast_channel * chan

References ast_channel_internal_bridge_channel(), ast_channel_lock, ast_channel_uniqueid(), ast_channel_unlock, ast_debug, ast_bridge_channel::chan, and depart_channel().

Referenced by dial_bridge_after_cb(), and internal_bridge_after_cb().

◆ bridge_timeout()

static int bridge_timeout ( struct ast_bridge_channel bridge_channel,
void *  ignore 
)
static

Dial timeout.

This is a bridge interval hook callback. The interval hook triggering means that the dial timeout has been reached. If the channel has not been answered by the time this callback is called, then the channel is hung up

Parameters
bridge_channelBridge channel on which interval hook has been called
ignoreIgnored
Returns
-1 (i.e. remove the interval hook)

Definition at line 1235 of file control.c.

1236{
1237 struct ast_datastore *datastore;
1238 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1239
1240 control = stasis_app_control_find_by_channel(bridge_channel->chan);
1241
1242 ast_channel_lock(bridge_channel->chan);
1243 if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) {
1244 /* Don't bother removing the datastore because it will happen when the channel is hung up */
1245 ast_channel_unlock(bridge_channel->chan);
1247 return -1;
1248 }
1249
1250 datastore = ast_channel_datastore_find(bridge_channel->chan, &timeout_datastore, NULL);
1251 if (!datastore) {
1252 ast_channel_unlock(bridge_channel->chan);
1253 return -1;
1254 }
1255 ast_channel_datastore_remove(bridge_channel->chan, datastore);
1256 ast_channel_unlock(bridge_channel->chan);
1257 ast_datastore_free(datastore);
1258
1259 return -1;
1260}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
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:2399
struct ast_datastore_info timeout_datastore
Dial timeout datastore.
Definition: control.c:1212
int stasis_app_send_command_async(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
Asynchronous version of stasis_app_send_command().
Definition: control.c:924
static int hangup_channel(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1216
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
struct stasis_app_control * stasis_app_control_find_by_channel(const struct ast_channel *chan)
Returns the handler for the given channel.
Definition: res_stasis.c:338
Structure for a data store object.
Definition: datastore.h:64
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_unlock, ast_datastore_free(), AST_STATE_UP, ast_bridge_channel::chan, hangup_channel(), NULL, RAII_VAR, stasis_app_control_find_by_channel(), stasis_app_send_command_async(), and timeout_datastore.

Referenced by set_interval_hook().

◆ control_add_channel_to_bridge()

int control_add_channel_to_bridge ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)

Command callback for adding a channel to a bridge.

Parameters
controlThe control for chan
chanThe channel on which commands should be executed
dataBridge to be passed to the callback

Definition at line 1398 of file control.c.

1399{
1400 return control_swap_channel_in_bridge(control, data, chan, NULL);
1401}
int control_swap_channel_in_bridge(struct stasis_app_control *control, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap)
Command for swapping a channel in a bridge.
Definition: control.c:1304

References control_swap_channel_in_bridge(), and NULL.

Referenced by stasis_app_control_add_channel_to_bridge().

◆ control_app()

struct stasis_app * control_app ( struct stasis_app_control control)

Returns the pointer (non-reffed) to the app associated with this control.

Parameters
controlControl to query.
Returns
A pointer to the associated stasis_app

Definition at line 1583 of file control.c.

1584{
1585 return control->app;
1586}
struct stasis_app * app
Definition: control.c:90

References stasis_app_control::app.

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

◆ control_command_count()

int control_command_count ( struct stasis_app_control control)

Returns the count of items in a control's command queue.

Parameters
controlControl to count commands on
Returns
number of commands in the command que

Definition at line 363 of file control.c.

364{
365 return ao2_container_count(control->command_queue);
366}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.

References ao2_container_count(), and stasis_app_control::command_queue.

Referenced by stasis_app_control_execute_until_exhausted().

◆ control_create()

struct stasis_app_control * control_create ( struct ast_channel channel,
struct stasis_app app 
)

Create a control object.

Parameters
channelChannel to control.
appstasis_app for which this control is being created.
Returns
New control object.
Return values
NULLon error.

Definition at line 127 of file control.c.

128{
129 struct stasis_app_control *control;
130 int res;
131
132 control = ao2_alloc(sizeof(*control), control_dtor);
133 if (!control) {
134 return NULL;
135 }
136
137 AST_LIST_HEAD_INIT(&control->add_rules);
139
140 res = ast_cond_init(&control->wait_cond, NULL);
141 if (res != 0) {
142 ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
143 strerror(errno));
144 ao2_ref(control, -1);
145 return NULL;
146 }
147
148 control->app = ao2_bump(app);
149
151 control->channel = channel;
152
155 if (!control->command_queue) {
156 ao2_ref(control, -1);
157 return NULL;
158 }
159
160 control->next_app = NULL;
161 AST_VECTOR_INIT(&control->next_app_args, 0);
162
164
165 return control;
166}
static const char app[]
Definition: app_adsiprog.c:56
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
void control_set_thread(struct stasis_app_control *control, pthread_t threadid)
set the control's thread id
Definition: control.c:194
static void control_dtor(void *obj)
Definition: control.c:109
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_cond_init(cond, attr)
Definition: lock.h:201
int errno
ast_cond_t wait_cond
Definition: control.c:52
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References stasis_app_control::add_rules, ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_bump, ao2_container_alloc_list, ao2_ref, app, stasis_app_control::app, ast_channel_ref, ast_cond_init, AST_LIST_HEAD_INIT, ast_log, AST_PTHREADT_NULL, AST_VECTOR_INIT, stasis_app_control::channel, stasis_app_control::command_queue, control_dtor(), control_set_thread(), errno, LOG_ERROR, stasis_app_control::next_app, stasis_app_control::next_app_args, NULL, stasis_app_control::remove_rules, and stasis_app_control::wait_cond.

Referenced by stasis_app_control_create(), and stasis_app_exec().

◆ control_dial_args_alloc()

static struct control_dial_args * control_dial_args_alloc ( const char *  dialstring,
unsigned int  timeout 
)
static

Definition at line 1593 of file control.c.

1595{
1596 struct control_dial_args *args;
1597
1598 args = ast_malloc(sizeof(*args) + strlen(dialstring) + 1);
1599 if (!args) {
1600 return NULL;
1601 }
1602
1603 args->timeout = timeout;
1604 /* Safe */
1605 strcpy(args->dialstring, dialstring);
1606
1607 return args;
1608}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
char dialstring[0]
Definition: control.c:1590
unsigned int timeout
Definition: control.c:1589

References args, ast_malloc, control_dial_args::dialstring, NULL, and control_dial_args::timeout.

Referenced by stasis_app_control_dial().

◆ control_dial_args_destroy()

static void control_dial_args_destroy ( void *  data)
static

Definition at line 1610 of file control.c.

1611{
1612 struct control_dial_args *args = data;
1613
1614 ast_free(args);
1615}

References args, and ast_free.

Referenced by stasis_app_control_dial().

◆ control_dispatch_all()

int control_dispatch_all ( struct stasis_app_control control,
struct ast_channel chan 
)

Dispatch all commands enqueued to this control.

Parameters
controlControl object to dispatch.
chanAssociated channel.
Returns
Number of commands executed

Definition at line 1515 of file control.c.

1517{
1518 int count = 0;
1519 struct ao2_iterator iter;
1520 struct stasis_app_command *command;
1521
1522 ast_assert(control->channel == chan);
1523
1525 while ((command = ao2_iterator_next(&iter))) {
1526 command_invoke(command, control, chan);
1527 ao2_ref(command, -1);
1528 ++count;
1529 }
1530 ao2_iterator_destroy(&iter);
1531
1532 return count;
1533}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
@ AO2_ITERATOR_UNLINK
Definition: astobj2.h:1863
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
void command_invoke(struct stasis_app_command *command, struct stasis_app_control *control, struct ast_channel *chan)
Definition: command.c:101
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, AO2_ITERATOR_UNLINK, ao2_ref, ast_assert, stasis_app_control::channel, command_invoke(), and stasis_app_control::command_queue.

Referenced by stasis_app_control_execute_until_exhausted(), and stasis_app_exec().

◆ control_dtor()

static void control_dtor ( void *  obj)
static

Definition at line 109 of file control.c.

110{
111 struct stasis_app_control *control = obj;
112
113 ao2_cleanup(control->command_queue);
114
116 ao2_cleanup(control->app);
117
118 control_move_cleanup(control);
119
120 ast_cond_destroy(&control->wait_cond);
124
125}
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3674
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:653
#define ast_cond_destroy(cond)
Definition: lock.h:202
struct ast_bridge_features * bridge_features
Definition: control.c:68

References stasis_app_control::add_rules, ao2_cleanup, stasis_app_control::app, ast_bridge_features_destroy(), ast_channel_cleanup, ast_cond_destroy, AST_LIST_HEAD_DESTROY, stasis_app_control::bridge_features, stasis_app_control::channel, stasis_app_control::command_queue, control_move_cleanup(), stasis_app_control::remove_rules, and stasis_app_control::wait_cond.

Referenced by control_create().

◆ control_flush_queue()

void 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 1502 of file control.c.

1503{
1504 struct ao2_iterator iter;
1505 struct stasis_app_command *command;
1506
1508 while ((command = ao2_iterator_next(&iter))) {
1509 command_complete(command, -1);
1510 ao2_ref(command, -1);
1511 }
1512 ao2_iterator_destroy(&iter);
1513}
void command_complete(struct stasis_app_command *command, int retval)
Definition: command.c:77

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, AO2_ITERATOR_UNLINK, ao2_ref, command_complete(), and stasis_app_control::command_queue.

Referenced by stasis_app_control_flush_queue(), and stasis_app_exec().

◆ control_is_done()

int control_is_done ( struct stasis_app_control control)

Returns true if control_continue() has been called on this control.

Parameters
controlControl to query.
Return values
True(non-zero) if control_continue() has been called.
False(zero) otherwise.

Definition at line 368 of file control.c.

369{
370 /* Called from stasis_app_exec thread; no lock needed */
371 return control->is_done;
372}

References stasis_app_control::is_done.

Referenced by stasis_app_control_execute_until_exhausted(), stasis_app_control_is_done(), and stasis_app_exec().

◆ control_mark_done()

void control_mark_done ( struct stasis_app_control control)

Definition at line 374 of file control.c.

375{
376 /* Locking necessary to sync with other threads adding commands to the queue. */
377 ao2_lock(control->command_queue);
378 control->is_done = 1;
379 ao2_unlock(control->command_queue);
380}

References ao2_lock, ao2_unlock, stasis_app_control::command_queue, and stasis_app_control::is_done.

Referenced by app_control_continue(), stasis_app_control_execute_until_exhausted(), and stasis_app_exec().

◆ control_move_cleanup()

void control_move_cleanup ( struct stasis_app_control control)

Free any memory that was allocated for switching applications via /channels/{channelId}/move.

Parameters
controlThe control for the channel

Definition at line 1722 of file control.c.

1723{
1724 ast_free(control->next_app);
1725 control->next_app = NULL;
1726
1728}
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625

References ast_free, ast_free_ptr(), AST_VECTOR_RESET, stasis_app_control::next_app, stasis_app_control::next_app_args, and NULL.

Referenced by app_control_move(), control_dtor(), and stasis_app_exec().

◆ control_next_app()

char * control_next_app ( struct stasis_app_control control)

Returns the name of the application we are moving to.

Parameters
controlThe control for the channel
Returns
The name of the application we are moving to

Definition at line 1717 of file control.c.

1718{
1719 return control->next_app;
1720}

References stasis_app_control::next_app.

Referenced by stasis_app_exec().

◆ control_next_app_args()

char ** control_next_app_args ( struct stasis_app_control control)

Returns the list of arguments to pass to the application we are moving to.

Note
If you wish to get the size of the list, control_next_app_args_size should be called before this, as this function will steal the elements from the string vector and set the size to 0.
Parameters
controlThe control for the channel
Returns
The arguments to pass to the application we are moving to

Definition at line 1730 of file control.c.

1731{
1732 return AST_VECTOR_STEAL_ELEMENTS(&control->next_app_args);
1733}
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition: vector.h:140

References AST_VECTOR_STEAL_ELEMENTS, and stasis_app_control::next_app_args.

Referenced by stasis_app_exec().

◆ control_next_app_args_size()

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.

Note
This should always be called before control_next_app_args, as calling that function will steal all elements from the string vector and set the size to 0.
Parameters
controlThe control for the channel
Returns
The number of arguments to be passed to the application we are moving to

Definition at line 1735 of file control.c.

1736{
1737 return AST_VECTOR_SIZE(&control->next_app_args);
1738}
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609

References AST_VECTOR_SIZE, and stasis_app_control::next_app_args.

Referenced by stasis_app_exec().

◆ control_prestart_dispatch_all()

int control_prestart_dispatch_all ( struct stasis_app_control control,
struct ast_channel chan 
)

Dispatch all queued prestart commands.

Parameters
controlThe control for chan
chanThe channel on which commands should be executed
Returns
The number of commands executed

Definition at line 1555 of file control.c.

1557{
1558 struct ao2_container *command_queue;
1559 int count = 0;
1560 struct ao2_iterator iter;
1561 struct stasis_app_command *command;
1562
1563 ast_channel_lock(chan);
1564 command_queue = command_prestart_get_container(chan);
1565 ast_channel_unlock(chan);
1566 if (!command_queue) {
1567 return 0;
1568 }
1569
1570 iter = ao2_iterator_init(command_queue, AO2_ITERATOR_UNLINK);
1571
1572 while ((command = ao2_iterator_next(&iter))) {
1573 command_invoke(command, control, chan);
1574 ao2_cleanup(command);
1575 ++count;
1576 }
1577
1578 ao2_iterator_destroy(&iter);
1579 ao2_cleanup(command_queue);
1580 return count;
1581}
struct ao2_container * command_prestart_get_container(struct ast_channel *chan)
Get the Stasis() prestart commands for a channel.
Definition: command.c:160
Generic container type.

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, AO2_ITERATOR_UNLINK, ast_channel_lock, ast_channel_unlock, command_invoke(), and command_prestart_get_container().

Referenced by stasis_app_exec().

◆ control_set_app()

void control_set_app ( struct stasis_app_control control,
struct stasis_app app 
)

Set the application the control object belongs to.

Parameters
controlThe control for the channel
appThe application this control will now belong to
Note
This will unref control's previous app by 1, and bump app by 1

Definition at line 1711 of file control.c.

1712{
1713 ao2_cleanup(control->app);
1714 control->app = ao2_bump(app);
1715}

References ao2_bump, ao2_cleanup, app, and stasis_app_control::app.

Referenced by stasis_app_exec().

◆ control_set_thread()

void control_set_thread ( struct stasis_app_control control,
pthread_t  threadid 
)

set the control's thread id

Since
18
Parameters
controlControl object on which to set the thread id.
threadidid to set

Definition at line 194 of file control.c.

195{
196 ao2_lock(control->command_queue);
197 control->control_thread = threadid;
198 ao2_unlock(control->command_queue);
199}
pthread_t control_thread
Definition: control.c:98

References ao2_lock, ao2_unlock, stasis_app_control::command_queue, and stasis_app_control::control_thread.

Referenced by control_create(), and stasis_app_exec().

◆ control_silence_stop_now()

void control_silence_stop_now ( struct stasis_app_control control)

Stop playing silence to a channel right now.

Since
13.9.0
Parameters
controlThe control for chan

Definition at line 857 of file control.c.

858{
859 if (control->silgen) {
860 ast_debug(3, "%s: Stopping silence generator\n",
863 control->channel, control->silgen);
864 control->silgen = NULL;
865 }
866}

References ast_channel_stop_silence_generator(), ast_debug, stasis_app_control::channel, NULL, stasis_app_control::silgen, and stasis_app_control_get_channel_id().

Referenced by app_control_silence_stop(), and stasis_app_exec().

◆ control_swap_channel_in_bridge()

int control_swap_channel_in_bridge ( struct stasis_app_control control,
struct ast_bridge bridge,
struct ast_channel chan,
struct ast_channel swap 
)

Command for swapping a channel in a bridge.

Parameters
controlThe control for chan
chanThe channel on which commands should be executed
bridgeBridge to be passed to the callback
swapChannel to swap with when joining the bridge

Definition at line 1304 of file control.c.

1305{
1306 int res;
1307 struct ast_bridge_features *features;
1309
1310 if (!control || !bridge) {
1311 return -1;
1312 }
1313
1314 ast_debug(3, "%s: Adding to bridge %s\n",
1316 bridge->uniqueid);
1317
1318 ast_assert(chan != NULL);
1319
1320 /* Depart whatever Stasis bridge we're currently in. */
1321 if (stasis_app_get_bridge(control)) {
1322 /* Note that it looks like there's a race condition here, since
1323 * we don't have control locked. But this happens from the
1324 * control callback thread, so there won't be any other
1325 * concurrent attempts to bridge.
1326 */
1327 ast_bridge_depart(chan);
1328 }
1329
1330
1332 bridge_after_cb_failed, control);
1333 if (res != 0) {
1334 ast_log(LOG_ERROR, "Error setting after-bridge callback\n");
1335 return -1;
1336 }
1337
1338 ao2_lock(control);
1339
1340 /* Ensure the controlling application is subscribed early enough
1341 * to receive the ChannelEnteredBridge message. This works in concert
1342 * with the subscription handled in the Stasis application execution
1343 * loop */
1344 app_subscribe_bridge(control->app, bridge);
1345
1346 /* Save off the channel's PBX */
1347 ast_assert(control->pbx == NULL);
1348 if (!control->pbx) {
1349 control->pbx = ast_channel_pbx(chan);
1351 }
1352
1353 /* Pull bridge features from the control */
1354 features = control->bridge_features;
1355 control->bridge_features = NULL;
1356 if (features && features->inhibit_colp) {
1358 }
1359
1361 /* We need to set control->bridge here since bridge_after_cb may be run
1362 * before ast_bridge_impart returns. bridge_after_cb gets a reason
1363 * code so it can tell if the bridge is actually valid or not.
1364 */
1365 control->bridge = bridge;
1366
1367 /* We can't be holding the control lock while impart is running
1368 * or we could create a deadlock with bridge_after_cb which also
1369 * tries to lock control.
1370 */
1371 ao2_unlock(control);
1372 res = ast_bridge_impart(bridge,
1373 chan,
1374 swap,
1375 features, /* features */
1376 flags);
1377 if (res != 0) {
1378 /* ast_bridge_impart failed before it could spawn the depart
1379 * thread. The callbacks aren't called in this case.
1380 * The impart could still fail even if ast_bridge_impart returned
1381 * ok but that's handled by bridge_after_cb.
1382 */
1383 ast_log(LOG_ERROR, "Error adding channel to bridge\n");
1384 ao2_lock(control);
1385 ast_channel_pbx_set(chan, control->pbx);
1386 control->pbx = NULL;
1387 control->bridge = NULL;
1388 ao2_unlock(control);
1389 } else {
1390 ast_channel_lock(chan);
1391 set_interval_hook(chan);
1392 ast_channel_unlock(chan);
1393 }
1394
1395 return res;
1396}
@ AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP
Definition: bridge.h:592
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
static void set_interval_hook(struct ast_channel *chan)
Set a dial timeout interval hook on the channel.
Definition: control.c:1274
static void bridge_after_cb(struct ast_channel *chan, void *data)
Definition: control.c:1183
static void bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition: control.c:1190
int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Add a bridge subscription to an existing channel subscription.
Structure that contains features information.
unsigned int inhibit_colp
struct ast_pbx * pbx
Definition: control.c:72

References ao2_lock, ao2_unlock, stasis_app_control::app, app_subscribe_bridge(), ast_assert, ast_bridge_depart(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_DEPARTABLE, AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP, ast_bridge_set_after_callback(), ast_channel_lock, ast_channel_pbx(), ast_channel_pbx_set(), ast_channel_unlock, ast_debug, ast_log, stasis_app_control::bridge, bridge_after_cb(), bridge_after_cb_failed(), stasis_app_control::bridge_features, ast_bridge_features::inhibit_colp, LOG_ERROR, NULL, stasis_app_control::pbx, set_interval_hook(), stasis_app_control_get_channel_id(), stasis_app_get_bridge(), and ast_bridge::uniqueid.

Referenced by control_add_channel_to_bridge(), and defer_bridge_add().

◆ control_wait()

void control_wait ( struct stasis_app_control control)

Blocks until control's command queue has a command available.

Parameters
controlControl to block on.

Definition at line 1535 of file control.c.

1536{
1537 if (!control) {
1538 return;
1539 }
1540
1541 ast_assert(control->command_queue != NULL);
1542
1543 ao2_lock(control->command_queue);
1544 while (ao2_container_count(control->command_queue) == 0) {
1545 int res = ast_cond_wait(&control->wait_cond,
1547 if (res < 0) {
1548 ast_log(LOG_ERROR, "Error waiting on command queue\n");
1549 break;
1550 }
1551 }
1552 ao2_unlock(control->command_queue);
1553}
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205

References ao2_container_count(), ao2_lock, ao2_object_get_lockaddr(), ao2_unlock, ast_assert, ast_cond_wait, ast_log, stasis_app_control::command_queue, LOG_ERROR, NULL, and stasis_app_control::wait_cond.

Referenced by stasis_app_exec().

◆ depart_channel()

static int depart_channel ( struct stasis_app_control control,
struct ast_channel chan 
)
static

Depart a channel from a bridge, and potentially add it back to the dial bridge.

Parameters
controlTake a guess
chanTake another guess

Definition at line 1089 of file control.c.

1090{
1091 ast_bridge_depart(chan);
1092
1093 /* Channels which have a PBX are not ones that have been created and dialed from ARI. They
1094 * have externally come in from the dialplan, and thus should not be placed into the dial
1095 * bridge. Only channels which are created and dialed in ARI should go into the dial bridge.
1096 */
1097 if (!ast_check_hangup(chan) && ast_channel_state(chan) != AST_STATE_UP && !ast_channel_pbx(chan)) {
1098 /* Channel is still being dialed, so put it back in the dialing bridge */
1099 add_to_dial_bridge(control, chan);
1100 }
1101
1102 return 0;
1103}
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445

References add_to_dial_bridge(), ast_bridge_depart(), ast_channel_pbx(), ast_check_hangup(), and AST_STATE_UP.

Referenced by app_control_remove_channel_from_bridge(), and bridge_channel_depart().

◆ dial_bridge_after_cb()

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

after bridge callback for the dial bridge

The only purpose of this callback is to ensure that the control structure's bridge pointer is NULLed

Definition at line 1029 of file control.c.

1030{
1031 struct stasis_app_control *control = data;
1032 struct ast_bridge_channel *bridge_channel;
1033
1035 bridge_channel = ast_channel_get_bridge_channel(chan);
1037
1038 ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), ast_channel_hangupcause(chan));
1039
1041
1042 control->bridge = NULL;
1043}
void __ao2_cleanup(void *obj)
Definition: astobj2.c:677
int ast_channel_hangupcause(const struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10582
static int bridge_channel_depart(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1105

References __ao2_cleanup(), ast_channel_get_bridge_channel(), ast_channel_hangupcause(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, stasis_app_control::bridge, bridge_channel_depart(), ast_bridge_channel::chan, stasis_app_control::channel, NULL, and stasis_app_send_command_async().

Referenced by add_to_dial_bridge(), and dial_bridge_after_cb_failed().

◆ dial_bridge_after_cb_failed()

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

Definition at line 1045 of file control.c.

1046{
1047 struct stasis_app_control *control = data;
1048
1049 ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), reason);
1050 dial_bridge_after_cb(control->channel, data);
1051}

References ast_channel_name(), ast_debug, stasis_app_control::channel, and dial_bridge_after_cb().

Referenced by add_to_dial_bridge().

◆ dtmf_in_bridge()

static void dtmf_in_bridge ( struct ast_channel chan,
struct stasis_app_control_dtmf_data dtmf_data 
)
static

Definition at line 541 of file control.c.

542{
543 if (dtmf_data->before) {
544 usleep(dtmf_data->before * 1000);
545 }
546
547 ast_dtmf_stream_external(chan, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
548
549 if (dtmf_data->after) {
550 usleep(dtmf_data->after * 1000);
551 }
552}
void ast_dtmf_stream_external(struct ast_channel *chan, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel from an external thread.
Definition: main/app.c:1142

References stasis_app_control_dtmf_data::after, ast_dtmf_stream_external(), stasis_app_control_dtmf_data::before, stasis_app_control_dtmf_data::between, stasis_app_control_dtmf_data::dtmf, and stasis_app_control_dtmf_data::duration.

Referenced by app_control_dtmf().

◆ dtmf_no_bridge()

static void dtmf_no_bridge ( struct ast_channel chan,
struct stasis_app_control_dtmf_data dtmf_data 
)
static

Definition at line 554 of file control.c.

555{
556 if (dtmf_data->before) {
557 ast_safe_sleep(chan, dtmf_data->before);
558 }
559
560 ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
561
562 if (dtmf_data->after) {
563 ast_safe_sleep(chan, dtmf_data->after);
564 }
565}
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel.
Definition: main/app.c:1127

References stasis_app_control_dtmf_data::after, ast_dtmf_stream(), ast_safe_sleep(), stasis_app_control_dtmf_data::before, stasis_app_control_dtmf_data::between, stasis_app_control_dtmf_data::dtmf, stasis_app_control_dtmf_data::duration, and NULL.

Referenced by app_control_dtmf().

◆ exec_command()

static struct stasis_app_command * exec_command ( struct stasis_app_control control,
stasis_app_command_cb  command_fn,
void *  data,
command_data_destructor_fn  data_destructor 
)
static

Definition at line 321 of file control.c.

324{
325 return exec_command_on_condition(control, command_fn, data, data_destructor, NULL);
326}

References stasis_app_command::data, stasis_app_command::data_destructor, exec_command_on_condition(), and NULL.

Referenced by stasis_app_send_command_async().

◆ exec_command_on_condition()

static struct stasis_app_command * exec_command_on_condition ( struct stasis_app_control control,
stasis_app_command_cb  command_fn,
void *  data,
command_data_destructor_fn  data_destructor,
app_command_can_exec_cb  can_exec_fn 
)
static

Definition at line 280 of file control.c.

284{
285 int retval;
286 struct stasis_app_command *command;
287
288 command_fn = command_fn ? : noop_cb;
289
290 command = command_create(command_fn, data, data_destructor);
291 if (!command) {
292 return NULL;
293 }
294
295 ao2_lock(control->command_queue);
296 if (control->is_done) {
297 ao2_unlock(control->command_queue);
298 ao2_ref(command, -1);
299 return NULL;
300 }
301 if (can_exec_fn && (retval = can_exec_fn(control))) {
302 ao2_unlock(control->command_queue);
303 command_complete(command, retval);
304 return command;
305 }
306
307 ao2_link_flags(control->command_queue, command, OBJ_NOLOCK);
308 ast_cond_signal(&control->wait_cond);
309
310 if (control->control_thread != AST_PTHREADT_NULL) {
311 /* if the control thread is waiting on the channel, send the SIGURG
312 to let it know there is a new command */
313 pthread_kill(control->control_thread, SIGURG);
314 }
315
316 ao2_unlock(control->command_queue);
317
318 return command;
319}
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
struct stasis_app_command * command_create(stasis_app_command_cb callback, void *data, command_data_destructor_fn data_destructor)
Definition: command.c:55
static int noop_cb(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:270
static ENTRY retval
Definition: hsearch.c:50
#define ast_cond_signal(cond)
Definition: lock.h:203

References ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, ast_cond_signal, AST_PTHREADT_NULL, command_complete(), command_create(), stasis_app_control::command_queue, stasis_app_control::control_thread, stasis_app_command::data, stasis_app_command::data_destructor, stasis_app_control::is_done, noop_cb(), NULL, OBJ_NOLOCK, retval, and stasis_app_control::wait_cond.

Referenced by app_send_command_on_condition(), and exec_command().

◆ free_chanvar()

static void free_chanvar ( void *  data)
static

Definition at line 712 of file control.c.

713{
714 struct chanvar *var = data;
715
716 ast_free(var->name);
717 ast_free(var->value);
718 ast_free(var);
719}

References ast_free, and var.

Referenced by stasis_app_control_set_channel_var().

◆ get_dial_bridge()

static struct ast_bridge * get_dial_bridge ( void  )
static

Retrieve a reference to the dial bridge.

If the dial bridge has not been created yet, it will be created, otherwise, a reference to the existing bridge will be returned.

The caller will need to unreference the dial bridge once they are finished with it.

Return values
NULLUnable to find/create the dial bridge
non-NULLA reference to the dial bridge

Definition at line 994 of file control.c.

995{
996 struct ast_bridge *ret_bridge = NULL;
997
999
1000 if (shutting_down) {
1001 goto end;
1002 }
1003
1004 if (dial_bridge) {
1005 ret_bridge = ao2_bump(dial_bridge);
1006 goto end;
1007 }
1008
1009 dial_bridge = stasis_app_bridge_create_invisible("holding", "dial_bridge", NULL);
1010 if (!dial_bridge) {
1011 goto end;
1012 }
1013 ret_bridge = ao2_bump(dial_bridge);
1014
1015end:
1017 return ret_bridge;
1018}
static struct ast_bridge * dial_bridge
Singleton dial bridge.
Definition: control.c:978
static int shutting_down
Indicates if the Stasis app internals are being shut down.
Definition: control.c:49
static ast_mutex_t dial_bridge_lock
Definition: control.c:979
char * end
Definition: eagi_proxy.c:73
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
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.
Definition: res_stasis.c:859

References ao2_bump, ast_mutex_lock, ast_mutex_unlock, dial_bridge, dial_bridge_lock, end, NULL, shutting_down, and stasis_app_bridge_create_invisible().

Referenced by add_to_dial_bridge().

◆ hangup_channel()

static int hangup_channel ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 1216 of file control.c.

1218{
1220 return 0;
1221}
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148

References ast_softhangup(), and AST_SOFTHANGUP_EXPLICIT.

Referenced by bridge_timeout().

◆ internal_bridge_after_cb()

static void internal_bridge_after_cb ( struct ast_channel chan,
void *  data,
enum ast_bridge_after_cb_reason  reason 
)
static

Definition at line 1128 of file control.c.

1130{
1131 struct stasis_app_control *control = data;
1132 struct ast_bridge_channel *bridge_channel;
1133
1134 ao2_lock(control);
1135 ast_debug(3, "%s, %s: %s\n",
1136 ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown",
1138
1140 /* The impart actually failed so control->bridge isn't valid. */
1141 control->bridge = NULL;
1142 }
1143
1144 ast_assert(chan == control->channel);
1145
1146 /* Restore the channel's PBX */
1147 ast_channel_pbx_set(control->channel, control->pbx);
1148 control->pbx = NULL;
1149
1150 if (control->bridge) {
1151 app_unsubscribe_bridge(control->app, control->bridge);
1152
1153 /* No longer in the bridge */
1154 control->bridge = NULL;
1155
1156 /* Get the bridge channel so we don't depart from the wrong bridge */
1158 bridge_channel = ast_channel_get_bridge_channel(chan);
1160
1161 /* Depart this channel from the bridge using the command queue if possible */
1163 }
1164
1166 /* The channel has had a StasisEnd published on it, but until now had remained in
1167 * the bridging system. This means that the channel moved from a Stasis bridge to a
1168 * non-Stasis bridge and is now exiting the bridging system. Because of this, the
1169 * channel needs to exit the Stasis application and go to wherever the non-Stasis
1170 * bridge has directed it to go. If the non-Stasis bridge has not set up an after
1171 * bridge destination, then the channel should be hung up.
1172 */
1173 int hangup_flag;
1174
1177 ast_softhangup_nolock(chan, hangup_flag);
1179 }
1180 ao2_unlock(control);
1181}
@ AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED
Definition: bridge_after.h:49
int app_unsubscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Cancel the bridge subscription for an application.
int stasis_app_channel_is_stasis_end_published(struct ast_channel *chan)
Has this channel had a StasisEnd published on it?
Definition: res_stasis.c:1302

References __ao2_cleanup(), ao2_lock, ao2_unlock, stasis_app_control::app, app_unsubscribe_bridge(), ast_assert, AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED, ast_bridge_after_cb_reason_string(), ast_bridge_setup_after_goto(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_pbx_set(), ast_channel_uniqueid(), ast_channel_unlock, ast_debug, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), stasis_app_control::bridge, bridge_channel_depart(), ast_bridge_channel::chan, stasis_app_control::channel, NULL, stasis_app_control::pbx, stasis_app_channel_is_stasis_end_published(), stasis_app_send_command_async(), and ast_bridge::uniqueid.

Referenced by bridge_after_cb(), and bridge_after_cb_failed().

◆ noop_cb()

static int noop_cb ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 270 of file control.c.

272{
273 return 0;
274}

Referenced by exec_command_on_condition().

◆ set_interval_hook()

static void set_interval_hook ( struct ast_channel chan)
static

Set a dial timeout interval hook on the channel.

The absolute time that the timeout should occur is stored on a datastore on the channel. This time is converted into a relative number of milliseconds in the future. Then an interval hook is set to trigger in that number of milliseconds.

Precondition
chan is locked
Parameters
chanThe channel on which to set the interval hook

Definition at line 1274 of file control.c.

1275{
1276 struct ast_datastore *datastore;
1277 struct timeval *hangup_time;
1278 int64_t ms;
1279 struct ast_bridge_channel *bridge_channel;
1280
1282 if (!datastore) {
1283 return;
1284 }
1285
1286 hangup_time = datastore->data;
1287
1288 ms = ast_tvdiff_ms(*hangup_time, ast_tvnow());
1289 bridge_channel = ast_channel_get_bridge_channel(chan);
1290 if (!bridge_channel) {
1291 return;
1292 }
1293
1294 if (ast_bridge_interval_hook(bridge_channel->features, 0, ms > 0 ? ms : 1,
1295 bridge_timeout, NULL, NULL, 0)) {
1296 ao2_ref(bridge_channel, -1);
1297 return;
1298 }
1299
1300 ast_queue_frame(bridge_channel->chan, &ast_null_frame);
1301 ao2_ref(bridge_channel, -1);
1302}
int ast_bridge_interval_hook(struct ast_bridge_features *features, enum ast_bridge_hook_timer_option flags, unsigned int interval, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach an interval hook to a bridge features structure.
Definition: bridge.c:3319
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
static int bridge_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
Dial timeout.
Definition: control.c:1235
struct ast_frame ast_null_frame
Definition: main/frame.c:79
struct ast_bridge_features * features
void * data
Definition: datastore.h:66
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ao2_ref, ast_bridge_interval_hook(), ast_channel_datastore_find(), ast_channel_get_bridge_channel(), ast_null_frame, ast_queue_frame(), ast_tvdiff_ms(), ast_tvnow(), bridge_timeout(), ast_bridge_channel::chan, ast_datastore::data, ast_bridge_channel::features, NULL, and timeout_datastore.

Referenced by control_swap_channel_in_bridge(), and set_timeout().

◆ set_timeout()

static int set_timeout ( struct ast_channel chan,
unsigned int  timeout 
)
static

Set dial timeout on a channel to be dialed.

Parameters
chanThe channel on which to set the dial timeout
timeoutThe timeout in seconds

Definition at line 1623 of file control.c.

1624{
1625 struct ast_datastore *datastore;
1626 struct timeval *hangup_time;
1627
1628 hangup_time = ast_malloc(sizeof(struct timeval));
1629
1631 if (!datastore) {
1632 return -1;
1633 }
1634 *hangup_time = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1));
1635 datastore->data = hangup_time;
1636
1637 ast_channel_lock(chan);
1638 ast_channel_datastore_add(chan, datastore);
1639
1640 if (ast_channel_is_bridged(chan)) {
1641 set_interval_hook(chan);
1642 }
1643 ast_channel_unlock(chan);
1644
1645 return 0;
1646}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282

References ast_channel_datastore_add(), ast_channel_is_bridged(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_malloc, ast_samp2tv(), ast_tvadd(), ast_tvnow(), ast_datastore::data, NULL, set_interval_hook(), and timeout_datastore.

Referenced by app_control_dial().

◆ stasis_app_control_absorb_dtmf_in_bridge()

void stasis_app_control_absorb_dtmf_in_bridge ( struct stasis_app_control control,
int  absorb 
)

Set whether DTMF from the channel is absorbed instead of passing through to the bridge.

Parameters
controlControl whose channel should have its DTMF absorbed when bridged
absorbWhether DTMF should be absorbed (1) instead of passed through (0).

Definition at line 1484 of file control.c.

1486{
1487 control->bridge_features->dtmf_passthrough = !absorb;
1488}
unsigned int dtmf_passthrough

References stasis_app_control::bridge_features, and ast_bridge_features::dtmf_passthrough.

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_add_channel_to_bridge()

int stasis_app_control_add_channel_to_bridge ( struct stasis_app_control control,
struct ast_bridge bridge 
)

Add a channel to the bridge.

Parameters
controlControl whose channel should be added to the bridge
bridgePointer to the bridge
Returns
non-zero on failure
zero on success

Definition at line 1403 of file control.c.

1405{
1406 ast_debug(3, "%s: Sending channel add_to_bridge command\n",
1408
1410 control, control_add_channel_to_bridge, bridge, NULL,
1412}
int control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Command callback for adding a channel to a bridge.
Definition: control.c:1398
static int app_send_command_on_condition(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
Definition: control.c:886
static int app_control_can_add_channel_to_bridge(struct stasis_app_control *control)
Definition: control.c:258

References app_control_can_add_channel_to_bridge(), app_send_command_on_condition(), ast_debug, control_add_channel_to_bridge(), NULL, and stasis_app_control_get_channel_id().

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_add_role()

int stasis_app_control_add_role ( struct stasis_app_control control,
const char *  role 
)

Apply a bridge role to a channel controlled by a stasis app control.

Parameters
controlControl for res_stasis
roleRole to apply
Returns
0 for success
-1 for error.

Definition at line 336 of file control.c.

337{
338 char *role_dup;
339
340 role_dup = ast_strdup(role);
341 if (!role_dup) {
342 return -1;
343 }
344
346
347 return 0;
348}
static int app_control_add_role(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:328

References app_control_add_role(), ast_free_ptr(), ast_strdup, and stasis_app_send_command_async().

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_bridge_features_init()

int stasis_app_control_bridge_features_init ( struct stasis_app_control control)

Initialize bridge features into a channel control.

Note
Bridge features on a control are destroyed after each bridge session, so new features need to be initialized before each bridge add.
Parameters
controlControl in which to store the features
Returns
non-zero on failure
zero on success

Definition at line 1471 of file control.c.

1473{
1474 struct ast_bridge_features *features;
1475
1476 features = ast_bridge_features_new();
1477 if (!features) {
1478 return 1;
1479 }
1480 control->bridge_features = features;
1481 return 0;
1482}
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3683

References ast_bridge_features_new(), and stasis_app_control::bridge_features.

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_clear_roles()

void stasis_app_control_clear_roles ( struct stasis_app_control control)

Clear bridge roles currently applied to a channel controlled by a stasis app control.

Parameters
controlControl for res_stasis

Definition at line 358 of file control.c.

359{
361}
static int app_control_clear_roles(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:350

References app_control_clear_roles(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_continue()

int stasis_app_control_continue ( struct stasis_app_control control,
const char *  context,
const char *  extension,
int  priority 
)

Exit res_stasis and continue execution in the dialplan.

If the channel is no longer in res_stasis, this function does nothing.

Parameters
controlControl for res_stasis
contextAn optional context to continue to
extensionAn optional extension to continue to
priorityAn optional priority to continue to
Returns
0 for success
-1 for error.

Definition at line 409 of file control.c.

410{
411 struct stasis_app_control_continue_data *continue_data;
412
413 if (!(continue_data = ast_calloc(1, sizeof(*continue_data)))) {
414 return -1;
415 }
416 ast_copy_string(continue_data->context, S_OR(context, ""), sizeof(continue_data->context));
417 ast_copy_string(continue_data->extension, S_OR(extension, ""), sizeof(continue_data->extension));
418 if (priority > 0) {
419 continue_data->priority = priority;
420 } else {
421 continue_data->priority = -1;
422 }
423
425
426 return 0;
427}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static int priority
static int app_control_continue(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:388
#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
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
structure to hold extensions

References app_control_continue(), ast_calloc, ast_copy_string(), ast_free_ptr(), voicemailpwcheck::context, stasis_app_control_continue_data::context, stasis_app_control_continue_data::extension, priority, stasis_app_control_continue_data::priority, S_OR, and stasis_app_send_command_async().

Referenced by ast_ari_channels_continue_in_dialplan().

◆ stasis_app_control_dial()

int stasis_app_control_dial ( struct stasis_app_control control,
const char *  dialstring,
unsigned int  timeout 
)

Dial a channel.

Parameters
controlControl for res_stasis.
dialstringThe dialstring to pass to the channel driver
timeoutOptional timeout in milliseconds

Definition at line 1686 of file control.c.

1688{
1689 struct control_dial_args *args;
1690
1692 if (!args) {
1693 return -1;
1694 }
1695
1698}
static struct control_dial_args * control_dial_args_alloc(const char *dialstring, unsigned int timeout)
Definition: control.c:1593
static void control_dial_args_destroy(void *data)
Definition: control.c:1610
static int app_control_dial(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1648

References app_control_dial(), args, control_dial_args_alloc(), control_dial_args_destroy(), control_dial_args::dialstring, stasis_app_send_command_async(), and control_dial_args::timeout.

Referenced by ast_ari_channels_dial().

◆ stasis_app_control_dtmf()

int stasis_app_control_dtmf ( struct stasis_app_control control,
const char *  dtmf,
int  before,
int  between,
unsigned int  duration,
int  after 
)

Send DTMF to the channel associated with this control.

Parameters
controlControl for res_stasis.
dtmfDTMF string.
beforeAmount of time to wait before sending DTMF digits.
betweenAmount of time between each DTMF digit.
durationAmount of time each DTMF digit lasts for.
afterAmount of time to wait after sending DTMF digits.
Returns
0 for success.
-1 for error.

Definition at line 585 of file control.c.

586{
587 struct stasis_app_control_dtmf_data *dtmf_data;
588
589 if (!(dtmf_data = ast_calloc(1, sizeof(*dtmf_data) + strlen(dtmf) + 1))) {
590 return -1;
591 }
592
593 dtmf_data->before = before;
594 dtmf_data->between = between;
595 dtmf_data->duration = duration;
596 dtmf_data->after = after;
597 strcpy(dtmf_data->dtmf, dtmf);
598
600
601 return 0;
602}
static int app_control_dtmf(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:567

References stasis_app_control_dtmf_data::after, app_control_dtmf(), ast_calloc, ast_free_ptr(), stasis_app_control_dtmf_data::before, stasis_app_control_dtmf_data::between, stasis_app_control_dtmf_data::dtmf, stasis_app_control_dtmf_data::duration, and stasis_app_send_command_async().

Referenced by ast_ari_channels_send_dtmf().

◆ stasis_app_control_get_channel_id()

const char * stasis_app_control_get_channel_id ( const struct stasis_app_control control)

◆ stasis_app_control_get_snapshot()

struct ast_channel_snapshot * stasis_app_control_get_snapshot ( const struct stasis_app_control control)

Returns the most recent snapshot for the associated channel.

The returned pointer is AO2 managed, so ao2_cleanup() when you're done.

Parameters
controlControl for res_stasis.
Returns
Most recent snapshot. ao2_cleanup() when done.
Return values
NULLif channel isn't in cache.

Definition at line 880 of file control.c.

882{
884}
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,...

References ast_channel_snapshot_get_latest(), and stasis_app_control_get_channel_id().

Referenced by ari_bridges_play_helper(), ari_channels_handle_play(), ast_ari_channels_continue_in_dialplan(), and channel_state_invalid().

◆ stasis_app_control_hold()

void stasis_app_control_hold ( struct stasis_app_control control)

Place the channel associated with the control on hold.

Parameters
controlControl for res_stasis.

Definition at line 768 of file control.c.

769{
771}
static int app_control_hold(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:760

References app_control_hold(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_hold().

◆ stasis_app_control_inhibit_colp_in_bridge()

void stasis_app_control_inhibit_colp_in_bridge ( struct stasis_app_control control,
int  inhibit_colp 
)

Set whether COLP frames should be generated when joining the bridge.

Since
18
Parameters
controlControl whose channel should have its COLP frames inhibited when bridged
inhibit_colpWhether COLP frames should be generated (0) or not (1).

Definition at line 1496 of file control.c.

1498{
1499 control->bridge_features->inhibit_colp = inhibit_colp;
1500}

References stasis_app_control::bridge_features, and ast_bridge_features::inhibit_colp.

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_moh_start()

void stasis_app_control_moh_start ( struct stasis_app_control control,
const char *  moh_class 
)

Play music on hold to a channel (does not affect hold status)

Parameters
controlControl for res_stasis.
moh_classclass of music on hold to play (NULL allowed)

Definition at line 800 of file control.c.

801{
802 char *data = NULL;
803
804 if (!ast_strlen_zero(moh_class)) {
805 data = ast_strdup(moh_class);
806 }
807
809}
static int app_control_moh_start(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:786
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References app_control_moh_start(), ast_free_ptr(), ast_strdup, ast_strlen_zero(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_start_moh().

◆ stasis_app_control_moh_stop()

void stasis_app_control_moh_stop ( struct stasis_app_control control)

Stop playing music on hold to a channel (does not affect hold status)

Parameters
controlControl for res_stasis.

Definition at line 818 of file control.c.

819{
821}
static int app_control_moh_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:811

References app_control_moh_stop(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_stop_moh().

◆ stasis_app_control_move()

int stasis_app_control_move ( struct stasis_app_control control,
const char *  app_name,
const char *  app_args 
)

Exit res_stasis and move to another Stasis application.

If the channel is no longer in res_stasis, this function does nothing.

Parameters
controlControl for res_stasis
app_nameThe name of the application to switch to
app_argsThe list of arguments to pass to the application
Returns
0 for success
-1 for error

Definition at line 471 of file control.c.

472{
473 struct stasis_app_control_move_data *move_data;
474 size_t size;
475
476 size = sizeof(*move_data) + strlen(app_name) + 1;
477 if (app_args) {
478 /* Application arguments are optional */
479 size += strlen(app_args) + 1;
480 }
481
482 if (!(move_data = ast_calloc(1, size))) {
483 return -1;
484 }
485
486 move_data->app_name = (char *)move_data + sizeof(*move_data);
487 strcpy(move_data->app_name, app_name); /* Safe */
488
489 if (app_args) {
490 move_data->app_args = move_data->app_name + strlen(app_name) + 1;
491 strcpy(move_data->app_args, app_args); /* Safe */
492 } else {
493 move_data->app_args = NULL;
494 }
495
497
498 return 0;
499}
static int app_control_move(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:434
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463

References stasis_app_control_move_data::app_args, app_control_move(), app_name(), stasis_app_control_move_data::app_name, ast_calloc, ast_free_ptr(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_move().

◆ stasis_app_control_mute()

int stasis_app_control_mute ( struct stasis_app_control control,
unsigned int  direction,
enum ast_frame_type  frametype 
)

Mute the channel associated with this control.

Parameters
controlControl for res_stasis.
directionThe direction in which the audio should be muted.
frametypeThe type of stream that should be muted.
Returns
0 for success
-1 for error.

Definition at line 651 of file control.c.

652{
653 struct stasis_app_control_mute_data *mute_data;
654
655 if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
656 return -1;
657 }
658
659 mute_data->direction = direction;
660 mute_data->frametype = frametype;
661
663
664 return 0;
665}
static int app_control_mute(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:639
direction

References app_control_mute(), ast_calloc, ast_free_ptr(), stasis_app_control_mute_data::direction, stasis_app_control_mute_data::frametype, and stasis_app_send_command_async().

Referenced by ast_ari_channels_mute().

◆ stasis_app_control_mute_in_bridge()

void stasis_app_control_mute_in_bridge ( struct stasis_app_control control,
int  mute 
)

Set whether audio from the channel is muted instead of passing through to the bridge.

Parameters
controlControl whose channel should have its audio muted when bridged
muteWhether audio should be muted (1) instead of passed through (0).

Definition at line 1490 of file control.c.

1492{
1493 control->bridge_features->mute = mute;
1494}

References stasis_app_control::bridge_features, and ast_bridge_features::mute.

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_publish()

void stasis_app_control_publish ( struct stasis_app_control control,
struct stasis_message message 
)

Publish a message to the control's channel's topic.

Parameters
controlControl to publish to
messageMessage to publish

Definition at line 1456 of file control.c.

1458{
1459 if (!control || !control->channel || !message) {
1460 return;
1461 }
1463}
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511

References ast_channel_topic(), stasis_app_control::channel, and stasis_publish().

Referenced by playback_publish(), and recording_publish().

◆ stasis_app_control_queue_control()

int stasis_app_control_queue_control ( struct stasis_app_control control,
enum ast_control_frame_type  frame_type 
)

Queue a control frame without payload.

Parameters
controlControl to publish to.
frame_typetype of control frame.
Returns
zero on success
non-zero on failure

Definition at line 1465 of file control.c.

1467{
1468 return ast_queue_control(control->channel, frame_type);
1469}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
frame_type
Definition: codec_builtin.c:44

References ast_queue_control(), and stasis_app_control::channel.

Referenced by playback_forward(), playback_pause(), playback_restart(), playback_reverse(), playback_stop(), playback_unpause(), recording_cancel(), recording_pause(), recording_stop(), recording_unpause(), and toggle_recording_mute().

◆ stasis_app_control_redirect()

int stasis_app_control_redirect ( struct stasis_app_control control,
const char *  endpoint 
)

Redirect a channel in res_stasis to a particular endpoint.

Parameters
controlControl for res_stasis
endpointThe endpoint transfer string where the channel should be sent to
Returns
0 for success
-1 for error

Definition at line 520 of file control.c.

521{
522 char *endpoint_data = ast_strdup(endpoint);
523
524 if (!endpoint_data) {
525 return -1;
526 }
527
529
530 return 0;
531}
static int app_control_redirect(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:501

References app_control_redirect(), ast_free_ptr(), ast_strdup, and stasis_app_send_command_async().

Referenced by ast_ari_channels_redirect().

◆ stasis_app_control_register_add_rule()

void stasis_app_control_register_add_rule ( struct stasis_app_control control,
struct stasis_app_control_rule rule 
)

Registers an add channel to bridge rule.

Parameters
controlControl object
ruleThe rule to register

Definition at line 230 of file control.c.

233{
234 return app_control_register_rule(control, &control->add_rules, rule);
235}
static void app_control_register_rule(struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj)
Definition: control.c:168

References stasis_app_control::add_rules, and app_control_register_rule().

Referenced by stasis_app_control_record().

◆ stasis_app_control_register_remove_rule()

void stasis_app_control_register_remove_rule ( struct stasis_app_control control,
struct stasis_app_control_rule rule 
)

Registers a remove channel from bridge rule.

Parameters
controlControl object
ruleThe rule to register

Definition at line 244 of file control.c.

247{
248 return app_control_register_rule(control, &control->remove_rules, rule);
249}

References app_control_register_rule(), and stasis_app_control::remove_rules.

◆ stasis_app_control_remove_channel_from_bridge()

int stasis_app_control_remove_channel_from_bridge ( struct stasis_app_control control,
struct ast_bridge bridge 
)

Remove a channel from the bridge.

Parameters
controlControl whose channel should be removed from the bridge
bridgePointer to the bridge
Returns
non-zero on failure
zero on success

Definition at line 1440 of file control.c.

1442{
1443 ast_debug(3, "%s: Sending channel remove_from_bridge command\n",
1448}
static int app_control_remove_channel_from_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:1414
static int app_control_can_remove_channel_from_bridge(struct stasis_app_control *control)
Definition: control.c:264

References app_control_can_remove_channel_from_bridge(), app_control_remove_channel_from_bridge(), app_send_command_on_condition(), ast_debug, NULL, and stasis_app_control_get_channel_id().

Referenced by ast_ari_bridges_remove_channel().

◆ stasis_app_control_ring()

int stasis_app_control_ring ( struct stasis_app_control control)

Indicate ringing to the channel associated with this control.

Parameters
controlControl for res_stasis.
Returns
0 for success.
-1 for error.

Definition at line 612 of file control.c.

613{
615
616 return 0;
617}
static int app_control_ring(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:604

References app_control_ring(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_ring().

◆ stasis_app_control_ring_stop()

int stasis_app_control_ring_stop ( struct stasis_app_control control)

Stop locally generated ringing on the channel associated with this control.

Parameters
controlControl for res_stasis.
Returns
0 for success.
-1 for error.

Definition at line 627 of file control.c.

628{
630
631 return 0;
632}
static int app_control_ring_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:619

References app_control_ring_stop(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_ring_stop().

◆ stasis_app_control_set_channel_var()

int stasis_app_control_set_channel_var ( struct stasis_app_control control,
const char *  variable,
const char *  value 
)

Set a variable on the channel associated with this control to value.

Parameters
controlControl for res_stasis.
variableThe name of the variable
valueThe value to set the variable to
Returns
0 for success.
-1 for error.

Definition at line 731 of file control.c.

732{
733 struct chanvar *var;
734
735 var = ast_calloc(1, sizeof(*var));
736 if (!var) {
737 return -1;
738 }
739
740 var->name = ast_strdup(variable);
741 if (!var->name) {
743 return -1;
744 }
745
746 /* It's kosher for value to be NULL. It means the variable is being unset */
747 if (value) {
748 var->value = ast_strdup(value);
749 if (!var->value) {
751 return -1;
752 }
753 }
754
756
757 return 0;
758}
static int app_control_set_channel_var(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:721
static void free_chanvar(void *data)
Definition: control.c:712
int value
Definition: syslog.c:37

References app_control_set_channel_var(), ast_calloc, ast_strdup, free_chanvar(), stasis_app_send_command_async(), value, and var.

Referenced by ast_ari_channels_set_channel_var().

◆ stasis_app_control_shutdown()

void stasis_app_control_shutdown ( void  )

Let Stasis app internals shut down.

This is called when res_stasis is unloaded. It ensures that the Stasis app internals can free any resources they may have allocated during the time that res_stasis was loaded.

Definition at line 1700 of file control.c.

1701{
1703 shutting_down = 1;
1704 if (dial_bridge) {
1706 dial_bridge = NULL;
1707 }
1709}
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944

References ast_bridge_destroy(), ast_mutex_lock, ast_mutex_unlock, dial_bridge, dial_bridge_lock, NULL, and shutting_down.

Referenced by unload_module().

◆ stasis_app_control_silence_start()

void stasis_app_control_silence_start ( struct stasis_app_control control)

Start playing silence to a channel.

Parameters
controlControl for res_stasis.

Definition at line 852 of file control.c.

853{
855}
static int app_control_silence_start(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:823

References app_control_silence_start(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_start_silence().

◆ stasis_app_control_silence_stop()

void stasis_app_control_silence_stop ( struct stasis_app_control control)

Stop playing silence to a channel.

Parameters
controlControl for res_stasis.

Definition at line 875 of file control.c.

876{
878}
static int app_control_silence_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:868

References app_control_silence_stop(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_stop_silence().

◆ stasis_app_control_unhold()

void stasis_app_control_unhold ( struct stasis_app_control control)

Remove the channel associated with the control from hold.

Parameters
controlControl for res_stasis.

Definition at line 781 of file control.c.

782{
784}
static int app_control_unhold(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:773

References app_control_unhold(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_unhold().

◆ stasis_app_control_unmute()

int stasis_app_control_unmute ( struct stasis_app_control control,
unsigned int  direction,
enum ast_frame_type  frametype 
)

Unmute the channel associated with this control.

Parameters
controlControl for res_stasis.
directionThe direction in which the audio should be unmuted.
frametypeThe type of stream that should be unmuted.
Returns
0 for success
-1 for error.

Definition at line 679 of file control.c.

680{
681 struct stasis_app_control_mute_data *mute_data;
682
683 if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
684 return -1;
685 }
686
687 mute_data->direction = direction;
688 mute_data->frametype = frametype;
689
691
692 return 0;
693}
static int app_control_unmute(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition: control.c:667

References app_control_unmute(), ast_calloc, ast_free_ptr(), stasis_app_control_mute_data::direction, stasis_app_control_mute_data::frametype, and stasis_app_send_command_async().

Referenced by ast_ari_channels_unmute().

◆ stasis_app_control_unregister_add_rule()

void stasis_app_control_unregister_add_rule ( struct stasis_app_control control,
struct stasis_app_control_rule rule 
)

UnRegister an add channel to bridge rule.

Parameters
controlControl object
ruleThe rule to unregister

Definition at line 237 of file control.c.

240{
241 app_control_unregister_rule(control, &control->add_rules, rule);
242}
static void app_control_unregister_rule(struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj)
Definition: control.c:177

References stasis_app_control::add_rules, and app_control_unregister_rule().

Referenced by record_file(), and recording_fail().

◆ stasis_app_control_unregister_remove_rule()

void stasis_app_control_unregister_remove_rule ( struct stasis_app_control control,
struct stasis_app_control_rule rule 
)

Unregisters a remove channel from bridge rule.

Parameters
controlControl object
ruleThe rule to unregister

Definition at line 251 of file control.c.

254{
255 app_control_unregister_rule(control, &control->remove_rules, rule);
256}

References app_control_unregister_rule(), and stasis_app_control::remove_rules.

◆ stasis_app_get_bridge()

struct ast_bridge * stasis_app_get_bridge ( struct stasis_app_control control)

Gets the bridge currently associated with a control object.

Since
12
Note
If the bridge returned by this function is to be held for any length of time, its refcount should be incremented until the caller is finished with it.
Parameters
controlControl object for the channel to query.
Returns
Associated ast_bridge.
Return values
NULLif not associated with a bridge.

Definition at line 951 of file control.c.

952{
953 struct ast_bridge *ret;
954
955 if (!control) {
956 return NULL;
957 }
958
959 ao2_lock(control);
960 ret = control->bridge;
961 ao2_unlock(control);
962
963 return ret;
964}

References ao2_lock, ao2_unlock, stasis_app_control::bridge, and NULL.

Referenced by app_control_continue(), app_control_dtmf(), app_control_remove_channel_from_bridge(), ast_ari_bridges_remove_channel(), ast_ari_bridges_set_video_source(), control_swap_channel_in_bridge(), play_uri(), record_file(), and stasis_app_exec().

◆ stasis_app_send_command()

int stasis_app_send_command ( struct stasis_app_control control,
stasis_app_command_cb  command,
void *  data,
command_data_destructor_fn  data_destructor 
)

Invokes a command on a control's channel.

Since
12

This function dispatches the command to be executed in the context of stasis_app_exec(), so this command will block waiting for the results of the command.

Parameters
controlControl object for the channel to send the command to.
commandCommand function to execute.
dataOptional data to pass along with the control function.
data_destructorOptional function which will be called on the data in either the event of command completion or failure to schedule or complete the command
Returns
zero on success.
error code otherwise.

Definition at line 918 of file control.c.

920{
921 return app_send_command_on_condition(control, command_fn, data, data_destructor, NULL);
922}

References app_send_command_on_condition(), stasis_app_command::data, stasis_app_command::data_destructor, and NULL.

Referenced by ast_ari_bridges_set_video_source(), and stasis_app_control_answer().

◆ stasis_app_send_command_async()

int stasis_app_send_command_async ( struct stasis_app_control control,
stasis_app_command_cb  command,
void *  data,
command_data_destructor_fn  data_destructor 
)

Asynchronous version of stasis_app_send_command().

Since
12

This function enqueues a command for execution, but returns immediately without waiting for the response.

Parameters
controlControl object for the channel to send the command to.
commandCommand function to execute.
dataOptional data to pass along with the control function.
data_destructorOptional function which will be called on the data in either the event of command completion or failure to schedule or complete the command
Returns
0 on success.
Non-zero on error.

Definition at line 924 of file control.c.

927{
928 struct stasis_app_command *command;
929
930 if (control == NULL || control->is_done) {
931 /* If exec_command fails, it calls the data_destructor. In order to
932 * provide consistent behavior, we'll also call the data_destructor
933 * on this error path. This way, callers never have to call the
934 * data_destructor themselves.
935 */
936 if (data_destructor) {
938 }
939 return -1;
940 }
941
942 command = exec_command(control, command_fn, data, data_destructor);
943 if (!command) {
944 return -1;
945 }
946 ao2_ref(command, -1);
947
948 return 0;
949}
static struct stasis_app_command * exec_command(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
Definition: control.c:321

References ao2_ref, stasis_app_command::data, stasis_app_command::data_destructor, exec_command(), stasis_app_control::is_done, and NULL.

Referenced by bridge_timeout(), dial_bridge_after_cb(), internal_bridge_after_cb(), stasis_app_control_add_role(), stasis_app_control_clear_roles(), stasis_app_control_continue(), stasis_app_control_dial(), stasis_app_control_dtmf(), stasis_app_control_hold(), stasis_app_control_moh_start(), stasis_app_control_moh_stop(), stasis_app_control_move(), stasis_app_control_mute(), stasis_app_control_play_uri(), stasis_app_control_record(), stasis_app_control_redirect(), stasis_app_control_ring(), stasis_app_control_ring_stop(), stasis_app_control_set_channel_var(), stasis_app_control_silence_start(), stasis_app_control_silence_stop(), stasis_app_control_unhold(), and stasis_app_control_unmute().

Variable Documentation

◆ dial_bridge

struct ast_bridge* dial_bridge
static

Singleton dial bridge.

The dial bridge is a holding bridge used to hold all outbound dialed channels that are not in any "real" ARI-created bridge. The dial bridge is invisible, meaning that it does not show up in channel snapshots, AMI or ARI output, and no events get raised for it.

This is used to keep dialed channels confined to the bridging system and unify the threading model used for dialing outbound channels.

Definition at line 978 of file control.c.

Referenced by get_dial_bridge(), and stasis_app_control_shutdown().

◆ dial_bridge_lock

ast_mutex_t dial_bridge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 979 of file control.c.

Referenced by get_dial_bridge(), and stasis_app_control_shutdown().

◆ shutting_down

int shutting_down
static

Indicates if the Stasis app internals are being shut down.

Definition at line 49 of file control.c.

Referenced by get_dial_bridge(), and stasis_app_control_shutdown().

◆ timeout_datastore

struct ast_datastore_info timeout_datastore
Initial value:
= {
.type = "ARI dial timeout",
}

Dial timeout datastore.

A datastore is used because a channel may change bridges during the course of a dial attempt. This may be because the channel changes from the dial bridge to a standard bridge, or it may move between standard bridges. In order to keep the dial timeout, we need to keep the timeout information local to the channel. That is what this datastore is for

Definition at line 1212 of file control.c.

Referenced by bridge_timeout(), set_interval_hook(), and set_timeout().