Asterisk - The Open Source Telephony Project  21.4.1
Functions
control.h File Reference

Internal API for the Stasis application controller. More...

#include "asterisk/stasis_app.h"

Go to the source code of this file.

Functions

int control_add_channel_to_bridge (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 Command callback for adding a channel to a bridge. More...
 
struct stasis_appcontrol_app (struct stasis_app_control *control)
 Returns the pointer (non-reffed) to the app associated with this control. More...
 
int control_command_count (struct stasis_app_control *control)
 Returns the count of items in a control's command queue. More...
 
struct stasis_app_controlcontrol_create (struct ast_channel *channel, struct stasis_app *app)
 Create a control object. More...
 
int control_dispatch_all (struct stasis_app_control *control, struct ast_channel *chan)
 Dispatch all commands enqueued to this control. More...
 
void control_flush_queue (struct stasis_app_control *control)
 Flush the control command queue. More...
 
int control_is_done (struct stasis_app_control *control)
 Returns true if control_continue() has been called on this control. More...
 
void control_mark_done (struct stasis_app_control *control)
 
void control_move_cleanup (struct stasis_app_control *control)
 Free any memory that was allocated for switching applications via /channels/{channelId}/move. More...
 
char * control_next_app (struct stasis_app_control *control)
 Returns the name of the application we are moving to. More...
 
char ** control_next_app_args (struct stasis_app_control *control)
 Returns the list of arguments to pass to the application we are moving to. More...
 
int control_next_app_args_size (struct stasis_app_control *control)
 Returns the number of arguments to be passed to the application we are moving to. More...
 
int control_prestart_dispatch_all (struct stasis_app_control *control, struct ast_channel *chan)
 Dispatch all queued prestart commands. More...
 
void control_set_app (struct stasis_app_control *control, struct stasis_app *app)
 Set the application the control object belongs to. More...
 
void control_set_thread (struct stasis_app_control *control, pthread_t threadid)
 set the control's thread id More...
 
void control_silence_stop_now (struct stasis_app_control *control)
 Stop playing silence to a channel right now. More...
 
int control_swap_channel_in_bridge (struct stasis_app_control *control, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap)
 Command for swapping a channel in a bridge. More...
 
void control_wait (struct stasis_app_control *control)
 Blocks until control's command queue has a command available. More...
 

Detailed Description

Internal API for the Stasis application controller.

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

Definition in file control.h.

Function Documentation

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

References control_swap_channel_in_bridge().

Referenced by stasis_app_control_add_channel_to_bridge().

1401 {
1402  return control_swap_channel_in_bridge(control, data, chan, NULL);
1403 }
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:1306
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 1585 of file control.c.

References stasis_app_control::app.

Referenced by stasis_app_exec().

1586 {
1587  return control->app;
1588 }
struct stasis_app * app
Definition: control.c:92
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 365 of file control.c.

References ao2_container_count(), and stasis_app_control::command_queue.

Referenced by stasis_app_control_execute_until_exhausted().

366 {
367  return ao2_container_count(control->command_queue);
368 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ao2_container * command_queue
Definition: control.c:56
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 129 of file control.c.

References stasis_app_control::add_rules, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_bump, ao2_container_alloc_list, ao2_ref, stasis_app_control::app, ast_channel_ref, AST_LIST_HEAD_INIT, AST_VECTOR_INIT, stasis_app_control::channel, stasis_app_control::command_queue, control_set_thread(), stasis_app_control::next_app, stasis_app_control::next_app_args, and stasis_app_control::remove_rules.

Referenced by stasis_app_control_create(), and stasis_app_exec().

130 {
131  struct stasis_app_control *control;
132  int res;
133 
134  control = ao2_alloc(sizeof(*control), control_dtor);
135  if (!control) {
136  return NULL;
137  }
138 
139  AST_LIST_HEAD_INIT(&control->add_rules);
140  AST_LIST_HEAD_INIT(&control->remove_rules);
141 
142  res = ast_cond_init(&control->wait_cond, NULL);
143  if (res != 0) {
144  ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
145  strerror(errno));
146  ao2_ref(control, -1);
147  return NULL;
148  }
149 
150  control->app = ao2_bump(app);
151 
152  ast_channel_ref(channel);
153  control->channel = channel;
154 
156  AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL);
157  if (!control->command_queue) {
158  ao2_ref(control, -1);
159  return NULL;
160  }
161 
162  control->next_app = NULL;
163  AST_VECTOR_INIT(&control->next_app_args, 0);
164 
165  control_set_thread(control, AST_PTHREADT_NULL);
166 
167  return control;
168 }
char * next_app
Definition: control.c:96
struct app_control_rules remove_rules
Definition: control.c:82
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
struct stasis_app * app
Definition: control.c:92
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void control_set_thread(struct stasis_app_control *control, pthread_t threadid)
set the control's thread id
Definition: control.c:196
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
struct stasis_app_control::@497 next_app_args
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ast_channel * channel
Definition: control.c:62
struct ao2_container * command_queue
Definition: control.c:56
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
struct app_control_rules add_rules
Definition: control.c:78
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 1517 of file control.c.

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

Referenced by stasis_app_control_execute_until_exhausted(), and stasis_app_exec().

1519 {
1520  int count = 0;
1521  struct ao2_iterator iter;
1522  struct stasis_app_command *command;
1523 
1524  ast_assert(control->channel == chan);
1525 
1527  while ((command = ao2_iterator_next(&iter))) {
1528  command_invoke(command, control, chan);
1529  ao2_ref(command, -1);
1530  ++count;
1531  }
1532  ao2_iterator_destroy(&iter);
1533 
1534  return count;
1535 }
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ast_channel * channel
Definition: control.c:62
struct ao2_container * command_queue
Definition: control.c:56
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
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 1504 of file control.c.

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

Referenced by stasis_app_control_flush_queue(), and stasis_app_exec().

1505 {
1506  struct ao2_iterator iter;
1507  struct stasis_app_command *command;
1508 
1510  while ((command = ao2_iterator_next(&iter))) {
1511  command_complete(command, -1);
1512  ao2_ref(command, -1);
1513  }
1514  ao2_iterator_destroy(&iter);
1515 }
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ao2_container * command_queue
Definition: control.c:56
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
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 370 of file control.c.

References stasis_app_control::is_done.

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

371 {
372  /* Called from stasis_app_exec thread; no lock needed */
373  return control->is_done;
374 }
unsigned int is_done
Definition: control.c:108
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 1724 of file control.c.

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

Referenced by stasis_app_exec().

1725 {
1726  ast_free(control->next_app);
1727  control->next_app = NULL;
1728 
1730 }
char * next_app
Definition: control.c:96
void ast_free_ptr(void *ptr)
free() wrapper
Definition: main/astmm.c:1739
struct stasis_app_control::@497 next_app_args
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
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 1719 of file control.c.

References stasis_app_control::next_app.

Referenced by stasis_app_exec().

1720 {
1721  return control->next_app;
1722 }
char * next_app
Definition: control.c:96
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 1732 of file control.c.

References AST_VECTOR_STEAL_ELEMENTS, and stasis_app_control::next_app_args.

Referenced by stasis_app_exec().

1733 {
1734  return AST_VECTOR_STEAL_ELEMENTS(&control->next_app_args);
1735 }
struct stasis_app_control::@497 next_app_args
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition: vector.h:140
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 1737 of file control.c.

References AST_VECTOR_SIZE, and stasis_app_control::next_app_args.

Referenced by stasis_app_exec().

1738 {
1739  return AST_VECTOR_SIZE(&control->next_app_args);
1740 }
struct stasis_app_control::@497 next_app_args
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
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 1557 of file control.c.

References ao2_iterator_destroy(), ao2_iterator_init(), AO2_ITERATOR_UNLINK, command_prestart_get_container(), and stasis_app_control::command_queue.

Referenced by stasis_app_exec().

1559 {
1560  struct ao2_container *command_queue;
1561  int count = 0;
1562  struct ao2_iterator iter;
1563  struct stasis_app_command *command;
1564 
1565  ast_channel_lock(chan);
1566  command_queue = command_prestart_get_container(chan);
1567  ast_channel_unlock(chan);
1568  if (!command_queue) {
1569  return 0;
1570  }
1571 
1572  iter = ao2_iterator_init(command_queue, AO2_ITERATOR_UNLINK);
1573 
1574  while ((command = ao2_iterator_next(&iter))) {
1575  command_invoke(command, control, chan);
1576  ao2_cleanup(command);
1577  ++count;
1578  }
1579 
1580  ao2_iterator_destroy(&iter);
1581  ao2_cleanup(command_queue);
1582  return count;
1583 }
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * command_prestart_get_container(struct ast_channel *chan)
Get the Stasis() prestart commands for a channel.
Definition: command.c:160
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
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 1713 of file control.c.

References ao2_bump, and stasis_app_control::app.

Referenced by stasis_app_exec().

1714 {
1715  ao2_cleanup(control->app);
1716  control->app = ao2_bump(app);
1717 }
struct stasis_app * app
Definition: control.c:92
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void control_set_thread ( struct stasis_app_control control,
pthread_t  threadid 
)

set the control's thread id

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

Definition at line 196 of file control.c.

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

Referenced by control_create(), and stasis_app_exec().

197 {
198  ao2_lock(control->command_queue);
199  control->control_thread = threadid;
200  ao2_unlock(control->command_queue);
201 }
struct ao2_container * command_queue
Definition: control.c:56
pthread_t control_thread
Definition: control.c:100
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 859 of file control.c.

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

Referenced by stasis_app_exec().

860 {
861  if (control->silgen) {
862  ast_debug(3, "%s: Stopping silence generator\n",
865  control->channel, control->silgen);
866  control->silgen = NULL;
867  }
868 }
struct ast_channel * channel
Definition: control.c:62
#define ast_debug(level,...)
Log a DEBUG message.
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:1452
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8210
struct ast_silence_generator * silgen
Definition: control.c:86
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 1306 of file control.c.

References stasis_app_control::app, app_subscribe_bridge(), ast_bridge_depart(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_DEPARTABLE, AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP, ast_bridge_set_after_callback(), ast_debug, stasis_app_control::bridge, stasis_app_control::bridge_features, ast_bridge_features::inhibit_colp, 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().

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

References ao2_container_count(), ao2_object_get_lockaddr(), and stasis_app_control::command_queue.

Referenced by stasis_app_exec().

1538 {
1539  if (!control) {
1540  return;
1541  }
1542 
1543  ast_assert(control->command_queue != NULL);
1544 
1545  ao2_lock(control->command_queue);
1546  while (ao2_container_count(control->command_queue) == 0) {
1547  int res = ast_cond_wait(&control->wait_cond,
1549  if (res < 0) {
1550  ast_log(LOG_ERROR, "Error waiting on command queue\n");
1551  break;
1552  }
1553  }
1554  ao2_unlock(control->command_queue);
1555 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
struct ao2_container * command_queue
Definition: control.c:56