Asterisk - The Open Source Telephony Project GIT-master-5467495
Loading...
Searching...
No Matches
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 "asterisk/causes.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 <signal.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.
 
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_progress (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.
 
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.
 
struct stasis_appcontrol_app (struct stasis_app_control *control)
 Returns the pointer (non-reffed) to the app associated with this control.
 
int control_command_count (struct stasis_app_control *control)
 Returns the count of items in a control's command queue.
 
struct stasis_app_controlcontrol_create (struct ast_channel *channel, struct stasis_app *app)
 Create a control object.
 
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.
 
static void control_dtor (void *obj)
 
void control_flush_queue (struct stasis_app_control *control)
 Flush the control command queue.
 
int control_is_done (struct stasis_app_control *control)
 Returns true if control_continue() has been called on this control.
 
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.
 
char * control_next_app (struct stasis_app_control *control)
 Returns the name of the application we are moving to.
 
char ** control_next_app_args (struct stasis_app_control *control)
 Returns the list of arguments to pass to the application we are moving to.
 
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.
 
int control_prestart_dispatch_all (struct stasis_app_control *control, struct ast_channel *chan)
 Dispatch all queued prestart commands.
 
void control_set_app (struct stasis_app_control *control, struct stasis_app *app)
 Set the application the control object belongs to.
 
void control_silence_stop_now (struct stasis_app_control *control)
 Stop playing silence to a channel right now.
 
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.
 
void control_wait (struct stasis_app_control *control)
 Blocks until control's command queue has a command available.
 
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.
 
static void dial_bridge_after_cb (struct ast_channel *chan, void *data)
 after bridge callback for the dial bridge
 
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.
 
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.
 
static int set_timeout (struct ast_channel *chan, unsigned int timeout)
 Set dial timeout on a channel to be dialed.
 
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.
 
int stasis_app_control_add_channel_to_bridge (struct stasis_app_control *control, struct ast_bridge *bridge)
 Add a channel to the bridge.
 
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.
 
int stasis_app_control_bridge_features_init (struct stasis_app_control *control)
 Initialize bridge features into a channel control.
 
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.
 
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.
 
int stasis_app_control_dial (struct stasis_app_control *control, const char *dialstring, unsigned int timeout)
 Dial a channel.
 
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.
 
const char * stasis_app_control_get_channel_id (const struct stasis_app_control *control)
 Returns the uniqueid of the channel associated with this control.
 
struct ast_channel_snapshotstasis_app_control_get_snapshot (const struct stasis_app_control *control)
 Returns the most recent snapshot for the associated channel.
 
void stasis_app_control_hold (struct stasis_app_control *control)
 Place the channel associated with the control on hold.
 
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.
 
int stasis_app_control_is_failed (const struct stasis_app_control *control)
 Check if a control object is marked as "failed".
 
void stasis_app_control_mark_failed (struct stasis_app_control *control)
 Set the failed flag on a control structure.
 
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)
 
void stasis_app_control_moh_stop (struct stasis_app_control *control)
 Stop playing music on hold to a channel (does not affect hold status)
 
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.
 
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.
 
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.
 
int stasis_app_control_progress (struct stasis_app_control *control)
 Indicate progress to the channel associated with this control.
 
void stasis_app_control_publish (struct stasis_app_control *control, struct stasis_message *message)
 Publish a message to the control's channel's topic.
 
int stasis_app_control_queue_control (struct stasis_app_control *control, enum ast_control_frame_type frame_type)
 Queue a control frame without payload.
 
int stasis_app_control_redirect (struct stasis_app_control *control, const char *endpoint)
 Redirect a channel in res_stasis to a particular endpoint.
 
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.
 
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.
 
int stasis_app_control_remove_channel_from_bridge (struct stasis_app_control *control, struct ast_bridge *bridge)
 Remove a channel from the bridge.
 
int stasis_app_control_ring (struct stasis_app_control *control)
 Indicate ringing to the channel associated with this control.
 
int stasis_app_control_ring_stop (struct stasis_app_control *control)
 Stop locally generated ringing on the channel associated with this control.
 
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.
 
int stasis_app_control_set_channel_var_reportable (struct stasis_app_control *control, const char *variable, const char *value, int report_events)
 Set a variable on the channel associated with this control to value with option of including in events.
 
void stasis_app_control_shutdown (void)
 Let Stasis app internals shut down.
 
void stasis_app_control_silence_start (struct stasis_app_control *control)
 Start playing silence to a channel.
 
void stasis_app_control_silence_stop (struct stasis_app_control *control)
 Stop playing silence to a channel.
 
void stasis_app_control_unhold (struct stasis_app_control *control)
 Remove the channel associated with the control from hold.
 
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.
 
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.
 
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.
 
struct ast_bridgestasis_app_get_bridge (struct stasis_app_control *control)
 Gets the bridge currently associated with a control object.
 
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.
 
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().
 
static void timeout_datastore_data_destructor (void *data)
 Dial timeout datastore.
 

Variables

static struct ast_bridgedial_bridge
 Singleton dial bridge.
 
static ast_mutex_t dial_bridge_lock = AST_MUTEX_INIT_VALUE
 
static int shutting_down
 Indicates if the Stasis app internals are being shut down.
 
struct ast_datastore_info timeout_datastore
 

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 273 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 1103 of file control.c.

1104{
1105 struct ast_bridge *bridge;
1106
1107 bridge = get_dial_bridge();
1108 if (!bridge) {
1109 return -1;
1110 }
1111
1112 control->bridge = bridge;
1115 control->bridge = NULL;
1116 ao2_ref(bridge, -1);
1117 return -1;
1118 }
1119
1120 ao2_ref(bridge, -1);
1121
1122 return 0;
1123}
#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:2077
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
Definition bridge.h:598
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
Setup an after bridge callback for when the channel leaves the bridging system.
static void dial_bridge_after_cb(struct ast_channel *chan, void *data)
after bridge callback for the dial bridge
Definition control.c:1071
static struct ast_bridge * get_dial_bridge(void)
Retrieve a reference to the dial bridge.
Definition control.c:1036
static void dial_bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition control.c:1087
#define NULL
Definition resample.c:96
Structure that contains information about a bridge.
Definition bridge.h:355
struct ast_bridge * bridge
Definition control.c:67

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

325{
326 char *role = data;
327
328 return ast_channel_add_bridge_role(chan, role);
329}
int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.

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

255{
256 return app_control_check_rules(control, &control->add_rules);
257}
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:211
struct app_control_rules add_rules
Definition control.c:79

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

261{
262 return app_control_check_rules(control, &control->remove_rules);
263}
struct app_control_rules remove_rules
Definition control.c:83

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

214{
215 int res = 0;
217 AST_LIST_TRAVERSE(list, rule, next) {
218 if ((res = rule->check_rule(control))) {
219 return res;
220 }
221 }
222 return res;
223}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Rule to check to see if an operation is allowed.
Definition stasis_app.h:355
struct stasis_app_control_rule * next
Definition stasis_app.h:365

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

347{
349
350 return 0;
351}
void ast_channel_clear_bridge_roles(struct ast_channel *chan)
Removes all bridge roles currently on a channel.

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

396{
397 struct stasis_app_control_continue_data *continue_data = data;
398
399 ast_assert(control->channel != NULL);
400
401 /* If we're in a Stasis bridge, depart it before going back to the
402 * dialplan */
403 if (stasis_app_get_bridge(control)) {
404 ast_bridge_depart(control->channel);
405 }
406
407 /* Called from stasis_app_exec thread; no lock needed */
408 ast_explicit_goto(control->channel, continue_data->context, continue_data->extension, continue_data->priority);
409
410 control_mark_done(control);
411
412 return 0;
413}
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition bridge.c:2105
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition control.c:993
void control_mark_done(struct stasis_app_control *control)
Definition control.c:369
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition pbx.c:5223
char extension[AST_MAX_EXTENSION]
Definition control.c:390
char context[AST_MAX_CONTEXT]
Definition control.c:389
struct ast_channel * channel
Definition control.c:63
#define ast_assert(a)
Definition utils.h:779

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

1703{
1704 struct control_dial_args *args = data;
1705 int bridged;
1706
1707 ast_channel_lock(chan);
1708 bridged = ast_channel_is_bridged(chan);
1709 ast_channel_unlock(chan);
1710
1711 if (!bridged && add_to_dial_bridge(control, chan)) {
1712 return -1;
1713 }
1714
1715 if (args->timeout && set_timeout(chan, args->timeout)) {
1716 return -1;
1717 }
1718
1719 if (ast_call(chan, args->dialstring, 0)) {
1720 /* If call fails normally this channel would then just be normally hung up and destroyed.
1721 * In this case though the channel is being handled by the ARI control thread and dial
1722 * bridge which needs to be notified that the channel should be hung up. To do this we
1723 * queue a soft hangup which will cause each to wake up, see that the channel has been
1724 * hung up, and then destroy it.
1725 */
1726 int hangup_flag;
1728 ast_channel_lock(chan);
1729 ast_softhangup_nolock(chan, hangup_flag);
1730 ast_channel_unlock(chan);
1731 return -1;
1732 }
1733
1734 ast_channel_publish_dial(NULL, chan, args->dialstring, NULL);
1735
1736 return 0;
1737}
int ast_bridge_setup_after_goto(struct ast_channel *chan)
Setup any after bridge goto location to begin execution.
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition channel.c:6480
#define ast_channel_lock(chan)
Definition channel.h:2983
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition channel.c:10725
@ AST_SOFTHANGUP_ASYNCGOTO
Definition channel.h:1146
@ AST_SOFTHANGUP_DEV
Definition channel.h:1141
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition channel.c:2449
#define ast_channel_unlock(chan)
Definition channel.h:2984
static int set_timeout(struct ast_channel *chan, unsigned int timeout)
Set dial timeout on a channel to be dialed.
Definition control.c:1676
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:1103
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...
static struct @522 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 573 of file control.c.

575{
576 struct stasis_app_control_dtmf_data *dtmf_data = data;
577
578 if (ast_channel_state(chan) != AST_STATE_UP) {
580 }
581
582 if (stasis_app_get_bridge(control)) {
583 dtmf_in_bridge(chan, dtmf_data);
584 } else {
585 dtmf_no_bridge(chan, dtmf_data);
586 }
587
588 return 0;
589}
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition channel.c:4298
ast_channel_state
ast_channel states
@ AST_STATE_UP
static void dtmf_no_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
Definition control.c:560
static void dtmf_in_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)
Definition control.c:547
@ 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 802 of file control.c.

804{
806
807 return 0;
808}

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

830{
831 char *moh_class = data;
832
833 if (ast_channel_state(chan) != AST_STATE_UP) {
835 }
836
837 ast_moh_start(chan, moh_class, NULL);
838
839 return 0;
840}
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:7802

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

855{
856 ast_moh_stop(chan);
857 return 0;
858}
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition channel.c:7812

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

442{
443 struct stasis_app_control_move_data *move_data = data;
444
445 control->next_app = ast_strdup(move_data->app_name);
446 if (!control->next_app) {
447 ast_log(LOG_ERROR, "Allocation failed for next app\n");
448 return -1;
449 }
450
451 if (move_data->app_args) {
452 char *token;
453
454 while ((token = strtok_r(move_data->app_args, ",", &move_data->app_args))) {
455 int res;
456 char *arg;
457
458 if (!(arg = ast_strdup(token))) {
459 ast_log(LOG_ERROR, "Allocation failed for next app arg\n");
460 control_move_cleanup(control);
461 return -1;
462 }
463
464 res = AST_VECTOR_APPEND(&control->next_app_args, arg);
465 if (res) {
466 ast_log(LOG_ERROR, "Failed to append arg to next app args\n");
467 ast_free(arg);
468 control_move_cleanup(control);
469 return -1;
470 }
471 }
472 }
473
474 return 0;
475}
#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:1775
#define LOG_ERROR
struct stasis_app_control::@530 next_app_args
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267

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

662{
663 struct stasis_app_control_mute_data *mute_data = data;
664
665 ast_channel_lock(chan);
666 ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);
667 ast_channel_unlock(chan);
668
669 return 0;
670}
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:10957
enum ast_frame_type frametype
Definition control.c:656

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

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

Definition at line 640 of file control.c.

642{
644
645 return 0;
646}

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

Referenced by stasis_app_control_progress().

◆ app_control_redirect()

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

Definition at line 507 of file control.c.

509{
510 char *endpoint = data;
511 int res;
512
513 ast_assert(control->channel != NULL);
514 ast_assert(endpoint != NULL);
515
516 res = ast_transfer(control->channel, endpoint);
517 if (!res) {
518 ast_log(LOG_NOTICE, "Unsupported transfer requested on channel '%s'\n",
519 ast_channel_name(control->channel));
520 return 0;
521 }
522
523 return 0;
524}
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:6504
#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 170 of file control.c.

173{
174 ao2_lock(control->command_queue);
175 AST_LIST_INSERT_TAIL(list, obj, next);
176 ao2_unlock(control->command_queue);
177}
#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.
struct ao2_container * command_queue
Definition control.c:57

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

1470{
1471 struct ast_bridge *bridge = data;
1472
1473 if (!control) {
1474 return -1;
1475 }
1476
1477 /* We should only depart from our own bridge */
1478 ast_debug(3, "%s: Departing bridge %s\n",
1480 bridge->uniqueid);
1481
1482 if (bridge != stasis_app_get_bridge(control)) {
1483 ast_log(LOG_WARNING, "%s: Not in bridge %s; not removing\n",
1485 bridge->uniqueid);
1486 return -1;
1487 }
1488
1489 depart_channel(control, chan);
1490 return 0;
1491}
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:1503
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:1131
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
const ast_string_field uniqueid
Definition bridge.h:407

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

612{
614
615 return 0;
616}
@ 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 625 of file control.c.

627{
628 ast_indicate(control->channel, -1);
629
630 return 0;
631}

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

746{
747 struct chanvar *var = data;
748 /*
749 * Save the current inhibit state then enable it.
750 */
751 int inhibited = ast_thread_inhibit_escalations_swap(1);
752
753 if (ast_channel_set_ari_var_reportable(control->channel, var->name, var->report_events)) {
754 return -1;
755 }
756
757 pbx_builtin_setvar_helper(control->channel, var->name, var->value);
758 /*
759 * Re-enable it if it was originally enabled.
760 */
761 if (inhibited > 0) {
763 }
764
765 return 0;
766}
#define var
Definition ast_expr2f.c:605
int ast_channel_set_ari_var_reportable(struct ast_channel *chan, const char *variable, int report_events)
Set whether a channel variable should be included in REST events on the channel.
Definition channel.c:7906
int ast_thread_inhibit_escalations_swap(int inhibit)
Swap the current thread escalation inhibit setting.
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.
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
structure for queuing ARI channel variable setting
Definition control.c:726

References ast_channel_set_ari_var_reportable(), ast_thread_inhibit_escalations(), ast_thread_inhibit_escalations_swap(), stasis_app_control::channel, pbx_builtin_setvar_helper(), and var.

Referenced by stasis_app_control_set_channel_var_reportable().

◆ 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 865 of file control.c.

867{
868 if (ast_channel_state(chan) != AST_STATE_UP) {
870 }
871
872 if (control->silgen) {
873 /* We have a silence generator, but it may have been implicitly
874 * disabled by media actions (music on hold, playing media,
875 * etc.) Just stop it and restart a new one.
876 */
878 control->channel, control->silgen);
879 }
880
881 ast_debug(3, "%s: Starting silence generator\n",
884
885 if (!control->silgen) {
887 "%s: Failed to start silence generator.\n",
889 }
890
891 return 0;
892}
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition channel.c:8340
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:8386
struct ast_silence_generator * silgen
Definition control.c:87

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

912{
914 return 0;
915}
void control_silence_stop_now(struct stasis_app_control *control)
Stop playing silence to a channel right now.
Definition control.c:899

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

817{
819
820 return 0;
821}
@ 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 688 of file control.c.

690{
691 struct stasis_app_control_mute_data *mute_data = data;
692
693 ast_channel_lock(chan);
694 ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);
695 ast_channel_unlock(chan);
696
697 return 0;
698}
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:11019

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

932{
933 int ret;
934 struct stasis_app_command *command;
935
936 if (control == NULL || control->is_done) {
937 /* If exec_command_on_condition fails, it calls the data_destructor.
938 * In order to provide consistent behavior, we'll also call the data_destructor
939 * on this error path. This way, callers never have to call the
940 * data_destructor themselves.
941 */
942 if (data_destructor) {
944 }
945 return -1;
946 }
947
949 control, command_fn, data, data_destructor, can_exec_fn);
950 if (!command) {
951 return -1;
952 }
953
954 ret = command_join(command);
955 ao2_ref(command, -1);
956
957 return ret;
958}
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:275
command_data_destructor_fn data_destructor
Definition command.c:38
unsigned int is_done
Definition control.c:105

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

1226{
1227 struct stasis_app_control *control = data;
1228
1230}
@ AST_BRIDGE_AFTER_CB_REASON_DEPART
static void internal_bridge_after_cb(struct ast_channel *chan, void *data, enum ast_bridge_after_cb_reason reason)
Definition control.c:1170

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

1234{
1235 struct stasis_app_control *control = data;
1236
1237 internal_bridge_after_cb(control->channel, data, reason);
1238
1239 ast_debug(3, " reason: %s\n",
1241}
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.

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

1149{
1150 struct ast_bridge_channel *bridge_channel;
1151
1153 bridge_channel = ast_channel_internal_bridge_channel(chan);
1155
1156 if (bridge_channel != data) {
1157 ast_debug(3, "%s: Channel is no longer in departable state\n",
1159 return -1;
1160 }
1161
1162 ast_debug(3, "%s: Channel departing bridge\n",
1164
1165 depart_channel(control, chan);
1166
1167 return 0;
1168}
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 1288 of file control.c.

1289{
1290 struct ast_datastore *datastore;
1291 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1292
1293 control = stasis_app_control_find_by_channel(bridge_channel->chan);
1294
1295 ast_channel_lock(bridge_channel->chan);
1296 if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) {
1297 /* Don't bother removing the datastore because it will happen when the channel is hung up */
1298 ast_channel_unlock(bridge_channel->chan);
1300 return -1;
1301 }
1302
1303 datastore = ast_channel_datastore_find(bridge_channel->chan, &timeout_datastore, NULL);
1304 if (!datastore) {
1305 ast_channel_unlock(bridge_channel->chan);
1306 return -1;
1307 }
1308 ast_channel_datastore_remove(bridge_channel->chan, datastore);
1309 ast_channel_unlock(bridge_channel->chan);
1310 ast_datastore_free(datastore);
1311
1312 return -1;
1313}
#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:2385
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition channel.c:2390
struct ast_datastore_info timeout_datastore
Definition control.c:1260
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:966
static int hangup_channel(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:1265
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:981

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

1452{
1453 return control_swap_channel_in_bridge(control, data, chan, NULL);
1454}
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:1357

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

1637{
1638 return control->app;
1639}
struct stasis_app * app
Definition control.c:93

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

359{
360 return ao2_container_count(control->command_queue);
361}
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 131 of file control.c.

132{
133 struct stasis_app_control *control;
134 int res;
135
136 control = ao2_alloc(sizeof(*control), control_dtor);
137 if (!control) {
138 return NULL;
139 }
140
141 AST_LIST_HEAD_INIT(&control->add_rules);
143
144 res = ast_cond_init(&control->wait_cond, NULL);
145 if (res != 0) {
146 ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
147 strerror(errno));
148 ao2_ref(control, -1);
149 return NULL;
150 }
151
152 control->app = ao2_bump(app);
153
155 control->channel = channel;
156
159 if (!control->command_queue) {
160 ao2_ref(control, -1);
161 return NULL;
162 }
163
164 control->next_app = NULL;
165 AST_VECTOR_INIT(&control->next_app_args, 0);
166
167 return control;
168}
static const char app[]
@ 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:3008
static void control_dtor(void *obj)
Definition control.c:113
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ast_cond_init(cond, attr)
Definition lock.h:208
int errno
ast_cond_t wait_cond
Definition control.c:55
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124

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_VECTOR_INIT, stasis_app_control::channel, stasis_app_control::command_queue, control_dtor(), 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 1646 of file control.c.

1648{
1649 struct control_dial_args *args;
1650
1651 args = ast_malloc(sizeof(*args) + strlen(dialstring) + 1);
1652 if (!args) {
1653 return NULL;
1654 }
1655
1656 args->timeout = timeout;
1657 /* Safe */
1658 strcpy(args->dialstring, dialstring);
1659
1660 return args;
1661}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
char dialstring[0]
Definition control.c:1643
unsigned int timeout
Definition control.c:1642

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

1664{
1665 struct control_dial_args *args = data;
1666
1667 ast_free(args);
1668}

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

1570{
1571 int count = 0;
1572 struct ao2_iterator iter;
1573 struct stasis_app_command *command;
1574
1575 ast_assert(control->channel == chan);
1576
1578 while ((command = ao2_iterator_next(&iter))) {
1579 command_invoke(command, control, chan);
1580 ao2_ref(command, -1);
1581 ++count;
1582 }
1583 ao2_iterator_destroy(&iter);
1584
1585 return count;
1586}
#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 113 of file control.c.

114{
115 struct stasis_app_control *control = obj;
116
117 ao2_cleanup(control->command_queue);
118
120 ao2_cleanup(control->app);
121
122 control_move_cleanup(control);
123
124 ast_cond_destroy(&control->wait_cond);
128
129}
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition bridge.c:3883
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition channel.h:3030
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define ast_cond_destroy(cond)
Definition lock.h:209
struct ast_bridge_features * bridge_features
Definition control.c:71

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

1556{
1557 struct ao2_iterator iter;
1558 struct stasis_app_command *command;
1559
1561 while ((command = ao2_iterator_next(&iter))) {
1562 command_complete(command, -1);
1563 ao2_ref(command, -1);
1564 }
1565 ao2_iterator_destroy(&iter);
1566}
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 363 of file control.c.

364{
365 /* Called from stasis_app_exec thread; no lock needed */
366 return control->is_done;
367}

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

370{
371 /* Locking necessary to sync with other threads adding commands to the queue. */
372 ao2_lock(control->command_queue);
373 control->is_done = 1;
374 ao2_unlock(control->command_queue);
375}

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

1776{
1777 ast_free(control->next_app);
1778 control->next_app = NULL;
1779
1781}
void ast_free_ptr(void *ptr)
free() wrapper
Definition astmm.c:1739
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition vector.h:653

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

1771{
1772 return control->next_app;
1773}

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

1784{
1785 return AST_VECTOR_STEAL_ELEMENTS(&control->next_app_args);
1786}
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition vector.h:151

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

1789{
1790 return AST_VECTOR_SIZE(&control->next_app_args);
1791}
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:637

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

1610{
1611 struct ao2_container *command_queue;
1612 int count = 0;
1613 struct ao2_iterator iter;
1614 struct stasis_app_command *command;
1615
1616 ast_channel_lock(chan);
1617 command_queue = command_prestart_get_container(chan);
1618 ast_channel_unlock(chan);
1619 if (!command_queue) {
1620 return 0;
1621 }
1622
1623 iter = ao2_iterator_init(command_queue, AO2_ITERATOR_UNLINK);
1624
1625 while ((command = ao2_iterator_next(&iter))) {
1626 command_invoke(command, control, chan);
1627 ao2_cleanup(command);
1628 ++count;
1629 }
1630
1631 ao2_iterator_destroy(&iter);
1632 ao2_cleanup(command_queue);
1633 return count;
1634}
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 1764 of file control.c.

1765{
1766 ao2_cleanup(control->app);
1767 control->app = ao2_bump(app);
1768}

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

Referenced by 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 899 of file control.c.

900{
901 if (control->silgen) {
902 ast_debug(3, "%s: Stopping silence generator\n",
905 control->channel, control->silgen);
906 control->silgen = NULL;
907 }
908}

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

1358{
1359 int res;
1360 struct ast_bridge_features *features;
1362
1363 if (!control || !bridge) {
1364 return -1;
1365 }
1366
1367 ast_debug(3, "%s: Adding to bridge %s\n",
1369 bridge->uniqueid);
1370
1371 ast_assert(chan != NULL);
1372
1373 /* Depart whatever Stasis bridge we're currently in. */
1374 if (stasis_app_get_bridge(control)) {
1375 /* Note that it looks like there's a race condition here, since
1376 * we don't have control locked. But this happens from the
1377 * control callback thread, so there won't be any other
1378 * concurrent attempts to bridge.
1379 */
1380 ast_bridge_depart(chan);
1381 }
1382
1383
1385 bridge_after_cb_failed, control);
1386 if (res != 0) {
1387 ast_log(LOG_ERROR, "Error setting after-bridge callback\n");
1388 return -1;
1389 }
1390
1391 ao2_lock(control);
1392
1393 /* Ensure the controlling application is subscribed early enough
1394 * to receive the ChannelEnteredBridge message. This works in concert
1395 * with the subscription handled in the Stasis application execution
1396 * loop */
1397 app_subscribe_bridge(control->app, bridge);
1398
1399 /* Save off the channel's PBX */
1400 ast_assert(control->pbx == NULL);
1401 if (!control->pbx) {
1402 control->pbx = ast_channel_pbx(chan);
1404 }
1405
1406 /* Pull bridge features from the control */
1407 features = control->bridge_features;
1408 control->bridge_features = NULL;
1409 if (features && features->inhibit_colp) {
1411 }
1412
1414 /* We need to set control->bridge here since bridge_after_cb may be run
1415 * before ast_bridge_impart returns. bridge_after_cb gets a reason
1416 * code so it can tell if the bridge is actually valid or not.
1417 */
1418 control->bridge = bridge;
1419
1420 /* We can't be holding the control lock while impart is running
1421 * or we could create a deadlock with bridge_after_cb which also
1422 * tries to lock control.
1423 */
1424 ao2_unlock(control);
1425 res = ast_bridge_impart(bridge,
1426 chan,
1427 swap,
1428 features, /* features */
1429 flags);
1430 if (res != 0) {
1431 /* ast_bridge_impart failed before it could spawn the depart
1432 * thread. The callbacks aren't called in this case.
1433 * The impart could still fail even if ast_bridge_impart returned
1434 * ok but that's handled by bridge_after_cb.
1435 */
1436 ast_log(LOG_ERROR, "Error adding channel to bridge\n");
1437 ao2_lock(control);
1438 ast_channel_pbx_set(chan, control->pbx);
1439 control->pbx = NULL;
1440 control->bridge = NULL;
1441 ao2_unlock(control);
1442 } else {
1443 ast_channel_lock(chan);
1444 set_interval_hook(chan);
1445 ast_channel_unlock(chan);
1446 }
1447
1448 return res;
1449}
@ AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP
Definition bridge.h:602
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:1327
static void bridge_after_cb(struct ast_channel *chan, void *data)
Definition control.c:1225
static void bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
Definition control.c:1232
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:75

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

1589{
1590 if (!control) {
1591 return;
1592 }
1593
1594 ast_assert(control->command_queue != NULL);
1595
1596 ao2_lock(control->command_queue);
1597 while (ao2_container_count(control->command_queue) == 0) {
1598 int res = ast_cond_wait(&control->wait_cond,
1600 if (res < 0) {
1601 ast_log(LOG_ERROR, "Error waiting on command queue\n");
1602 break;
1603 }
1604 }
1605 ao2_unlock(control->command_queue);
1606}
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:212

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

1132{
1133 ast_bridge_depart(chan);
1134
1135 /* Channels which have a PBX are not ones that have been created and dialed from ARI. They
1136 * have externally come in from the dialplan, and thus should not be placed into the dial
1137 * bridge. Only channels which are created and dialed in ARI should go into the dial bridge.
1138 */
1139 if (!ast_check_hangup(chan) && ast_channel_state(chan) != AST_STATE_UP && !ast_channel_pbx(chan)) {
1140 /* Channel is still being dialed, so put it back in the dialing bridge */
1141 add_to_dial_bridge(control, chan);
1142 }
1143
1144 return 0;
1145}
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition channel.c:446

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

1072{
1073 struct stasis_app_control *control = data;
1074 struct ast_bridge_channel *bridge_channel;
1075
1077 bridge_channel = ast_channel_get_bridge_channel(chan);
1079
1080 ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), ast_channel_hangupcause(chan));
1081
1083
1084 control->bridge = NULL;
1085}
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:10762
static int bridge_channel_depart(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:1147

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

1088{
1089 struct stasis_app_control *control = data;
1090
1091 ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), reason);
1092 dial_bridge_after_cb(control->channel, data);
1093}

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

548{
549 if (dtmf_data->before) {
550 usleep(dtmf_data->before * 1000);
551 }
552
553 ast_dtmf_stream_external(chan, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
554
555 if (dtmf_data->after) {
556 usleep(dtmf_data->after * 1000);
557 }
558}
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 560 of file control.c.

561{
562 if (dtmf_data->before) {
563 ast_safe_sleep(chan, dtmf_data->before);
564 }
565
566 ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
567
568 if (dtmf_data->after) {
569 ast_safe_sleep(chan, dtmf_data->after);
570 }
571}
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition channel.c:1561
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 316 of file control.c.

319{
320 return exec_command_on_condition(control, command_fn, data, data_destructor, NULL);
321}

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

279{
280 int retval;
281 struct stasis_app_command *command;
282
283 command_fn = command_fn ? : noop_cb;
284
285 command = command_create(command_fn, data, data_destructor);
286 if (!command) {
287 return NULL;
288 }
289
290 ao2_lock(control->command_queue);
291 if (control->is_done) {
292 ao2_unlock(control->command_queue);
293 ao2_ref(command, -1);
294 return NULL;
295 }
296 if (can_exec_fn && (retval = can_exec_fn(control))) {
297 ao2_unlock(control->command_queue);
298 command_complete(command, retval);
299 return command;
300 }
301
302 ao2_link_flags(control->command_queue, command, OBJ_NOLOCK);
303 ast_cond_signal(&control->wait_cond);
304
305 if (control->channel) {
306 /* Queue a null frame so that if and when the channel is waited on,
307 return immediately to process the new command */
309 }
310
311 ao2_unlock(control->command_queue);
312
313 return command;
314}
#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
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:1171
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:265
struct ast_frame ast_null_frame
Definition main/frame.c:79
#define ast_cond_signal(cond)
Definition lock.h:210

References ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, ast_cond_signal, ast_null_frame, ast_queue_frame(), stasis_app_control::channel, command_complete(), command_create(), stasis_app_control::command_queue, stasis_app_command::data, stasis_app_command::data_destructor, stasis_app_control::is_done, noop_cb(), NULL, OBJ_NOLOCK, stasis_app_command::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 735 of file control.c.

736{
737 struct chanvar *var = data;
738
739 ast_free(var->name);
740 ast_free(var->value);
741 ast_free(var);
742}

References ast_free, and var.

Referenced by stasis_app_control_set_channel_var_reportable().

◆ 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 1036 of file control.c.

1037{
1038 struct ast_bridge *ret_bridge = NULL;
1039
1041
1042 if (shutting_down) {
1043 goto end;
1044 }
1045
1046 if (dial_bridge) {
1047 ret_bridge = ao2_bump(dial_bridge);
1048 goto end;
1049 }
1050
1051 dial_bridge = stasis_app_bridge_create_invisible("holding", "dial_bridge", NULL);
1052 if (!dial_bridge) {
1053 goto end;
1054 }
1055 ret_bridge = ao2_bump(dial_bridge);
1056
1057end:
1059 return ret_bridge;
1060}
static struct ast_bridge * dial_bridge
Singleton dial bridge.
Definition control.c:1020
static int shutting_down
Indicates if the Stasis app internals are being shut down.
Definition control.c:52
static ast_mutex_t dial_bridge_lock
Definition control.c:1021
char * end
Definition eagi_proxy.c:73
#define ast_mutex_unlock(a)
Definition lock.h:197
#define ast_mutex_lock(a)
Definition lock.h:196
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:903

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

1267{
1268 /* Set cause code to No Answer to be consistent with other dial timeout operations */
1269 ast_channel_lock(chan);
1271 ast_channel_unlock(chan);
1273 return 0;
1274}
#define AST_CAUSE_NO_ANSWER
Definition causes.h:109
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2462
@ AST_SOFTHANGUP_EXPLICIT
Definition channel.h:1168
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)

References AST_CAUSE_NO_ANSWER, ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_unlock, 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 1170 of file control.c.

1172{
1173 struct stasis_app_control *control = data;
1174 struct ast_bridge_channel *bridge_channel;
1175
1176 ao2_lock(control);
1177 ast_debug(3, "%s, %s: %s\n",
1178 ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown",
1180
1182 /* The impart actually failed so control->bridge isn't valid. */
1183 control->bridge = NULL;
1184 }
1185
1186 ast_assert(chan == control->channel);
1187
1188 /* Restore the channel's PBX */
1189 ast_channel_pbx_set(control->channel, control->pbx);
1190 control->pbx = NULL;
1191
1192 if (control->bridge) {
1193 app_unsubscribe_bridge(control->app, control->bridge);
1194
1195 /* No longer in the bridge */
1196 control->bridge = NULL;
1197
1198 /* Get the bridge channel so we don't depart from the wrong bridge */
1200 bridge_channel = ast_channel_get_bridge_channel(chan);
1202
1203 /* Depart this channel from the bridge using the command queue if possible */
1205 }
1206
1208 /* The channel has had a StasisEnd published on it, but until now had remained in
1209 * the bridging system. This means that the channel moved from a Stasis bridge to a
1210 * non-Stasis bridge and is now exiting the bridging system. Because of this, the
1211 * channel needs to exit the Stasis application and go to wherever the non-Stasis
1212 * bridge has directed it to go. If the non-Stasis bridge has not set up an after
1213 * bridge destination, then the channel should be hung up.
1214 */
1215 int hangup_flag;
1216
1219 ast_softhangup_nolock(chan, hangup_flag);
1221 }
1222 ao2_unlock(control);
1223}
@ AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED
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?

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

267{
268 return 0;
269}

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

1328{
1329 struct ast_datastore *datastore;
1330 struct timeval *hangup_time;
1331 int64_t ms;
1332 struct ast_bridge_channel *bridge_channel;
1333
1335 if (!datastore) {
1336 return;
1337 }
1338
1339 hangup_time = datastore->data;
1340
1341 ms = ast_tvdiff_ms(*hangup_time, ast_tvnow());
1342 bridge_channel = ast_channel_get_bridge_channel(chan);
1343 if (!bridge_channel) {
1344 return;
1345 }
1346
1347 if (ast_bridge_interval_hook(bridge_channel->features, 0, ms > 0 ? ms : 1,
1348 bridge_timeout, NULL, NULL, 0)) {
1349 ao2_ref(bridge_channel, -1);
1350 return;
1351 }
1352
1353 ast_queue_frame(bridge_channel->chan, &ast_null_frame);
1354 ao2_ref(bridge_channel, -1);
1355}
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:3528
static int bridge_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
Dial timeout.
Definition control.c:1288
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 1676 of file control.c.

1677{
1678 struct ast_datastore *datastore;
1679 struct timeval *hangup_time;
1680
1681 hangup_time = ast_malloc(sizeof(struct timeval));
1682
1684 if (!datastore) {
1685 return -1;
1686 }
1687 *hangup_time = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1));
1688 datastore->data = hangup_time;
1689
1690 ast_channel_lock(chan);
1691 ast_channel_datastore_add(chan, datastore);
1692
1693 if (ast_channel_is_bridged(chan)) {
1694 set_interval_hook(chan);
1695 }
1696 ast_channel_unlock(chan);
1697
1698 return 0;
1699}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2376
#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:2280

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

1539{
1540 control->bridge_features->dtmf_passthrough = !absorb;
1541}
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 1456 of file control.c.

1458{
1459 ast_debug(3, "%s: Sending channel add_to_bridge command\n",
1461
1463 control, control_add_channel_to_bridge, bridge, NULL,
1465}
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:1451
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:928
static int app_control_can_add_channel_to_bridge(struct stasis_app_control *control)
Definition control.c:253

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

332{
333 char *role_dup;
334
335 role_dup = ast_strdup(role);
336 if (!role_dup) {
337 return -1;
338 }
339
341
342 return 0;
343}
static int app_control_add_role(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:323

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

1526{
1527 struct ast_bridge_features *features;
1528
1529 features = ast_bridge_features_new();
1530 if (!features) {
1531 return 1;
1532 }
1533 control->bridge_features = features;
1534 return 0;
1535}
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition bridge.c:3892

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

354{
356}
static int app_control_clear_roles(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:345

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

416{
417 struct stasis_app_control_continue_data *continue_data;
418
419 if (!(continue_data = ast_calloc(1, sizeof(*continue_data)))) {
420 return -1;
421 }
422 ast_copy_string(continue_data->context, S_OR(context, ""), sizeof(continue_data->context));
423 ast_copy_string(continue_data->extension, S_OR(extension, ""), sizeof(continue_data->extension));
424 if (priority > 0) {
425 continue_data->priority = priority;
426 } else {
427 continue_data->priority = -1;
428 }
429
431
432 return 0;
433}
#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:394
#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(), 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(), and outbound_session_handler_thread().

◆ 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 1739 of file control.c.

1741{
1742 struct control_dial_args *args;
1743
1745 if (!args) {
1746 return -1;
1747 }
1748
1751}
static struct control_dial_args * control_dial_args_alloc(const char *dialstring, unsigned int timeout)
Definition control.c:1646
static void control_dial_args_destroy(void *data)
Definition control.c:1663
static int app_control_dial(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:1701

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

592{
593 struct stasis_app_control_dtmf_data *dtmf_data;
594
595 if (!(dtmf_data = ast_calloc(1, sizeof(*dtmf_data) + strlen(dtmf) + 1))) {
596 return -1;
597 }
598
599 dtmf_data->before = before;
600 dtmf_data->between = between;
601 dtmf_data->duration = duration;
602 dtmf_data->after = after;
603 strcpy(dtmf_data->dtmf, dtmf);
604
606
607 return 0;
608}
static int app_control_dtmf(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:573

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

924{
926}
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 810 of file control.c.

811{
813}
static int app_control_hold(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:802

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

1551{
1552 control->bridge_features->inhibit_colp = inhibit_colp;
1553}

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

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_is_failed()

int stasis_app_control_is_failed ( const struct stasis_app_control control)

Check if a control object is marked as "failed".

Parameters
controlControl object to check

Definition at line 382 of file control.c.

383{
384 return control->failed;
385}
unsigned int failed
Definition control.c:110

References stasis_app_control::failed.

Referenced by stasis_app_exec().

◆ stasis_app_control_mark_failed()

void stasis_app_control_mark_failed ( struct stasis_app_control control)

Set the failed flag on a control structure.

Parameters
controlControl object to be updated

Definition at line 377 of file control.c.

378{
379 control->failed = 1;
380}

References stasis_app_control::failed.

Referenced by outbound_session_handler_thread().

◆ 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 842 of file control.c.

843{
844 char *data = NULL;
845
846 if (!ast_strlen_zero(moh_class)) {
847 data = ast_strdup(moh_class);
848 }
849
851}
static int app_control_moh_start(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:828
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 860 of file control.c.

861{
863}
static int app_control_moh_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:853

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

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

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

673{
674 struct stasis_app_control_mute_data *mute_data;
675
676 if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
677 return -1;
678 }
679
680 mute_data->direction = direction;
681 mute_data->frametype = frametype;
682
684
685 return 0;
686}
static int app_control_mute(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:660
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 1543 of file control.c.

1545{
1546 control->bridge_features->mute = mute;
1547}

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

Referenced by ast_ari_bridges_add_channel().

◆ stasis_app_control_progress()

int stasis_app_control_progress ( struct stasis_app_control control)

Indicate progress to the channel associated with this control.

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

Definition at line 648 of file control.c.

649{
651
652 return 0;
653}
static int app_control_progress(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:640

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

Referenced by ast_ari_channels_progress().

◆ 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 1509 of file control.c.

1511{
1512 if (!control || !control->channel || !message) {
1513 return;
1514 }
1516}
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:1589

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

1520{
1521 return ast_queue_control(control->channel, frame_type);
1522}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition channel.c:1289
frame_type

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

527{
528 char *endpoint_data = ast_strdup(endpoint);
529
530 if (!endpoint_data) {
531 return -1;
532 }
533
535
536 return 0;
537}
static int app_control_redirect(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:507

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

228{
229 return app_control_register_rule(control, &control->add_rules, rule);
230}
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:170

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

242{
243 return app_control_register_rule(control, &control->remove_rules, rule);
244}

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

1495{
1496 ast_debug(3, "%s: Sending channel remove_from_bridge command\n",
1501}
static int app_control_remove_channel_from_bridge(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:1467
static int app_control_can_remove_channel_from_bridge(struct stasis_app_control *control)
Definition control.c:259

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

619{
621
622 return 0;
623}
static int app_control_ring(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:610

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

634{
636
637 return 0;
638}
static int app_control_ring_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:625

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
Note
The thread that actually does the set will have the inhibit_escalations flag set before the call to pbx_builtin_setvar_helper to prevent dangerous dialplan function execution from ARI. The flag will be reset to its original state when pbx_builtin_setvar_helper returns.
Returns
0 for success.
-1 for error.

Definition at line 768 of file control.c.

769{
770 return stasis_app_control_set_channel_var_reportable(control, variable, value, 0);
771}
int stasis_app_control_set_channel_var_reportable(struct stasis_app_control *control, const char *variable, const char *value, int report_events)
Set a variable on the channel associated with this control to value with option of including in event...
Definition control.c:773
int value
Definition syslog.c:37

References stasis_app_control_set_channel_var_reportable(), and value.

◆ stasis_app_control_set_channel_var_reportable()

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

Set a variable on the channel associated with this control to value with option of including in events.

Parameters
controlControl for res_stasis.
variableThe name of the variable
valueThe value to set the variable to
report_eventsWhether to include this variable in channel events.
Returns
0 for success.
-1 for error.

Definition at line 773 of file control.c.

774{
775 struct chanvar *var;
776
777 var = ast_calloc(1, sizeof(*var));
778 if (!var) {
779 return -1;
780 }
781
782 var->name = ast_strdup(variable);
783 if (!var->name) {
785 return -1;
786 }
787
788 /* It's kosher for value to be NULL. It means the variable is being unset */
789 if (value) {
790 var->value = ast_strdup(value);
791 if (!var->value) {
793 return -1;
794 }
795 }
796
797 var->report_events = report_events ? 1 : 0;
798
800}
static int app_control_set_channel_var(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:744
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.
Definition control.c:960
static void free_chanvar(void *data)
Definition control.c:735
unsigned int report_events
Definition control.c:732

References app_control_set_channel_var(), ast_calloc, ast_strdup, free_chanvar(), chanvar::report_events, stasis_app_send_command(), value, and var.

Referenced by ast_ari_channels_set_channel_var(), ast_ari_channels_set_channel_vars(), and stasis_app_control_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 1753 of file control.c.

1754{
1756 shutting_down = 1;
1757 if (dial_bridge) {
1759 dial_bridge = NULL;
1760 }
1762}
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition bridge.c:1029

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

895{
897}
static int app_control_silence_start(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:865

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

918{
920}
static int app_control_silence_stop(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:910

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

824{
826}
static int app_control_unhold(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:815

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

701{
702 struct stasis_app_control_mute_data *mute_data;
703
704 if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
705 return -1;
706 }
707
708 mute_data->direction = direction;
709 mute_data->frametype = frametype;
710
712
713 return 0;
714}
static int app_control_unmute(struct stasis_app_control *control, struct ast_channel *chan, void *data)
Definition control.c:688

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

235{
236 app_control_unregister_rule(control, &control->add_rules, rule);
237}
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:179

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

249{
250 app_control_unregister_rule(control, &control->remove_rules, rule);
251}

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

994{
995 struct ast_bridge *ret;
996
997 if (!control) {
998 return NULL;
999 }
1000
1001 ao2_lock(control);
1002 ret = control->bridge;
1003 ao2_unlock(control);
1004
1005 return ret;
1006}

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

962{
963 return app_send_command_on_condition(control, command_fn, data, data_destructor, NULL);
964}

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

◆ 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 966 of file control.c.

969{
970 struct stasis_app_command *command;
971
972 if (control == NULL || control->is_done) {
973 /* If exec_command fails, it calls the data_destructor. In order to
974 * provide consistent behavior, we'll also call the data_destructor
975 * on this error path. This way, callers never have to call the
976 * data_destructor themselves.
977 */
978 if (data_destructor) {
980 }
981 return -1;
982 }
983
984 command = exec_command(control, command_fn, data, data_destructor);
985 if (!command) {
986 return -1;
987 }
988 ao2_ref(command, -1);
989
990 return 0;
991}
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:316

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_progress(), stasis_app_control_record(), stasis_app_control_redirect(), stasis_app_control_ring(), stasis_app_control_ring_stop(), stasis_app_control_silence_start(), stasis_app_control_silence_stop(), stasis_app_control_unhold(), and stasis_app_control_unmute().

◆ timeout_datastore_data_destructor()

static void timeout_datastore_data_destructor ( void *  data)
static

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

1256{
1257 ast_free(data);
1258}

References ast_free.

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

Referenced by get_dial_bridge(), and stasis_app_control_shutdown().

◆ dial_bridge_lock

ast_mutex_t dial_bridge_lock = AST_MUTEX_INIT_VALUE
static

Definition at line 1021 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 52 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",
}
static void timeout_datastore_data_destructor(void *data)
Dial timeout datastore.
Definition control.c:1255

Definition at line 1260 of file control.c.

1260 {
1261 .type = "ARI dial timeout",
1263};

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