56 #include "asterisk/stasis_channels.h"
60 #define AST_NAME_STRLEN 256
61 #define NUM_SPYGROUPS 128
373 static const char app_chan[] =
"ChanSpy";
375 static const char app_ext[] =
"ExtenSpy";
377 static const char app_dahdiscan[] =
"DAHDIScan";
380 OPTION_QUIET = (1 << 0),
381 OPTION_BRIDGED = (1 << 1),
382 OPTION_VOLUME = (1 << 2),
383 OPTION_GROUP = (1 << 3),
384 OPTION_RECORD = (1 << 4),
385 OPTION_WHISPER = (1 << 5),
386 OPTION_PRIVATE = (1 << 6),
387 OPTION_READONLY = (1 << 7),
388 OPTION_EXIT = (1 << 8),
389 OPTION_ENFORCED = (1 << 9),
390 OPTION_NOTECH = (1 << 10),
391 OPTION_BARGE = (1 << 11),
392 OPTION_NAME = (1 << 12),
393 OPTION_DTMF_SWITCH_MODES = (1 << 13),
394 OPTION_DTMF_EXIT = (1 << 14),
395 OPTION_DTMF_CYCLE = (1 << 15),
396 OPTION_DAHDI_SCAN = (1 << 16),
397 OPTION_STOP = (1 << 17),
398 OPTION_EXITONHANGUP = (1 << 18),
399 OPTION_UNIQUEID = (1 << 19),
400 OPTION_LONG_QUEUE = (1 << 20),
401 OPTION_INTERLEAVED = (1 << 21),
455 static void *spy_alloc(
struct ast_channel *chan,
void *data)
461 static void spy_release(
struct ast_channel *chan,
void *data)
466 static int spy_generate(
struct ast_channel *chan,
void *data,
int len,
int samples)
478 if (ast_test_flag(&csth->flags, OPTION_READONLY)) {
481 }
else if (ast_test_flag(&csth->flags, OPTION_INTERLEAVED)) {
488 short stereo_buf[samples * 2];
491 .datalen =
sizeof(stereo_buf),
502 memcpy(read_buf, fr_read->
data.ptr,
sizeof(read_buf));
505 memset(read_buf, 0,
sizeof(read_buf));
509 memcpy(write_buf, fr_write->
data.ptr,
sizeof(write_buf));
511 memset(write_buf, 0,
sizeof(write_buf));
514 for (i = 0; i <
samples; i++) {
515 stereo_buf[i*2] = read_buf[i];
516 stereo_buf[i*2+1] = write_buf[i];
519 stereo_frame.
data.ptr = stereo_buf;
547 if (write(csth->fd, cur->
data.ptr, cur->
datalen) < 0) {
548 ast_log(LOG_WARNING,
"write() failed: %s\n", strerror(errno));
560 .release = spy_release,
561 .generate = spy_generate,
569 ast_verb(3,
"Attaching spy channel %s to %s\n",
570 spychan_name, ast_channel_name(autochan->chan));
572 if (ast_test_flag(flags, OPTION_READONLY)) {
577 if (ast_test_flag(flags, OPTION_LONG_QUEUE)) {
578 ast_debug(9,
"Using a long queue to store audio frames in spy audiohook\n");
583 ast_autochan_channel_unlock(autochan);
587 static void change_spy_mode(
const char digit,
struct ast_flags *flags)
590 ast_clear_flag(flags, OPTION_WHISPER);
591 ast_clear_flag(flags, OPTION_BARGE);
592 }
else if (digit ==
'5') {
593 ast_clear_flag(flags, OPTION_BARGE);
594 ast_set_flag(flags, OPTION_WHISPER);
595 }
else if (digit ==
'6') {
596 ast_clear_flag(flags, OPTION_WHISPER);
597 ast_set_flag(flags, OPTION_BARGE);
601 static int pack_channel_into_message(
struct ast_channel *chan,
const char *role,
622 static void publish_chanspy_message(
struct ast_channel *spyer,
632 ast_log(AST_LOG_WARNING,
"Attempt to publish ChanSpy message for NULL spyer channel\n");
636 if (!blob || !type) {
645 if (pack_channel_into_message(spyer,
"spyer_channel", payload)) {
650 if (pack_channel_into_message(spyee,
"spyee_channel", payload)) {
662 static int attach_barge(
struct ast_autochan *spyee_autochan,
664 const char *spyer_name,
const char *name,
struct ast_flags *flags)
673 ast_autochan_channel_unlock(spyee_autochan);
683 if (!internal_bridge_autochan) {
687 if (start_spying(internal_bridge_autochan, spyer_name, bridge_whisper_audiohook, flags)) {
688 ast_log(LOG_WARNING,
"Unable to attach barge audiohook on spyee '%s'. Barge mode disabled.\n", name);
692 *spyee_bridge_autochan = internal_bridge_autochan;
702 int running = 0, bridge_connected = 0, res, x = 0;
708 const char *spyer_name;
710 ast_channel_lock(chan);
712 ast_channel_unlock(chan);
716 ast_channel_unlock(chan);
720 || ast_test_flag(ast_channel_flags(spyee_autochan->chan),
AST_FLAG_ZOMBIE)) {
721 ast_autochan_channel_unlock(spyee_autochan);
724 name =
ast_strdupa(ast_channel_name(spyee_autochan->chan));
726 ast_verb(2,
"Spying on channel %s\n", name);
727 publish_chanspy_message(chan, spyee_autochan->chan, 1);
728 ast_autochan_channel_unlock(spyee_autochan);
730 memset(&csth, 0,
sizeof(csth));
731 ast_copy_flags(&csth.flags, flags, AST_FLAGS_ALL);
738 if (start_spying(spyee_autochan, spyer_name, &csth.spy_audiohook, flags)) {
743 if (ast_test_flag(flags, OPTION_WHISPER | OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
749 if (start_spying(spyee_autochan, spyer_name, &csth.whisper_audiohook, flags)) {
750 ast_log(LOG_WARNING,
"Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", name);
756 csth.volfactor = *volfactor;
758 if (csth.volfactor) {
765 if (ast_test_flag(flags, OPTION_PRIVATE))
798 if (!bridge_connected && attach_barge(spyee_autochan, &spyee_bridge_autochan,
799 &csth.bridge_whisper_audiohook, spyer_name, name, flags) == 0) {
800 bridge_connected = 1;
807 if (bridge_connected) {
828 if (x ==
sizeof(inp))
836 if (ast_test_flag(flags, OPTION_EXIT)) {
841 ast_debug(1,
"Got DTMF %c, goto context %s\n", tmp[0], exitcontext);
846 ast_debug(2,
"Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
848 }
else if (res >=
'0' && res <=
'9') {
849 if (ast_test_flag(flags, OPTION_DTMF_SWITCH_MODES)) {
850 change_spy_mode(res, flags);
856 if (res == user_options->cycle) {
859 }
else if (res == user_options->exit) {
862 }
else if (res == user_options->volume) {
863 if (!ast_strlen_zero(inp)) {
871 ast_verb(3,
"Setting spy volume on %s to %d\n", ast_channel_name(chan), *volfactor);
873 csth.volfactor = *volfactor;
879 if (ast_test_flag(flags, OPTION_PRIVATE))
886 if (ast_test_flag(flags, OPTION_WHISPER | OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
893 if (ast_test_flag(flags, OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
905 ast_verb(2,
"Done Spying on channel %s\n", name);
906 publish_chanspy_message(chan, spyee_autochan->chan, 0);
908 if (spyee_bridge_autochan) {
920 const size_t pseudo_len = strlen(
"DAHDI/pseudo");
927 if (!strncmp(ast_channel_name(next),
"DAHDI/pseudo", pseudo_len)
935 return autochan_store;
940 static int spy_sayname(
struct ast_channel *chan,
const char *mailbox,
const char *context)
944 mailbox_id =
ast_alloca(strlen(mailbox) + strlen(context) + 2);
945 sprintf(mailbox_id,
"%s@%s", mailbox, context);
951 const char *mygroup,
const char *myenforced,
const char *spec,
const char *exten,
952 const char *context,
const char *mailbox,
const char *name_context)
954 char nameprefix[AST_NAME_STRLEN];
956 signed char zero_volume = 0;
959 int num_spied_upon = 1;
962 if (ast_test_flag(flags, OPTION_EXIT)) {
964 ast_channel_lock(chan);
968 ast_copy_string(exitcontext, ast_channel_context(chan),
sizeof(exitcontext));
970 ast_channel_unlock(chan);
981 struct ast_autochan *autochan = NULL, *next_autochan = NULL;
984 if (!ast_test_flag(flags, OPTION_QUIET) && num_spied_upon) {
992 if (!ast_strlen_zero(exitcontext)) {
999 ast_debug(2,
"Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
1004 if (!ast_strlen_zero(spec)) {
1005 if (ast_test_flag(flags, OPTION_UNIQUEID)) {
1018 }
else if (!ast_strlen_zero(exten)) {
1035 if (!ast_strlen_zero(exitcontext)) {
1043 ast_debug(2,
"Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
1051 for (autochan = next_channel(iter, chan);
1053 prev = autochan->chan,
1055 autochan = next_autochan ?: next_channel(iter, chan),
1056 next_autochan = NULL) {
1057 int igrp = !mygroup;
1058 int ienf = !myenforced;
1060 if (autochan->chan == prev) {
1071 if (ast_test_flag(flags, OPTION_BRIDGED)
1073 ast_autochan_channel_unlock(autochan);
1078 || ast_test_flag(ast_channel_flags(autochan->chan),
AST_FLAG_SPYING)) {
1079 ast_autochan_channel_unlock(autochan);
1082 ast_autochan_channel_unlock(autochan);
1086 int num_mygroups = 0;
1087 char dup_group[512];
1088 char dup_mygroup[512];
1089 char *
groups[NUM_SPYGROUPS];
1090 char *mygroups[NUM_SPYGROUPS];
1091 const char *
group = NULL;
1095 num_mygroups = ast_app_separate_args(dup_mygroup,
':', mygroups,
1096 ARRAY_LEN(mygroups));
1101 if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) {
1106 ast_autochan_channel_unlock(autochan);
1108 if (!ast_strlen_zero(group)) {
1110 num_groups = ast_app_separate_args(dup_group,
':', groups,
1114 for (y = 0; y < num_mygroups; y++) {
1115 for (x = 0; x < num_groups; x++) {
1116 if (!strcmp(mygroups[y], groups[x])) {
1132 snprintf(buffer,
sizeof(buffer) - 1,
":%s:", myenforced);
1135 ast_copy_string(ext + 1, ast_channel_name(autochan->chan),
sizeof(ext) - 1);
1136 ast_autochan_channel_unlock(autochan);
1137 if ((end = strchr(ext,
'-'))) {
1144 if (strcasestr(buffer, ext)) {
1153 if (!ast_test_flag(flags, OPTION_QUIET)) {
1154 char peer_name[AST_NAME_STRLEN + 5];
1157 strcpy(peer_name,
"spy-");
1159 strncat(peer_name, ast_channel_name(autochan->chan), AST_NAME_STRLEN - 4 - 1);
1160 ast_autochan_channel_unlock(autochan);
1161 if ((ptr = strchr(peer_name,
'/'))) {
1163 for (s = peer_name; s < ptr; s++) {
1166 if ((s = strchr(ptr,
'-'))) {
1171 if (ast_test_flag(flags, OPTION_NAME)) {
1172 const char *local_context =
S_OR(name_context,
"default");
1173 const char *local_mailbox =
S_OR(mailbox, ptr);
1175 if (local_mailbox) {
1176 res = spy_sayname(chan, local_mailbox, local_context);
1181 if (!ast_test_flag(flags, OPTION_NAME) || res < 0) {
1183 if (!ast_test_flag(flags, OPTION_NOTECH)) {
1185 res =
ast_streamfile(chan, peer_name, ast_channel_language(chan));
1197 if (ptr && (num = atoi(ptr))) {
1203 res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext);
1210 }
else if (res == -2) {
1215 }
else if (res > 1 && spec && !ast_test_flag(flags, OPTION_UNIQUEID)) {
1218 snprintf(nameprefix, AST_NAME_STRLEN,
"%s/%d", spec, res);
1230 next_autochan = NULL;
1232 ast_autochan_channel_unlock(autochan);
1234 }
else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) {
1245 if (ast_test_flag(flags, OPTION_STOP) && !next_autochan) {
1258 static int chanspy_exec(
struct ast_channel *chan,
const char *data)
1260 char *myenforced = NULL;
1261 char *mygroup = NULL;
1262 char *recbase = NULL;
1273 char *mailbox = NULL;
1274 char *name_context = NULL;
1279 char *opts[OPT_ARG_ARRAY_SIZE];
1284 if (args.spec && !strcmp(args.spec,
"all"))
1290 if (ast_test_flag(&flags, OPTION_GROUP))
1291 mygroup = opts[OPT_ARG_GROUP];
1293 if (ast_test_flag(&flags, OPTION_RECORD) &&
1294 !(recbase = opts[OPT_ARG_RECORD]))
1295 recbase =
"chanspy";
1297 if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
1298 tmp = opts[OPT_ARG_EXIT][0];
1299 if (strchr(
"0123456789*#", tmp) && tmp !=
'\0') {
1300 user_options.exit = tmp;
1302 ast_log(LOG_NOTICE,
"Argument for option 'x' must be a valid DTMF digit.\n");
1306 if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
1307 tmp = opts[OPT_ARG_CYCLE][0];
1308 if (strchr(
"0123456789*#", tmp) && tmp !=
'\0') {
1309 user_options.cycle = tmp;
1311 ast_log(LOG_NOTICE,
"Argument for option 'c' must be a valid DTMF digit.\n");
1315 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
1318 if ((sscanf(opts[OPT_ARG_VOLUME],
"%30d", &vol) != 1) || (vol > 4) || (vol < -4))
1319 ast_log(LOG_NOTICE,
"Volume factor must be a number between -4 and 4\n");
1324 if (ast_test_flag(&flags, OPTION_PRIVATE))
1325 ast_set_flag(&flags, OPTION_WHISPER);
1327 if (ast_test_flag(&flags, OPTION_ENFORCED))
1328 myenforced = opts[OPT_ARG_ENFORCED];
1330 if (ast_test_flag(&flags, OPTION_NAME)) {
1331 if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
1333 if ((delimiter = strchr(opts[OPT_ARG_NAME],
'@'))) {
1334 mailbox = opts[OPT_ARG_NAME];
1335 *delimiter++ =
'\0';
1336 name_context = delimiter;
1338 mailbox = opts[OPT_ARG_NAME];
1343 ast_clear_flag(&flags, AST_FLAGS_ALL);
1346 oldwf =
ao2_bump(ast_channel_writeformat(chan));
1348 ast_log(LOG_ERROR,
"Could Not Set Write Format.\n");
1353 char filename[PATH_MAX];
1355 snprintf(filename,
sizeof(filename),
"%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (
int) time(NULL));
1356 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
1357 ast_log(LOG_WARNING,
"Cannot open '%s' for recording\n", filename);
1362 res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context);
1368 ast_log(LOG_ERROR,
"Could Not Set Write Format.\n");
1370 if (ast_test_flag(&flags, OPTION_EXITONHANGUP)) {
1371 ast_verb(3,
"Stopped spying due to the spied-on channel hanging up.\n");
1377 static int extenspy_exec(
struct ast_channel *chan,
const char *data)
1379 char *ptr, *exten = NULL;
1380 char *mygroup = NULL;
1381 char *recbase = NULL;
1392 char *mailbox = NULL;
1393 char *name_context = NULL;
1402 if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context,
'@'))) {
1403 exten = args.context;
1407 if (ast_strlen_zero(args.context))
1408 args.context =
ast_strdupa(ast_channel_context(chan));
1411 char *opts[OPT_ARG_ARRAY_SIZE];
1415 if (ast_test_flag(&flags, OPTION_GROUP))
1416 mygroup = opts[OPT_ARG_GROUP];
1418 if (ast_test_flag(&flags, OPTION_RECORD) &&
1419 !(recbase = opts[OPT_ARG_RECORD]))
1420 recbase =
"chanspy";
1422 if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
1423 tmp = opts[OPT_ARG_EXIT][0];
1424 if (strchr(
"0123456789*#", tmp) && tmp !=
'\0') {
1425 user_options.exit = tmp;
1427 ast_log(LOG_NOTICE,
"Argument for option 'x' must be a valid DTMF digit.\n");
1431 if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
1432 tmp = opts[OPT_ARG_CYCLE][0];
1433 if (strchr(
"0123456789*#", tmp) && tmp !=
'\0') {
1434 user_options.cycle = tmp;
1436 ast_log(LOG_NOTICE,
"Argument for option 'c' must be a valid DTMF digit.\n");
1440 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
1443 if ((sscanf(opts[OPT_ARG_VOLUME],
"%30d", &vol) != 1) || (vol > 4) || (vol < -4))
1444 ast_log(LOG_NOTICE,
"Volume factor must be a number between -4 and 4\n");
1449 if (ast_test_flag(&flags, OPTION_PRIVATE))
1450 ast_set_flag(&flags, OPTION_WHISPER);
1452 if (ast_test_flag(&flags, OPTION_NAME)) {
1453 if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
1455 if ((delimiter = strchr(opts[OPT_ARG_NAME],
'@'))) {
1456 mailbox = opts[OPT_ARG_NAME];
1457 *delimiter++ =
'\0';
1458 name_context = delimiter;
1460 mailbox = opts[OPT_ARG_NAME];
1467 ast_clear_flag(&flags, AST_FLAGS_ALL);
1470 oldwf =
ao2_bump(ast_channel_writeformat(chan));
1472 ast_log(LOG_ERROR,
"Could Not Set Write Format.\n");
1477 char filename[PATH_MAX];
1479 snprintf(filename,
sizeof(filename),
"%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (
int) time(NULL));
1480 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
1481 ast_log(LOG_WARNING,
"Cannot open '%s' for recording\n", filename);
1487 res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);
1493 ast_log(LOG_ERROR,
"Could Not Set Write Format.\n");
1498 static int dahdiscan_exec(
struct ast_channel *chan,
const char *data)
1500 const char *spec =
"DAHDI";
1509 char *mygroup = NULL;
1512 ast_clear_flag(&flags, AST_FLAGS_ALL);
1514 if (!ast_strlen_zero(data)) {
1517 ast_set_flag(&flags, OPTION_DTMF_EXIT);
1518 ast_set_flag(&flags, OPTION_DTMF_CYCLE);
1519 ast_set_flag(&flags, OPTION_DAHDI_SCAN);
1521 oldwf =
ao2_bump(ast_channel_writeformat(chan));
1523 ast_log(LOG_ERROR,
"Could Not Set Write Format.\n");
1528 res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);
1531 ast_log(LOG_ERROR,
"Could Not Set Write Format.\n");
1537 static int unload_module(
void)
1548 static int load_module(
void)
1559 AST_MODULE_INFO_STANDARD(
ASTERISK_GPL_KEY,
"Listen to the audio of an active channel");
Main Channel structure associated with a channel.
#define ast_frdup(fr)
Copies a frame.
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Asterisk locking-related definitions:
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Asterisk main include file. File version handling, generic pbx functions.
int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
Writes a frame into the audiohook structure.
#define AST_OPTION_TXGAIN
#define ast_autochan_channel_lock(autochan)
Lock the autochan's channel lock.
#define ast_channel_unref(c)
Decrease channel reference count.
int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id)
Play a recorded user name for the mailbox to the specified channel.
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
Support for translation of data formats. translate.c.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
Structure representing a snapshot of channel state.
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Clear a flag on a channel.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
ast_channel_state
ast_channel states
int ast_say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang)
says digits
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
struct stasis_message_type * ast_channel_chanspy_start_type(void)
Message type for when a channel starts spying on another channel.
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
int ast_unregister_application(const char *app)
Unregister an application.
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
struct ast_json * ast_json_null(void)
Get the JSON null value.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
General Asterisk PBX channel definitions.
Asterisk JSON abstraction layer.
Asterisk file paths, configured in asterisk.conf.
#define ast_strdupa(s)
duplicate a string in memory from the stack
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
Add a ast_channel_snapshot to a ast_multi_channel_blob object.
#define ast_channel_cleanup(c)
Cleanup a channel reference.
#define ast_debug(level,...)
Log a DEBUG message.
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
function to pronounce character and phonetic strings
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Core PBX routines and definitions.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
"smart" channels that update automatically if a channel is masqueraded
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
void ast_channel_set_flag(struct ast_channel *chan, unsigned int flag)
Set a flag on a channel.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
struct ast_channel_iterator * ast_channel_iterator_by_exten_new(const char *exten, const char *context)
Create a new channel iterator based on extension.
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
void(* digit)(struct ast_channel *chan, char digit)
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.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
union ast_frame::@224 data
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Structure used to handle boolean flags.
struct ast_channel_iterator * ast_channel_iterator_by_name_new(const char *name, size_t name_len)
Create a new channel iterator based on name.
void ast_autochan_destroy(struct ast_autochan *autochan)
destroy an ast_autochan structure
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_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
struct ast_autochan * ast_autochan_setup(struct ast_channel *chan)
set up a new ast_autochan structure
void ast_deactivate_generator(struct ast_channel *chan)
struct ast_audiohook_options options
struct ast_frame * ast_audiohook_read_frame_all(struct ast_audiohook *audiohook, size_t samples, struct ast_format *format, struct ast_frame **read_frame, struct ast_frame **write_frame)
Reads a frame in from the audiohook structure in mixed audio mode and copies read and write frame dat...
#define ast_channel_ref(c)
Increase channel reference count.
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
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_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
A multi channel blob data structure for multi_channel_blob stasis messages.
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
int ast_answer(struct ast_channel *chan)
Answer a channel.
Data structure associated with a single frame of data.
Abstract JSON element (object, array, string, int, ...).
Options provided by main asterisk program.
enum ast_audiohook_status status
enum ast_frame_type frametype
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
struct ast_format * format
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
Say numbers and dates (maybe words one day too)
#define ASTERISK_GPL_KEY
The text the key() function should return.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
#define ast_audiohook_lock(ah)
Lock an audiohook.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ast_frame * ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format)
Reads a frame in from the audiohook structure.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
struct ast_multi_channel_blob * ast_multi_channel_blob_create(struct ast_json *blob)
Create a ast_multi_channel_blob suitable for a stasis_message.
struct stasis_message_type * ast_channel_chanspy_stop_type(void)
Message type for when a channel stops spying on another channel.
void ast_frame_free(struct ast_frame *frame, int cache)
Frees a frame or list of frames.
#define AST_APP_ARG(name)
Define an application argument.