Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Typedefs | Functions
stasis_app_impl.h File Reference

Backend API for implementing components of res_stasis. More...

#include "asterisk/stasis_app.h"
Include dependency graph for stasis_app_impl.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef void(* command_data_destructor_fn) (void *data)
 Typedef for data destructor for stasis app commands. More...
 
typedef int(* stasis_app_command_cb) (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 

Functions

int stasis_app_exec (struct ast_channel *chan, const char *app_name, int argc, char *argv[])
 Control a channel using stasis_app. More...
 
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. More...
 
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(). More...
 

Detailed Description

Backend API for implementing components of res_stasis.

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

This file defines functions useful for defining new commands to execute on channels while they are in Stasis.

Definition in file stasis_app_impl.h.

Typedef Documentation

◆ command_data_destructor_fn

typedef void(* command_data_destructor_fn) (void *data)

Typedef for data destructor for stasis app commands.

This is called during destruction of the command or if we fail to schedule a command. It is passed a pointer to the user-defined data of the command.

Parameters
dataData to destroy.

Definition at line 59 of file stasis_app_impl.h.

◆ stasis_app_command_cb

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

Callback type for stasis app commands

Definition at line 62 of file stasis_app_impl.h.

Function Documentation

◆ stasis_app_exec()

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

Control a channel using stasis_app.

Since
12

This function blocks until the channel hangs up, or stasis_app_control_continue() is called on the channel's stasis_app_control struct.

Parameters
chanChannel to control with Stasis.
app_nameApplication controlling the channel.
argcNumber of arguments for the application.
argvArguments for the application.

Control a channel using stasis_app.

Definition at line 1327 of file res_stasis.c.

1329{
1330 RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
1331 RAII_VAR(struct stasis_app_control *, control, NULL, control_unlink);
1332 struct ast_bridge *bridge = NULL;
1333 int res = 0;
1334 int needs_depart;
1335
1336 ast_assert(chan != NULL);
1337
1338 /* Just in case there's a lingering indication that the channel has had a stasis
1339 * end published on it, remove that now.
1340 */
1342
1343 if (!apps_registry) {
1344 return -1;
1345 }
1346
1348 if (!app) {
1350 "Stasis app '%s' not registered\n", app_name);
1351 return -1;
1352 }
1353 if (!app_is_active(app)) {
1355 "Stasis app '%s' not active\n", app_name);
1356 return -1;
1357 }
1358
1359 control = control_create(chan, app);
1360 if (!control) {
1361 ast_log(LOG_ERROR, "Control allocation failed or Stasis app '%s' not registered\n", app_name);
1362 return -1;
1363 }
1364
1365 if (!control_app(control)) {
1366 ast_log(LOG_ERROR, "Stasis app '%s' not registered\n", app_name);
1367 return -1;
1368 }
1369
1370 if (!app_is_active(control_app(control))) {
1371 ast_log(LOG_ERROR, "Stasis app '%s' not active\n", app_name);
1372 return -1;
1373 }
1374 ao2_link(app_controls, control);
1375
1376 if (add_masquerade_store(chan)) {
1377 ast_log(LOG_ERROR, "Failed to attach masquerade detector\n");
1378 return -1;
1379 }
1380
1381 res = send_start_msg(control_app(control), chan, argc, argv);
1382 if (res != 0) {
1384 "Error sending start message to '%s'\n", app_name);
1386 return -1;
1387 }
1388
1389 /* Pull queued prestart commands and execute */
1390 control_prestart_dispatch_all(control, chan);
1391
1392 while (!control_is_done(control)) {
1393 RAII_VAR(struct ast_frame *, f, NULL, ast_frame_dtor);
1394 int r;
1395 int command_count;
1396 RAII_VAR(struct ast_bridge *, last_bridge, NULL, ao2_cleanup);
1397
1398 /* Check to see if a bridge absorbed our hangup frame */
1399 if (ast_check_hangup_locked(chan)) {
1400 control_mark_done(control);
1401 break;
1402 }
1403
1404 /* control->next_app is only modified within the control thread, so this is safe */
1405 if (control_next_app(control)) {
1406 struct stasis_app *next_app = ao2_find(apps_registry, control_next_app(control), OBJ_SEARCH_KEY);
1407
1408 if (next_app && app_is_active(next_app)) {
1409 int idx;
1410 int next_argc;
1411 char **next_argv;
1412
1413 /* If something goes wrong in this conditional, res will need to be non-zero
1414 * so that the code below the exec loop knows something went wrong during a move.
1415 */
1417 res = has_masquerade_store(chan) && app_send_end_msg(control_app(control), chan);
1418 if (res != 0) {
1420 "Error sending end message to %s\n", stasis_app_name(control_app(control)));
1421 control_mark_done(control);
1422 ao2_ref(next_app, -1);
1423 break;
1424 }
1425 } else {
1427 }
1428
1429 /* This will ao2_bump next_app, and unref the previous app by 1 */
1430 control_set_app(control, next_app);
1431
1432 /* There's a chance that the previous application is ready for clean up, so go ahead
1433 * and do that now.
1434 */
1435 cleanup();
1436
1437 /* We need to add another masquerade store, otherwise the leave message will
1438 * not show up for the correct application.
1439 */
1440 if (add_masquerade_store(chan)) {
1441 ast_log(LOG_ERROR, "Failed to attach masquerade detector\n");
1442 res = -1;
1443 control_mark_done(control);
1444 ao2_ref(next_app, -1);
1445 break;
1446 }
1447
1448 /* We MUST get the size before the list, as control_next_app_args steals the elements
1449 * from the string vector.
1450 */
1451 next_argc = control_next_app_args_size(control);
1452 next_argv = control_next_app_args(control);
1453
1454 res = send_start_msg(control_app(control), chan, next_argc, next_argv);
1455
1456 /* Even if res != 0, we still need to free the memory we got from control_argv */
1457 if (next_argv) {
1458 for (idx = 0; idx < next_argc; idx++) {
1459 ast_free(next_argv[idx]);
1460 }
1461 ast_free(next_argv);
1462 }
1463
1464 if (res != 0) {
1466 "Error sending start message to '%s'\n", stasis_app_name(control_app(control)));
1468 control_mark_done(control);
1469 ao2_ref(next_app, -1);
1470 break;
1471 }
1472
1473 /* Done switching applications, free memory and clean up */
1474 control_move_cleanup(control);
1475 } else {
1476 /* If we can't switch applications, do nothing */
1477 struct ast_json *msg;
1478 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1479
1480 if (!next_app) {
1481 ast_log(LOG_ERROR, "Could not move to Stasis app '%s' - not registered\n",
1482 control_next_app(control));
1483 } else {
1484 ast_log(LOG_ERROR, "Could not move to Stasis app '%s' - not active\n",
1485 control_next_app(control));
1486 }
1487
1489 if (!snapshot) {
1490 ast_log(LOG_ERROR, "Could not get channel shapshot for '%s'\n",
1491 ast_channel_name(chan));
1492 } else {
1493 struct ast_json *json_args;
1494 int next_argc = control_next_app_args_size(control);
1495 char **next_argv = control_next_app_args(control);
1496
1497 msg = ast_json_pack("{s: s, s: o, s: o, s: s, s: []}",
1498 "type", "ApplicationMoveFailed",
1499 "timestamp", ast_json_timeval(ast_tvnow(), NULL),
1500 "channel", ast_channel_snapshot_to_json(snapshot, NULL),
1501 "destination", control_next_app(control),
1502 "args");
1503 if (!msg) {
1504 ast_log(LOG_ERROR, "Failed to pack JSON for ApplicationMoveFailed message\n");
1505 } else {
1506 json_args = ast_json_object_get(msg, "args");
1507 if (!json_args) {
1508 ast_log(LOG_ERROR, "Could not get args json array");
1509 } else {
1510 int r = 0;
1511 int idx;
1512 for (idx = 0; idx < next_argc; ++idx) {
1513 r = ast_json_array_append(json_args,
1514 ast_json_string_create(next_argv[idx]));
1515 if (r != 0) {
1516 ast_log(LOG_ERROR, "Error appending to ApplicationMoveFailed message\n");
1517 break;
1518 }
1519 }
1520 if (r == 0) {
1521 app_send(control_app(control), msg);
1522 }
1523 }
1524 ast_json_unref(msg);
1525 }
1526 }
1527 }
1528 control_move_cleanup(control);
1529 ao2_cleanup(next_app);
1530 }
1531
1532 last_bridge = bridge;
1533 bridge = ao2_bump(stasis_app_get_bridge(control));
1534
1535 if (bridge != last_bridge) {
1536 if (last_bridge) {
1537 app_unsubscribe_bridge(control_app(control), last_bridge);
1538 }
1539 if (bridge) {
1540 app_subscribe_bridge(control_app(control), bridge);
1541 }
1542 }
1543
1544 if (bridge) {
1545 /* Bridge/dial is handling channel frames */
1546 control_wait(control);
1547 control_dispatch_all(control, chan);
1548 continue;
1549 }
1550
1551 /* Set this thread's id as the control thread id so that any
1552 new commands can signal out of this wait */
1553 control_set_thread(control, pthread_self());
1554 r = ast_waitfor(chan, MAX_WAIT_MS);
1556
1557 if (r < 0) {
1558 ast_debug(3, "%s: Poll error\n",
1559 ast_channel_uniqueid(chan));
1560 control_mark_done(control);
1561 break;
1562 }
1563
1564 command_count = control_dispatch_all(control, chan);
1565
1566 if (command_count > 0 && ast_channel_fdno(chan) == -1) {
1567 /* Command drained the channel; wait for next frame */
1568 continue;
1569 }
1570
1571 if (r == 0) {
1572 /* Timeout */
1573 continue;
1574 }
1575
1576 f = ast_read(chan);
1577 if (!f) {
1578 /* Continue on in the dialplan */
1579 ast_debug(3, "%s: Hangup (no more frames)\n",
1580 ast_channel_uniqueid(chan));
1581 control_mark_done(control);
1582 break;
1583 }
1584
1585 if (f->frametype == AST_FRAME_CONTROL) {
1586 if (f->subclass.integer == AST_CONTROL_HANGUP) {
1587 /* Continue on in the dialplan */
1588 ast_debug(3, "%s: Hangup\n",
1589 ast_channel_uniqueid(chan));
1590 control_mark_done(control);
1591 break;
1592 }
1593 }
1594 }
1595
1596 ast_channel_lock(chan);
1597 needs_depart = (ast_channel_internal_bridge_channel(chan) != NULL);
1598 ast_channel_unlock(chan);
1599 if (needs_depart) {
1600 ast_bridge_depart(chan);
1601 }
1602
1603 if (stasis_app_get_bridge(control)) {
1605 }
1606 ao2_cleanup(bridge);
1607
1608 /* Only publish a stasis_end event if it hasn't already been published */
1609 if (!res && !stasis_app_channel_is_stasis_end_published(chan)) {
1610 /* A masquerade has occurred and this message will be wrong so it
1611 * has already been sent elsewhere. */
1612 res = has_masquerade_store(chan) && app_send_end_msg(control_app(control), chan);
1613 if (res != 0) {
1615 "Error sending end message to %s\n", stasis_app_name(control_app(control)));
1616 return res;
1617 }
1618 } else {
1620 }
1621
1622 control_flush_queue(control);
1623
1624 /* Stop any lingering silence generator */
1625 control_silence_stop_now(control);
1626
1627 /* There's an off chance that app is ready for cleanup. Go ahead
1628 * and clean up, just in case
1629 */
1630 cleanup();
1631
1632 /* The control needs to be removed from the controls container in
1633 * case a new PBX is started and ends up coming back into Stasis.
1634 */
1635 control_unlink(control);
1636 control = NULL;
1637
1638 if (!res && !ast_channel_pbx(chan)) {
1639 int chan_hungup;
1640
1641 /* The ASYNCGOTO softhangup flag may have broken the channel out of
1642 * its bridge to run dialplan, so if there's no pbx on the channel
1643 * let it run dialplan here. Otherwise, it will run when this
1644 * application exits. */
1645 ast_channel_lock(chan);
1647 chan_hungup = ast_check_hangup(chan);
1648 ast_channel_unlock(chan);
1649
1650 if (!chan_hungup) {
1651 struct ast_pbx_args pbx_args;
1652
1653 memset(&pbx_args, 0, sizeof(pbx_args));
1654 pbx_args.no_hangup_chan = 1;
1655
1656 res = ast_pbx_run_args(chan, &pbx_args);
1657 }
1658 }
1659
1660 return res;
1661}
static const char app[]
Definition: app_adsiprog.c:56
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition: bridge.c:1906
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2432
int ast_channel_fdno(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3162
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:459
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
struct ast_bridge_channel * ast_channel_internal_bridge_channel(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1126
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
void control_set_thread(struct stasis_app_control *control, pthread_t threadid)
set the control's thread id
Definition: control.c:194
struct stasis_app_control * control_create(struct ast_channel *channel, struct stasis_app *app)
Create a control object.
Definition: control.c:127
int control_prestart_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all queued prestart commands.
Definition: control.c:1555
void control_wait(struct stasis_app_control *control)
Blocks until control's command queue has a command available.
Definition: control.c:1535
char ** control_next_app_args(struct stasis_app_control *control)
Returns the list of arguments to pass to the application we are moving to.
Definition: control.c:1730
int control_is_done(struct stasis_app_control *control)
Returns true if control_continue() has been called on this control.
Definition: control.c:368
void control_flush_queue(struct stasis_app_control *control)
Flush the control command queue.
Definition: control.c:1502
int control_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan)
Dispatch all commands enqueued to this control.
Definition: control.c:1515
int control_next_app_args_size(struct stasis_app_control *control)
Returns the number of arguments to be passed to the application we are moving to.
Definition: control.c:1735
void control_set_app(struct stasis_app_control *control, struct stasis_app *app)
Set the application the control object belongs to.
Definition: control.c:1711
void control_silence_stop_now(struct stasis_app_control *control)
Stop playing silence to a channel right now.
Definition: control.c:857
char * control_next_app(struct stasis_app_control *control)
Returns the name of the application we are moving to.
Definition: control.c:1717
struct stasis_app * control_app(struct stasis_app_control *control)
Returns the pointer (non-reffed) to the app associated with this control.
Definition: control.c:1583
void control_move_cleanup(struct stasis_app_control *control)
Free any memory that was allocated for switching applications via /channels/{channelId}/move.
Definition: control.c:1722
void control_mark_done(struct stasis_app_control *control)
Definition: control.c:374
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,...
void ast_frame_dtor(struct ast_frame *frame)
NULL-safe wrapper for ast_frfree, good for RAII_VAR.
Definition: main/frame.c:187
@ AST_FRAME_CONTROL
@ AST_CONTROL_HANGUP
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:670
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
#define AST_PTHREADT_NULL
Definition: lock.h:66
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:4735
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Add a bridge subscription to an existing channel subscription.
int app_unsubscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
Cancel the bridge subscription for an application.
int app_is_active(struct stasis_app *app)
Checks whether an app is active.
void app_send(struct stasis_app *app, struct ast_json *message)
Send a message to an application.
static int send_start_msg(struct stasis_app *app, struct ast_channel *chan, int argc, char *argv[])
Definition: res_stasis.c:1060
struct ao2_container * app_controls
Definition: res_stasis.c:102
static void remove_stasis_end_published(struct ast_channel *chan)
Definition: res_stasis.c:1313
static void cleanup(void)
Clean up any old apps that we don't need any more.
Definition: res_stasis.c:327
static int add_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1220
static int has_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1214
int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
Send StasisEnd message to the listening app.
Definition: res_stasis.c:1086
#define MAX_WAIT_MS
Definition: res_stasis.c:77
static void remove_masquerade_store(struct ast_channel *chan)
Definition: res_stasis.c:1239
struct ao2_container * apps_registry
Stasis application container.
Definition: res_stasis.c:100
static void control_unlink(struct stasis_app_control *control)
In addition to running ao2_cleanup(), this function also removes the object from the app_controls con...
Definition: res_stasis.c:785
int stasis_app_channel_is_stasis_end_published(struct ast_channel *chan)
Has this channel had a StasisEnd published on it?
Definition: res_stasis.c:1302
#define NULL
Definition: resample.c:96
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition: control.c:951
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application's name.
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
Structure that contains information about a bridge.
Definition: bridge.h:349
Structure representing a snapshot of channel state.
Data structure associated with a single frame of data.
Abstract JSON element (object, array, string, int, ...).
Options for ast_pbx_run()
Definition: pbx.h:407
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_assert(a)
Definition: utils.h:739

References add_masquerade_store(), ao2_bump, ao2_cleanup, ao2_find, ao2_link, ao2_ref, app, app_controls, app_is_active(), app_name(), app_send(), app_send_end_msg(), app_subscribe_bridge(), app_unsubscribe_bridge(), apps_registry, ast_assert, ast_bridge_depart(), ast_channel_clear_softhangup(), ast_channel_fdno(), ast_channel_internal_bridge_channel(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_snapshot_get_latest(), ast_channel_snapshot_to_json(), ast_channel_uniqueid(), ast_channel_unlock, ast_check_hangup(), ast_check_hangup_locked(), AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CONTROL, ast_frame_dtor(), ast_free, ast_json_array_append(), ast_json_object_get(), ast_json_pack(), ast_json_string_create(), ast_json_timeval(), ast_json_unref(), ast_log, ast_pbx_run_args(), AST_PTHREADT_NULL, ast_read(), AST_SOFTHANGUP_ASYNCGOTO, ast_tvnow(), ast_waitfor(), cleanup(), control_app(), control_create(), control_dispatch_all(), control_flush_queue(), control_is_done(), control_mark_done(), control_move_cleanup(), control_next_app(), control_next_app_args(), control_next_app_args_size(), control_prestart_dispatch_all(), control_set_app(), control_set_thread(), control_silence_stop_now(), control_unlink(), control_wait(), has_masquerade_store(), LOG_ERROR, MAX_WAIT_MS, ast_pbx_args::no_hangup_chan, NULL, OBJ_SEARCH_KEY, RAII_VAR, remove_masquerade_store(), remove_stasis_end_published(), send_start_msg(), stasis_app_channel_is_stasis_end_published(), stasis_app_get_bridge(), and stasis_app_name().

Referenced by app_exec().

◆ stasis_app_send_command()

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

Invokes a command on a control's channel.

Since
12

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

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

Definition at line 918 of file control.c.

920{
921 return app_send_command_on_condition(control, command_fn, data, data_destructor, NULL);
922}
static int app_send_command_on_condition(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
Definition: control.c:886

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

Referenced by ast_ari_bridges_set_video_source(), and stasis_app_control_answer().

◆ stasis_app_send_command_async()

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

Asynchronous version of stasis_app_send_command().

Since
12

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

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

Definition at line 924 of file control.c.

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

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

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