Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
res_agi.c File Reference

AGI - the Asterisk Gateway Interface. More...

#include "asterisk.h"
#include <math.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <pthread.h>
#include "asterisk/paths.h"
#include "asterisk/network.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/astdb.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/image.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/strings.h"
#include "asterisk/manager.h"
#include "asterisk/ast_version.h"
#include "asterisk/speech.h"
#include "asterisk/term.h"
#include "asterisk/xmldoc.h"
#include "asterisk/srv.h"
#include "asterisk/test.h"
#include "asterisk/netsock2.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/format_cache.h"
#include "asterisk/agi.h"
Include dependency graph for res_agi.c:

Go to the source code of this file.

Data Structures

struct  agi_cmd
 
struct  agi_commands
 

Macros

#define AGI_BUF_INITSIZE   256
 
#define AGI_BUF_LEN   2048
 
#define AGI_BUF_SIZE   1024
 
#define AGI_NANDFS_RETRY   3
 
#define AGI_PORT   4573
 
#define AMI_BUF_SIZE   2048
 
#define AST_API_MODULE
 
#define ASYNC_AGI_BREAK   3
 
#define MAX_AGI_CONNECT   2000
 
#define MAX_ARGS   128
 
#define MAX_CMD_LEN   80
 
#define SRV_PREFIX   "_agi._tcp."
 
#define TONE_BLOCK_SIZE   200
 

Enumerations

enum  agi_result {
  AGI_RESULT_FAILURE = -1, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_FAST, AGI_RESULT_SUCCESS_ASYNC,
  AGI_RESULT_NOTFOUND, AGI_RESULT_HANGUP
}
 

Functions

static void __init_agi_buf (void)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int action_add_agi_cmd (struct mansession *s, const struct message *m)
 Add a new command to execute by the Async AGI application. More...
 
static int add_agi_cmd (struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
 
static int add_to_agi (struct ast_channel *chan)
 
static struct ast_manager_event_blobagi_async_end_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobagi_async_exec_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobagi_async_start_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobagi_channel_to_ami (const char *type, struct stasis_message *message)
 
static void agi_destroy_commands_cb (void *data)
 
static int agi_exec (struct ast_channel *chan, const char *data)
 
static struct ast_manager_event_blobagi_exec_end_to_ami (struct stasis_message *message)
 
static int agi_exec_full (struct ast_channel *chan, const char *data, int enhanced, int dead)
 
static struct ast_manager_event_blobagi_exec_start_to_ami (struct stasis_message *message)
 
static enum agi_result agi_handle_command (struct ast_channel *chan, AGI *agi, char *buf, int dead)
 
int AST_OPTIONAL_API_NAME() ast_agi_register (struct ast_module *mod, agi_command *cmd)
 
int AST_OPTIONAL_API_NAME() ast_agi_register_multiple (struct ast_module *mod, struct agi_command *cmd, unsigned int len)
 
int AST_OPTIONAL_API_NAME() ast_agi_send (int fd, struct ast_channel *chan, char *fmt,...)
 
int AST_OPTIONAL_API_NAME() ast_agi_unregister (agi_command *cmd)
 
int AST_OPTIONAL_API_NAME() ast_agi_unregister_multiple (struct agi_command *cmd, unsigned int len)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (test_agi_null_docs)
 
static enum agi_result async_agi_read_frame (struct ast_channel *chan)
 
static int deadagi_exec (struct ast_channel *chan, const char *data)
 
static int eagi_exec (struct ast_channel *chan, const char *data)
 
static agi_commandfind_command (const char *const cmds[], int exact)
 
static void free_agi_cmd (struct agi_cmd *cmd)
 
static int get_agi_cmd (struct ast_channel *chan, struct agi_cmd **cmd)
 Retrieve the list head to the requested channel's AGI datastore. More...
 
static int handle_answer (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_asyncagi_break (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_autohangup (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_channelstatus (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static char * handle_cli_agi_add_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to add applications to execute in Async AGI. More...
 
static char * handle_cli_agi_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_agi_dump_html (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_agi_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int handle_connection (const char *agiurl, const struct ast_sockaddr addr, const int netsockfd)
 
static int handle_controlstreamfile (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_dbdel (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_dbdeltree (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_dbget (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_dbput (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_exec (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_getdata (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_getoption (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 get option - really similar to the handle_streamfile, but with a timeout More...
 
static int handle_getvariable (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_getvariablefull (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_hangup (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_noop (struct ast_channel *chan, AGI *agi, int arg, const char *const argv[])
 
static int handle_recordfile (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_recvchar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_recvtext (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_sayalpha (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saydate (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saydatetime (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saydigits (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saynumber (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 Say number in various language syntaxes. More...
 
static int handle_sayphonetic (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saytime (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_sendimage (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_sendtext (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setcallerid (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setcontext (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setextension (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setmusic (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setpriority (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setvariable (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechactivategrammar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechcreate (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechdeactivategrammar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechdestroy (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechloadgrammar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechrecognize (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechset (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechunloadgrammar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_streamfile (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_tddmode (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_verbose (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_waitfordigit (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static char * help_workhorse (int fd, const char *const match[])
 
static enum agi_result launch_asyncagi (struct ast_channel *chan, int argc, char *argv[], int *efd)
 
static enum agi_result launch_ha_netscript (char *agiurl, char *argv[], int *fds)
 
static enum agi_result launch_netscript (char *agiurl, char *argv[], int *fds)
 
static enum agi_result launch_script (struct ast_channel *chan, char *script, int argc, char *argv[], int *fds, int *efd, int *opid)
 
static int load_module (void)
 
static int parse_args (char *s, int *max, const char *argv[])
 
static void publish_async_exec_end (struct ast_channel *chan, int command_id, const char *command, int result_code, const char *result)
 
static enum agi_result run_agi (struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
 
static void setup_env (struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
 
static int speech_streamfile (struct ast_channel *chan, const char *filename, const char *preflang, int offset)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (agi_exec_start_type,.to_ami=agi_exec_start_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (agi_exec_end_type,.to_ami=agi_exec_end_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (agi_async_start_type,.to_ami=agi_async_start_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (agi_async_exec_type,.to_ami=agi_async_exec_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (agi_async_end_type,.to_ami=agi_async_end_to_ami,)
 
static int unload_module (void)
 
static void write_html_escaped (FILE *htmlfile, char *str)
 Convert string to use HTML escaped characters. More...
 
static int write_htmldump (const char *filename)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk Gateway Interface (AGI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_speech", }
 
static struct ast_threadstorage agi_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_agi_buf , .custom_init = NULL , }
 
static struct agi_commands agi_commands = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static const struct ast_datastore_info agi_commands_datastore_info
 
static int agidebug = 0
 
static char * app = "AGI"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_agi []
 
static struct agi_command commands []
 AGI commands list. More...
 
static char * deadapp = "DeadAGI"
 
static char * eapp = "EAGI"
 

Detailed Description

AGI - the Asterisk Gateway Interface.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file res_agi.c.

Macro Definition Documentation

◆ AGI_BUF_INITSIZE

#define AGI_BUF_INITSIZE   256

Definition at line 1484 of file res_agi.c.

Referenced by ast_agi_send().

◆ AGI_BUF_LEN

#define AGI_BUF_LEN   2048

Definition at line 1391 of file res_agi.c.

Referenced by run_agi().

◆ AGI_BUF_SIZE

#define AGI_BUF_SIZE   1024

Referenced by launch_asyncagi().

◆ AGI_NANDFS_RETRY

#define AGI_NANDFS_RETRY   3

Definition at line 1390 of file res_agi.c.

Referenced by run_agi().

◆ AGI_PORT

#define AGI_PORT   4573

Definition at line 1407 of file res_agi.c.

Referenced by launch_netscript().

◆ AMI_BUF_SIZE

#define AMI_BUF_SIZE   2048

Referenced by launch_asyncagi().

◆ AST_API_MODULE

#define AST_API_MODULE

Definition at line 71 of file res_agi.c.

◆ ASYNC_AGI_BREAK

#define ASYNC_AGI_BREAK   3

Special return code for "asyncagi break" command.

Definition at line 1410 of file res_agi.c.

Referenced by agi_handle_command(), and handle_asyncagi_break().

◆ MAX_AGI_CONNECT

#define MAX_AGI_CONNECT   2000

Definition at line 1405 of file res_agi.c.

Referenced by handle_connection().

◆ MAX_ARGS

#define MAX_ARGS   128

Definition at line 1388 of file res_agi.c.

Referenced by agi_exec_full(), agi_handle_command(), and parse_args().

◆ MAX_CMD_LEN

#define MAX_CMD_LEN   80

◆ SRV_PREFIX

#define SRV_PREFIX   "_agi._tcp."

Definition at line 1392 of file res_agi.c.

Referenced by launch_ha_netscript().

◆ TONE_BLOCK_SIZE

#define TONE_BLOCK_SIZE   200

Definition at line 1402 of file res_agi.c.

Enumeration Type Documentation

◆ agi_result

enum agi_result
Enumerator
AGI_RESULT_FAILURE 
AGI_RESULT_SUCCESS 
AGI_RESULT_SUCCESS_FAST 
AGI_RESULT_SUCCESS_ASYNC 
AGI_RESULT_NOTFOUND 
AGI_RESULT_HANGUP 

Definition at line 1412 of file res_agi.c.

Function Documentation

◆ __init_agi_buf()

static void __init_agi_buf ( void  )
static

Definition at line 1483 of file res_agi.c.

1487 {

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4715 of file res_agi.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4715 of file res_agi.c.

◆ action_add_agi_cmd()

static int action_add_agi_cmd ( struct mansession s,
const struct message m 
)
static

Add a new command to execute by the Async AGI application.

Parameters
s
mIt will append the application to the specified channel's queue if the channel is not inside Async AGI application it will return an error
Return values
0on success or incorrect use
1on failure to add the command ( most likely because the channel is not in Async AGI loop )

Definition at line 1709 of file res_agi.c.

References add_agi_cmd(), agi_handle_command(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), buf, request(), and setup_env().

Referenced by load_module().

1710 {
1711  const char *channel = astman_get_header(m, "Channel");
1712  const char *cmdbuff = astman_get_header(m, "Command");
1713  const char *cmdid = astman_get_header(m, "CommandID");
1714  struct ast_channel *chan;
1715  char buf[256];
1716 
1717  if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) {
1718  astman_send_error(s, m, "Both, Channel and Command are *required*");
1719  return 0;
1720  }
1721 
1722  if (!(chan = ast_channel_get_by_name(channel))) {
1723  snprintf(buf, sizeof(buf), "Channel %s does not exist.", channel);
1724  astman_send_error(s, m, buf);
1725  return 0;
1726  }
1727 
1728  ast_channel_lock(chan);
1729 
1730  if (add_agi_cmd(chan, cmdbuff, cmdid)) {
1731  snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", ast_channel_name(chan));
1732  astman_send_error(s, m, buf);
1733  ast_channel_unlock(chan);
1734  chan = ast_channel_unref(chan);
1735  return 0;
1736  }
1737 
1738  ast_channel_unlock(chan);
1739  chan = ast_channel_unref(chan);
1740 
1741  astman_send_ack(s, m, "Added AGI command to queue");
1742 
1743  return 0;
1744 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
Definition: res_agi.c:1580
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_channel_unlock(chan)
Definition: channel.h:2946
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ add_agi_cmd()

static int add_agi_cmd ( struct ast_channel chan,
const char *  cmd_buff,
const char *  cmd_id 
)
static

Definition at line 1580 of file res_agi.c.

References agi_commands, ast_calloc, ast_channel_datastore_find(), ast_channel_name(), ast_free, AST_LIST_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_strdup, agi_cmd::cmd_buffer, agi_cmd::cmd_id, ast_datastore::data, LOG_WARNING, and NULL.

Referenced by action_add_agi_cmd(), and handle_cli_agi_add_cmd().

1581 {
1582  struct ast_datastore *store;
1583  struct agi_cmd *cmd;
1585 
1587  if (!store) {
1588  ast_log(LOG_WARNING, "Channel %s is not setup for Async AGI.\n", ast_channel_name(chan));
1589  return -1;
1590  }
1591  agi_commands = store->data;
1592  cmd = ast_calloc(1, sizeof(*cmd));
1593  if (!cmd) {
1594  return -1;
1595  }
1596  cmd->cmd_buffer = ast_strdup(cmd_buff);
1597  if (!cmd->cmd_buffer) {
1598  ast_free(cmd);
1599  return -1;
1600  }
1601  cmd->cmd_id = ast_strdup(cmd_id);
1602  if (!cmd->cmd_id) {
1603  ast_free(cmd->cmd_buffer);
1604  ast_free(cmd);
1605  return -1;
1606  }
1610  return 0;
1611 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
char * cmd_id
Definition: res_agi.c:1518
#define ast_log
Definition: astobj2.c:42
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static const struct ast_datastore_info agi_commands_datastore_info
Definition: res_agi.c:1544
static struct agi_commands agi_commands
void * data
Definition: datastore.h:70
char * cmd_buffer
Definition: res_agi.c:1517
const char * ast_channel_name(const struct ast_channel *chan)
Definition: search.h:40

◆ add_to_agi()

static int add_to_agi ( struct ast_channel chan)
static

Definition at line 1613 of file res_agi.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, ast_log, ast_datastore::data, LOG_ERROR, and NULL.

Referenced by launch_asyncagi().

1614 {
1615  struct ast_datastore *datastore;
1616  AST_LIST_HEAD(, agi_cmd) *agi_cmds_list;
1617 
1618  /* check if already on AGI */
1619  ast_channel_lock(chan);
1621  ast_channel_unlock(chan);
1622  if (datastore) {
1623  /* we already have an AGI datastore, let's just
1624  return success */
1625  return 0;
1626  }
1627 
1628  /* the channel has never been on Async AGI,
1629  let's allocate it's datastore */
1630  datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI");
1631  if (!datastore) {
1632  return -1;
1633  }
1634  agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list));
1635  if (!agi_cmds_list) {
1636  ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n");
1637  ast_datastore_free(datastore);
1638  return -1;
1639  }
1640  datastore->data = agi_cmds_list;
1641  AST_LIST_HEAD_INIT(agi_cmds_list);
1642  ast_channel_lock(chan);
1643  ast_channel_datastore_add(chan, datastore);
1644  ast_channel_unlock(chan);
1645  return 0;
1646 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:625
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static const struct ast_datastore_info agi_commands_datastore_info
Definition: res_agi.c:1544
void * data
Definition: datastore.h:70
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ agi_async_end_to_ami()

static struct ast_manager_event_blob* agi_async_end_to_ami ( struct stasis_message message)
static

Definition at line 1460 of file res_agi.c.

References agi_async_exec_to_ami(), agi_async_start_to_ami(), agi_channel_to_ami(), agi_exec_end_to_ami(), agi_exec_start_to_ami(), find_command(), STASIS_MESSAGE_TYPE_DEFN_LOCAL(), and to_ami().

1461 {
1462  return agi_channel_to_ami("AsyncAGIEnd", message);
1463 }
static struct ast_manager_event_blob * agi_channel_to_ami(const char *type, struct stasis_message *message)
Definition: res_agi.c:1421

◆ agi_async_exec_to_ami()

static struct ast_manager_event_blob* agi_async_exec_to_ami ( struct stasis_message message)
static

Definition at line 1455 of file res_agi.c.

References agi_channel_to_ami().

Referenced by agi_async_end_to_ami().

1456 {
1457  return agi_channel_to_ami("AsyncAGIExec", message);
1458 }
static struct ast_manager_event_blob * agi_channel_to_ami(const char *type, struct stasis_message *message)
Definition: res_agi.c:1421

◆ agi_async_start_to_ami()

static struct ast_manager_event_blob* agi_async_start_to_ami ( struct stasis_message message)
static

Definition at line 1450 of file res_agi.c.

References agi_channel_to_ami().

Referenced by agi_async_end_to_ami().

1451 {
1452  return agi_channel_to_ami("AsyncAGIStart", message);
1453 }
static struct ast_manager_event_blob * agi_channel_to_ami(const char *type, struct stasis_message *message)
Definition: res_agi.c:1421

◆ agi_channel_to_ami()

static struct ast_manager_event_blob* agi_channel_to_ami ( const char *  type,
struct stasis_message message 
)
static

Definition at line 1421 of file res_agi.c.

References ast_free, ast_manager_build_channel_state_string(), ast_manager_event_blob_create(), ast_manager_str_from_json_object(), ast_str_buffer(), ast_channel_blob::blob, EVENT_FLAG_AGI, NULL, RAII_VAR, ast_channel_blob::snapshot, and stasis_message_data().

Referenced by agi_async_end_to_ami(), agi_async_exec_to_ami(), agi_async_start_to_ami(), agi_exec_end_to_ami(), and agi_exec_start_to_ami().

1422 {
1423  struct ast_channel_blob *obj = stasis_message_data(message);
1424  RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1425  RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
1426 
1427  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1428  event_string = ast_manager_str_from_json_object(obj->blob, NULL);
1429  if (!channel_string || !event_string) {
1430  return NULL;
1431  }
1432 
1434  "%s"
1435  "%s",
1436  ast_str_buffer(channel_string),
1437  ast_str_buffer(event_string));
1438 }
static const char type[]
Definition: chan_ooh323.c:109
struct ast_json * blob
struct ast_channel_snapshot * snapshot
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define NULL
Definition: resample.c:96
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:9727
Blob of data associated with a channel.
struct ast_str * ast_manager_str_from_json_object(struct ast_json *blob, key_exclusion_cb exclusion_cb)
Convert a JSON object into an AMI compatible string.
Definition: manager.c:1821
#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:911
#define EVENT_FLAG_AGI
Definition: manager.h:84
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
#define ast_free(a)
Definition: astmm.h:182

◆ agi_destroy_commands_cb()

static void agi_destroy_commands_cb ( void *  data)
static

Definition at line 1530 of file res_agi.c.

References ast_free, AST_LIST_HEAD, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and free_agi_cmd().

1531 {
1532  struct agi_cmd *cmd;
1533  AST_LIST_HEAD(, agi_cmd) *chan_cmds = data;
1534  AST_LIST_LOCK(chan_cmds);
1535  while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) {
1536  free_agi_cmd(cmd);
1537  }
1538  AST_LIST_UNLOCK(chan_cmds);
1539  AST_LIST_HEAD_DESTROY(chan_cmds);
1540  ast_free(chan_cmds);
1541 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:652
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define ast_free(a)
Definition: astmm.h:182
static void free_agi_cmd(struct agi_cmd *cmd)
Definition: res_agi.c:1522
Definition: search.h:40

◆ agi_exec()

static int agi_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 4561 of file res_agi.c.

References agi_exec_full(), and ast_check_hangup().

Referenced by deadagi_exec(), and load_module().

4562 {
4563  if (!ast_check_hangup(chan))
4564  return agi_exec_full(chan, data, 0, 0);
4565  else
4566  return agi_exec_full(chan, data, 0, 1);
4567 }
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
static int agi_exec_full(struct ast_channel *chan, const char *data, int enhanced, int dead)
Definition: res_agi.c:4494

◆ agi_exec_end_to_ami()

static struct ast_manager_event_blob* agi_exec_end_to_ami ( struct stasis_message message)
static

Definition at line 1445 of file res_agi.c.

References agi_channel_to_ami().

Referenced by agi_async_end_to_ami().

1446 {
1447  return agi_channel_to_ami("AGIExecEnd", message);
1448 }
static struct ast_manager_event_blob * agi_channel_to_ami(const char *type, struct stasis_message *message)
Definition: res_agi.c:1421

◆ agi_exec_full()

static int agi_exec_full ( struct ast_channel chan,
const char *  data,
int  enhanced,
int  dead 
)
static

Definition at line 4494 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_NOTFOUND, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, AGI_RESULT_SUCCESS_FAST, args, ast_answer(), AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_log, ast_safe_fork_cleanup(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero, buf, launch_script(), LOG_WARNING, MAX_ARGS, NULL, pbx_builtin_setvar_helper(), run_agi(), and status.

Referenced by agi_exec(), and eagi_exec().

4495 {
4496  enum agi_result res;
4497  char *buf;
4498  int fds[2], efd = -1, pid = -1;
4500  AST_APP_ARG(arg)[MAX_ARGS];
4501  );
4502  AGI agi;
4503 
4504  if (ast_strlen_zero(data)) {
4505  ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
4506  return -1;
4507  }
4508  if (dead)
4509  ast_debug(3, "Hungup channel detected, running agi in dead mode.\n");
4510  memset(&agi, 0, sizeof(agi));
4511  buf = ast_strdupa(data);
4513  args.arg[args.argc] = NULL;
4514 #if 0
4515  /* Answer if need be */
4516  if (chan->_state != AST_STATE_UP) {
4517  if (ast_answer(chan))
4518  return -1;
4519  }
4520 #endif
4521  res = launch_script(chan, args.arg[0], args.argc, args.arg, fds, enhanced ? &efd : NULL, &pid);
4522  /* Async AGI do not require run_agi(), so just proceed if normal AGI
4523  or Fast AGI are setup with success. */
4524  if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
4525  int status = 0;
4526  agi.fd = fds[1];
4527  agi.ctrl = fds[0];
4528  agi.audio = efd;
4529  agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
4530  res = run_agi(chan, args.arg[0], &agi, pid, &status, dead, args.argc, args.arg);
4531  /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
4532  if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status)
4533  res = AGI_RESULT_FAILURE;
4534  if (fds[1] != fds[0])
4535  close(fds[1]);
4536  if (efd > -1)
4537  close(efd);
4538  }
4540 
4541  switch (res) {
4542  case AGI_RESULT_SUCCESS:
4545  pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
4546  break;
4547  case AGI_RESULT_FAILURE:
4548  pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE");
4549  break;
4550  case AGI_RESULT_NOTFOUND:
4551  pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND");
4552  break;
4553  case AGI_RESULT_HANGUP:
4554  pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP");
4555  return -1;
4556  }
4557 
4558  return 0;
4559 }
agi_result
Definition: res_agi.c:1412
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
const char * args
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
void ast_safe_fork_cleanup(void)
Common routine to cleanup after fork&#39;ed process is complete (if reaping was stopped) ...
Definition: main/app.c:3108
static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
Definition: res_agi.c:4112
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static enum agi_result launch_script(struct ast_channel *chan, char *script, int argc, char *argv[], int *fds, int *efd, int *opid)
Definition: res_agi.c:2200
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_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
#define MAX_ARGS
Definition: res_agi.c:1388
Definition: agi.h:34
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
jack_status_t status
Definition: app_jack.c:146
#define AST_APP_ARG(name)
Define an application argument.

◆ agi_exec_start_to_ami()

static struct ast_manager_event_blob* agi_exec_start_to_ami ( struct stasis_message message)
static

Definition at line 1440 of file res_agi.c.

References agi_channel_to_ami().

Referenced by agi_async_end_to_ami().

1441 {
1442  return agi_channel_to_ami("AGIExecStart", message);
1443 }
static struct ast_manager_event_blob * agi_channel_to_ami(const char *type, struct stasis_message *message)
Definition: res_agi.c:1421

◆ agi_handle_command()

static enum agi_result agi_handle_command ( struct ast_channel chan,
AGI agi,
char *  buf,
int  dead 
)
static

Definition at line 4021 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, ast_agi_send(), ast_channel_publish_cached_blob(), ast_json_pack(), ast_json_unref(), ast_module_running_ref, ast_module_unref, ast_random(), ast_strdupa, ast_strlen_zero, ASYNC_AGI_BREAK, c, agi_command::dead, agi_state::fd, find_command(), agi_command::handler, MAX_ARGS, agi_command::mod, NULL, parse_args(), publish_async_exec_end(), RAII_VAR, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.

Referenced by action_add_agi_cmd(), launch_asyncagi(), and run_agi().

4022 {
4023  const char *argv[MAX_ARGS] = {0};
4024  int argc = MAX_ARGS;
4025  int res;
4026  agi_command *c;
4027  char *ami_cmd = ast_strdupa(buf);
4028  const char *ami_res;
4029  int command_id = ast_random();
4030  int resultcode = 0;
4031  RAII_VAR(struct ast_json *, startblob, NULL, ast_json_unref);
4032 
4033  startblob = ast_json_pack("{s: i, s: s}",
4034  "CommandId", command_id,
4035  "Command", ami_cmd);
4036  ast_channel_publish_cached_blob(chan, agi_exec_start_type(), startblob);
4037 
4038  parse_args(buf, &argc, argv);
4039  c = find_command(argv, 0);
4040  if (!c || !ast_module_running_ref(c->mod)) {
4041  ami_res = "Invalid or unknown command";
4042  resultcode = 510;
4043 
4044  ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
4045 
4046  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4047 
4048  return AGI_RESULT_SUCCESS;
4049  }
4050 
4051  if (!dead || (dead && c->dead)) {
4052  res = c->handler(chan, agi, argc, argv);
4053  switch (res) {
4054  case RESULT_SHOWUSAGE:
4055  ami_res = "Usage";
4056  resultcode = 520;
4057 
4058  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4059 
4060  if (ast_strlen_zero(c->usage)) {
4061  ast_agi_send(agi->fd, chan, "520 Invalid command syntax. Proper usage not available.\n");
4062  } else {
4063  ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n");
4064  ast_agi_send(agi->fd, chan, "%s\n", c->usage);
4065  ast_agi_send(agi->fd, chan, "520 End of proper usage.\n");
4066  }
4067 
4068  break;
4069  case RESULT_FAILURE:
4070  ami_res = "Failure";
4071  resultcode = -1;
4072 
4073  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4074 
4075  /* The RESULT_FAILURE code is usually because the channel hungup. */
4076  return AGI_RESULT_FAILURE;
4077  case ASYNC_AGI_BREAK:
4078  ami_res = "Success";
4079  resultcode = 200;
4080 
4081  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4082 
4083  return AGI_RESULT_SUCCESS_ASYNC;
4084  case RESULT_SUCCESS:
4085  ami_res = "Success";
4086  resultcode = 200;
4087 
4088  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4089 
4090  break;
4091  default:
4092  ami_res = "Unknown Result";
4093  resultcode = 200;
4094 
4095  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4096 
4097  break;
4098  }
4099  } else {
4100  ami_res = "Command Not Permitted on a dead channel or intercept routine";
4101  resultcode = 511;
4102 
4103  ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
4104 
4105  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4106  }
4107  ast_module_unref(c->mod);
4108 
4109  return AGI_RESULT_SUCCESS;
4110 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
static int parse_args(char *s, int *max, const char *argv[])
Definition: res_agi.c:3947
int(*const handler)(struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
Definition: agi.h:46
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define RESULT_SHOWUSAGE
Definition: cli.h:41
void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message using the latest snapshot from the cache.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const char *const usage
Definition: agi.h:50
struct ast_module * mod
Definition: agi.h:60
static void publish_async_exec_end(struct ast_channel *chan, int command_id, const char *command, int result_code, const char *result)
Definition: res_agi.c:4010
static agi_command * find_command(const char *const cmds[], int exact)
Definition: res_agi.c:3909
static struct test_val c
#define NULL
Definition: resample.c:96
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
#define ast_strlen_zero(foo)
Definition: strings.h:52
const int dead
Definition: agi.h:52
#define ASYNC_AGI_BREAK
Definition: res_agi.c:1410
#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:911
long int ast_random(void)
Definition: main/utils.c:2064
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int fd
Definition: agi.h:35
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:455
#define MAX_ARGS
Definition: res_agi.c:1388
Abstract JSON element (object, array, string, int, ...).
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ ast_agi_register()

int AST_OPTIONAL_API_NAME() ast_agi_register ( struct ast_module mod,
agi_command cmd 
)

Definition at line 3783 of file res_agi.c.

References ast_join, AST_LIST_INSERT_TAIL, ast_log, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_strdup, ast_strlen_zero, ast_verb, AST_XML_DOC, ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), find_command(), LOG_WARNING, MAX_CMD_LEN, and NULL.

Referenced by ast_agi_register_multiple(), AST_TEST_DEFINE(), and load_module().

3784 {
3785  char fullcmd[MAX_CMD_LEN];
3786 
3787  ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3788 
3789  if (!find_command(cmd->cmda, 1)) {
3790  *((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC;
3791  if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
3792 #ifdef AST_XML_DOCS
3793  *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd, NULL);
3794  *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd, NULL);
3795  *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd, NULL);
3796  *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd, NULL);
3797  *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
3798 #endif
3799 #ifndef HAVE_NULLSAFE_PRINTF
3800  if (!cmd->summary) {
3801  *((char **) &cmd->summary) = ast_strdup("");
3802  }
3803  if (!cmd->usage) {
3804  *((char **) &cmd->usage) = ast_strdup("");
3805  }
3806  if (!cmd->syntax) {
3807  *((char **) &cmd->syntax) = ast_strdup("");
3808  }
3809  if (!cmd->seealso) {
3810  *((char **) &cmd->seealso) = ast_strdup("");
3811  }
3812 #endif
3813  }
3814 
3815  cmd->mod = mod;
3817  AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
3819  ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
3820  return 1;
3821  } else {
3822  ast_log(LOG_WARNING, "Command already registered!\n");
3823  return 0;
3824  }
3825 }
const char *const summary
Definition: agi.h:48
const char *const seealso
Definition: agi.h:56
#define ast_join(s, len, w)
Definition: strings.h:483
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:274
const char *const usage
Definition: agi.h:50
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
Definition: xmldoc.c:2250
struct ast_module * mod
Definition: agi.h:60
static agi_command * find_command(const char *const cmds[], int exact)
Definition: res_agi.c:3909
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition: xmldoc.c:2227
ast_doc_src
From where the documentation come from, this structure is useful for use it inside application/functi...
Definition: xmldoc.h:30
#define ast_verb(level,...)
Definition: logger.h:463
#define MAX_CMD_LEN
Definition: res_agi.c:1389
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
const char *const syntax
Definition: agi.h:54
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
Definition: xmldoc.c:1253
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the <see-also> node content.
Definition: xmldoc.c:1698
enum ast_doc_src docsrc
Definition: agi.h:58

◆ ast_agi_register_multiple()

int AST_OPTIONAL_API_NAME() ast_agi_register_multiple ( struct ast_module mod,
struct agi_command cmd,
unsigned int  len 
)

Definition at line 3863 of file res_agi.c.

References ast_agi_register(), ast_agi_unregister(), and len().

Referenced by __stub__ast_agi_unregister(), and load_module().

3864 {
3865  unsigned int i, x = 0;
3866 
3867  for (i = 0; i < len; i++) {
3868  if (ast_agi_register(mod, cmd + i) == 1) {
3869  x++;
3870  continue;
3871  }
3872 
3873  /* registration failed, unregister everything
3874  that had been registered up to that point
3875  */
3876  for (; x > 0; x--) {
3877  /* we are intentionally ignoring the
3878  result of ast_agi_unregister() here,
3879  but it should be safe to do so since
3880  we just registered these commands and
3881  the only possible way for unregistration
3882  to fail is if the command is not
3883  registered
3884  */
3885  (void) ast_agi_unregister(cmd + x - 1);
3886  }
3887  return -1;
3888  }
3889 
3890  return 0;
3891 }
int AST_OPTIONAL_API_NAME() ast_agi_unregister(agi_command *cmd)
Definition: res_agi.c:3827
int AST_OPTIONAL_API_NAME() ast_agi_register(struct ast_module *mod, agi_command *cmd)
Definition: res_agi.c:3783
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ ast_agi_send()

int AST_OPTIONAL_API_NAME() ast_agi_send ( int  fd,
struct ast_channel chan,
char *  fmt,
  ... 
)

Definition at line 1486 of file res_agi.c.

References agi_buf, AGI_BUF_INITSIZE, agidebug, ast_carefulwrite(), ast_channel_name(), ast_log, ast_str_buffer(), ast_str_set_va(), ast_str_strlen(), ast_str_thread_get(), ast_verbose(), buf, and LOG_ERROR.

Referenced by __stub__ast_agi_unregister_multiple(), agi_handle_command(), handle_answer(), handle_asyncagi_break(), handle_autohangup(), handle_channelstatus(), handle_controlstreamfile(), handle_dbdel(), handle_dbdeltree(), handle_dbget(), handle_dbput(), handle_exec(), handle_getdata(), handle_getoption(), handle_getvariable(), handle_getvariablefull(), handle_gosub(), handle_hangup(), handle_noop(), handle_recordfile(), handle_recvchar(), handle_recvtext(), handle_sayalpha(), handle_saydate(), handle_saydatetime(), handle_saydigits(), handle_saynumber(), handle_sayphonetic(), handle_saytime(), handle_sendimage(), handle_sendtext(), handle_setcallerid(), handle_setcontext(), handle_setextension(), handle_setmusic(), handle_setpriority(), handle_setvariable(), handle_speechactivategrammar(), handle_speechcreate(), handle_speechdeactivategrammar(), handle_speechdestroy(), handle_speechloadgrammar(), handle_speechrecognize(), handle_speechset(), handle_speechunloadgrammar(), handle_streamfile(), handle_tddmode(), handle_verbose(), handle_waitfordigit(), launch_netscript(), run_agi(), and setup_env().

1487 {
1488  int res = 0;
1489  va_list ap;
1490  struct ast_str *buf;
1491 
1493  return -1;
1494 
1495  va_start(ap, fmt);
1496  res = ast_str_set_va(&buf, 0, fmt, ap);
1497  va_end(ap);
1498 
1499  if (res == -1) {
1500  ast_log(LOG_ERROR, "Out of memory\n");
1501  return -1;
1502  }
1503 
1504  if (agidebug) {
1505  if (chan) {
1506  ast_verbose("<%s>AGI Tx >> %s", ast_channel_name(chan), ast_str_buffer(buf));
1507  } else {
1508  ast_verbose("AGI Tx >> %s", ast_str_buffer(buf));
1509  }
1510  }
1511 
1512  return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
1513 }
static int agidebug
Definition: res_agi.c:1400
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
Try to write string, but wait no more than ms milliseconds before timing out.
Definition: main/utils.c:1592
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
Definition: strings.h:982
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define AGI_BUF_INITSIZE
Definition: res_agi.c:1484
static struct ast_threadstorage agi_buf
Definition: res_agi.c:1483
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861

◆ ast_agi_unregister()

int AST_OPTIONAL_API_NAME() ast_agi_unregister ( agi_command cmd)

Definition at line 3827 of file res_agi.c.

References ast_free, ast_join, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, AST_XML_DOC, agi_command::docsrc, agi_command::list, MAX_CMD_LEN, NULL, agi_command::seealso, agi_command::summary, agi_command::syntax, and agi_command::usage.

Referenced by __stub__ast_agi_register(), ast_agi_register_multiple(), ast_agi_unregister_multiple(), AST_TEST_DEFINE(), and unload_module().

3828 {
3829  struct agi_command *e;
3830  int unregistered = 0;
3831  char fullcmd[MAX_CMD_LEN];
3832 
3833  ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3834 
3837  if (cmd == e) {
3839 #ifdef AST_XML_DOCS
3840  if (e->docsrc == AST_XML_DOC) {
3841  ast_free((char *) e->summary);
3842  ast_free((char *) e->usage);
3843  ast_free((char *) e->syntax);
3844  ast_free((char *) e->seealso);
3845  *((char **) &e->summary) = NULL;
3846  *((char **) &e->usage) = NULL;
3847  *((char **) &e->syntax) = NULL;
3848  *((char **) &e->seealso) = NULL;
3849  }
3850 #endif
3851  unregistered=1;
3852  break;
3853  }
3854  }
3857  if (unregistered) {
3858  ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd);
3859  }
3860  return unregistered;
3861 }
const char *const summary
Definition: agi.h:48
const char *const seealso
Definition: agi.h:56
#define ast_join(s, len, w)
Definition: strings.h:483
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const char *const usage
Definition: agi.h:50
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define MAX_CMD_LEN
Definition: res_agi.c:1389
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
const char *const syntax
Definition: agi.h:54
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
#define ast_free(a)
Definition: astmm.h:182
struct agi_command::@219 list
enum ast_doc_src docsrc
Definition: agi.h:58
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ ast_agi_unregister_multiple()

int AST_OPTIONAL_API_NAME() ast_agi_unregister_multiple ( struct agi_command cmd,
unsigned int  len 
)

Definition at line 3893 of file res_agi.c.

References ast_agi_unregister(), and len().

Referenced by __stub__ast_agi_register_multiple(), and unload_module().

3894 {
3895  unsigned int i;
3896  int res = 0;
3897 
3898  for (i = 0; i < len; i++) {
3899  /* remember whether any of the unregistration
3900  attempts failed... there is no recourse if
3901  any of them do
3902  */
3903  res |= ast_agi_unregister(cmd + i);
3904  }
3905 
3906  return res;
3907 }
int AST_OPTIONAL_API_NAME() ast_agi_unregister(agi_command *cmd)
Definition: res_agi.c:3827
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 4715 of file res_agi.c.

◆ AST_TEST_DEFINE()

AST_TEST_DEFINE ( test_agi_null_docs  )

Definition at line 4625 of file res_agi.c.

References ast_agi_register(), ast_agi_unregister(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, handle_noop(), sip_to_pjsip::info(), NULL, ast_module_info::self, agi_command::syntax, TEST_EXECUTE, TEST_INIT, and agi_command::usage.

4626 {
4627  int res = AST_TEST_PASS;
4628  struct agi_command noop_command =
4629  { { "testnoop", NULL }, handle_noop, NULL, NULL, 0 };
4630 
4631  switch (cmd) {
4632  case TEST_INIT:
4633  info->name = "null_agi_docs";
4634  info->category = "/res/agi/";
4635  info->summary = "AGI command with no documentation";
4636  info->description = "Test whether an AGI command with no documentation will crash Asterisk";
4637  return AST_TEST_NOT_RUN;
4638  case TEST_EXECUTE:
4639  break;
4640  }
4641 
4642  if (ast_agi_register(ast_module_info->self, &noop_command) == 0) {
4643  ast_test_status_update(test, "Unable to register testnoop command, because res_agi is not loaded.\n");
4644  return AST_TEST_NOT_RUN;
4645  }
4646 
4647 #ifndef HAVE_NULLSAFE_PRINTF
4648  /* Test for condition without actually crashing Asterisk */
4649  if (noop_command.usage == NULL) {
4650  ast_test_status_update(test, "AGI testnoop usage was not updated properly.\n");
4651  res = AST_TEST_FAIL;
4652  }
4653  if (noop_command.syntax == NULL) {
4654  ast_test_status_update(test, "AGI testnoop syntax was not updated properly.\n");
4655  res = AST_TEST_FAIL;
4656  }
4657 #endif
4658 
4659  ast_agi_unregister(&noop_command);
4660  return res;
4661 }
int AST_OPTIONAL_API_NAME() ast_agi_unregister(agi_command *cmd)
Definition: res_agi.c:3827
const char *const usage
Definition: agi.h:50
#define NULL
Definition: resample.c:96
struct ast_module * self
Definition: module.h:342
int AST_OPTIONAL_API_NAME() ast_agi_register(struct ast_module *mod, agi_command *cmd)
Definition: res_agi.c:3783
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
const char *const syntax
Definition: agi.h:54
def info(msg)
static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char *const argv[])
Definition: res_agi.c:3391

◆ async_agi_read_frame()

static enum agi_result async_agi_read_frame ( struct ast_channel chan)
static

Definition at line 1759 of file res_agi.c.

References AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS, ast_channel_name(), AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CONTROL, ast_frfree, ast_read(), ast_frame::frametype, ast_frame_subclass::integer, and ast_frame::subclass.

Referenced by launch_asyncagi().

1760 {
1761  struct ast_frame *f;
1762 
1763  f = ast_read(chan);
1764  if (!f) {
1765  ast_debug(3, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
1766  return AGI_RESULT_HANGUP;
1767  }
1768  if (f->frametype == AST_FRAME_CONTROL) {
1769  /*
1770  * Is there any other frame we should care about besides
1771  * AST_CONTROL_HANGUP?
1772  */
1773  switch (f->subclass.integer) {
1774  case AST_CONTROL_HANGUP:
1775  ast_debug(3, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
1776  ast_frfree(f);
1777  return AGI_RESULT_HANGUP;
1778  default:
1779  break;
1780  }
1781  }
1782  ast_frfree(f);
1783 
1784  return AGI_RESULT_SUCCESS;
1785 }
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
struct ast_frame_subclass subclass
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
Data structure associated with a single frame of data.
enum ast_frame_type frametype

◆ deadagi_exec()

static int deadagi_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 4611 of file res_agi.c.

References agi_exec(), ast_log, and LOG_WARNING.

Referenced by load_module().

4612 {
4613  ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n");
4614  return agi_exec(chan, data);
4615 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
static int agi_exec(struct ast_channel *chan, const char *data)
Definition: res_agi.c:4561
union ast_frame::@263 data

◆ eagi_exec()

static int eagi_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 4569 of file res_agi.c.

References agi_exec_full(), ao2_bump, ao2_cleanup, ast_channel_name(), ast_channel_readformat(), ast_check_hangup(), ast_format_cache_get, ast_format_get_name(), ast_format_slin, ast_log, ast_set_read_format(), ast_verb, LOG_ERROR, LOG_WARNING, NULL, and pbx_builtin_getvar_helper().

Referenced by load_module().

4570 {
4571  int res;
4572  struct ast_format *readformat;
4573  struct ast_format *requested_format = NULL;
4574  const char *requested_format_name;
4575 
4576  if (ast_check_hangup(chan)) {
4577  ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n");
4578  return 0;
4579  }
4580 
4581  requested_format_name = pbx_builtin_getvar_helper(chan, "EAGI_AUDIO_FORMAT");
4582  if (requested_format_name) {
4583  requested_format = ast_format_cache_get(requested_format_name);
4584  if (requested_format) {
4585  ast_verb(3, "<%s> Setting EAGI audio pipe format to %s\n",
4586  ast_channel_name(chan), ast_format_get_name(requested_format));
4587  } else {
4588  ast_log(LOG_ERROR, "Could not find requested format: %s\n", requested_format_name);
4589  }
4590  }
4591 
4592  readformat = ao2_bump(ast_channel_readformat(chan));
4593  if (ast_set_read_format(chan, requested_format ?: ast_format_slin)) {
4594  ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", ast_channel_name(chan));
4595  ao2_cleanup(requested_format);
4596  ao2_cleanup(readformat);
4597  return -1;
4598  }
4599  res = agi_exec_full(chan, data, 1, 0);
4600  if (!res) {
4601  if (ast_set_read_format(chan, readformat)) {
4602  ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", ast_channel_name(chan),
4603  ast_format_get_name(readformat));
4604  }
4605  }
4606  ao2_cleanup(requested_format);
4607  ao2_cleanup(readformat);
4608  return res;
4609 }
#define LOG_WARNING
Definition: logger.h:274
Definition of a media format.
Definition: format.c:43
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_format_cache_get(name)
Definition: format_cache.h:286
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
static int agi_exec_full(struct ast_channel *chan, const char *data, int enhanced, int dead)
Definition: res_agi.c:4494
#define LOG_ERROR
Definition: logger.h:285
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41

◆ find_command()

static agi_command * find_command ( const char *const  cmds[],
int  exact 
)
static

Definition at line 3909 of file res_agi.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, agi_command::list, match(), and NULL.

Referenced by agi_async_end_to_ami(), agi_handle_command(), ast_agi_register(), and handle_cli_agi_show().

3910 {
3911  int y, match;
3912  struct agi_command *e;
3913 
3916  if (!e->cmda[0])
3917  break;
3918  /* start optimistic */
3919  match = 1;
3920  for (y = 0; match && cmds[y]; y++) {
3921  /* If there are no more words in the command (and we're looking for
3922  an exact match) or there is a difference between the two words,
3923  then this is not a match */
3924  if (!e->cmda[y] && !exact)
3925  break;
3926  /* don't segfault if the next part of a command doesn't exist */
3927  if (!e->cmda[y]) {
3929  return NULL;
3930  }
3931  if (strcasecmp(e->cmda[y], cmds[y]))
3932  match = 0;
3933  }
3934  /* If more words are needed to complete the command then this is not
3935  a candidate (unless we're looking for a really inexact answer */
3936  if ((exact > -1) && e->cmda[y])
3937  match = 0;
3938  if (match) {
3940  return e;
3941  }
3942  }
3944  return NULL;
3945 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
#define NULL
Definition: resample.c:96
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
struct agi_command::@219 list

◆ free_agi_cmd()

static void free_agi_cmd ( struct agi_cmd cmd)
static

Definition at line 1522 of file res_agi.c.

References ast_free, agi_cmd::cmd_buffer, and agi_cmd::cmd_id.

Referenced by agi_destroy_commands_cb(), and launch_asyncagi().

1523 {
1524  ast_free(cmd->cmd_buffer);
1525  ast_free(cmd->cmd_id);
1526  ast_free(cmd);
1527 }
char * cmd_id
Definition: res_agi.c:1518
#define ast_free(a)
Definition: astmm.h:182
char * cmd_buffer
Definition: res_agi.c:1517

◆ get_agi_cmd()

static int get_agi_cmd ( struct ast_channel chan,
struct agi_cmd **  cmd 
)
static

Retrieve the list head to the requested channel's AGI datastore.

Parameters
chanChannel datastore is requested for
cmdPointer to the struct pointer which will reference the head of the agi command list.
Return values
0if the datastore was valid and the list head was retrieved appropriately (even if it's NULL and the list is empty)
-1if the datastore could not be retrieved causing an error

Definition at line 1558 of file res_agi.c.

References agi_commands, ast_channel_datastore_find(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log, ast_datastore::data, LOG_ERROR, and NULL.

Referenced by launch_asyncagi().

1559 {
1560  struct ast_datastore *store;
1562 
1563  ast_channel_lock(chan);
1565  ast_channel_unlock(chan);
1566  if (!store) {
1567  ast_log(LOG_ERROR, "Huh? Async AGI datastore disappeared on Channel %s!\n",
1568  ast_channel_name(chan));
1569  *cmd = NULL;
1570  return -1;
1571  }
1572  agi_commands = store->data;
1576  return 0;
1577 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define LOG_ERROR
Definition: logger.h:285
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static const struct ast_datastore_info agi_commands_datastore_info
Definition: res_agi.c:1544
static struct agi_commands agi_commands
void * data
Definition: datastore.h:70
const char * ast_channel_name(const struct ast_channel *chan)
Definition: search.h:40

◆ handle_answer()

static int handle_answer ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2364 of file res_agi.c.

References ast_agi_send(), ast_answer(), AST_STATE_UP, agi_state::fd, RESULT_FAILURE, and RESULT_SUCCESS.

2365 {
2366  int res = 0;
2367 
2368  /* Answer the channel */
2369  if (ast_channel_state(chan) != AST_STATE_UP)
2370  res = ast_answer(chan);
2371 
2372  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2373  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2374 }
ast_channel_state
ast_channel states
Definition: channelstate.h:35
int fd
Definition: agi.h:35
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_asyncagi_break()

static int handle_asyncagi_break ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2376 of file res_agi.c.

References ast_agi_send(), ASYNC_AGI_BREAK, and agi_state::fd.

2377 {
2378  ast_agi_send(agi->fd, chan, "200 result=0\n");
2379  return ASYNC_AGI_BREAK;
2380 }
#define ASYNC_AGI_BREAK
Definition: res_agi.c:1410
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486

◆ handle_autohangup()

static int handle_autohangup ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3078 of file res_agi.c.

References ast_agi_send(), ast_channel_lock, ast_channel_setwhentohangup_tv(), ast_channel_unlock, agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and timeout.

3079 {
3080  double timeout;
3081  struct timeval whentohangup = { 0, 0 };
3082 
3083  if (argc != 3)
3084  return RESULT_SHOWUSAGE;
3085  if (sscanf(argv[2], "%30lf", &timeout) != 1)
3086  return RESULT_SHOWUSAGE;
3087  if (timeout < 0)
3088  timeout = 0;
3089  if (timeout) {
3090  whentohangup.tv_sec = timeout;
3091  whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
3092  }
3093  ast_channel_lock(chan);
3094  ast_channel_setwhentohangup_tv(chan, whentohangup);
3095  ast_channel_unlock(chan);
3096  ast_agi_send(agi->fd, chan, "200 result=0\n");
3097  return RESULT_SUCCESS;
3098 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
void ast_channel_setwhentohangup_tv(struct ast_channel *chan, struct timeval offset)
Set when to hang a channel up.
Definition: channel.c:510
#define RESULT_SHOWUSAGE
Definition: cli.h:41
static int timeout
Definition: cdr_mysql.c:86
int fd
Definition: agi.h:35
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_channelstatus()

static int handle_channelstatus ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3179 of file res_agi.c.

References ao2_ref, ast_agi_send(), ast_channel_snapshot_get_latest_by_name(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_channel_snapshot::state.

3180 {
3181  if (argc == 2) {
3182  /* no argument: supply info on the current channel */
3183  ast_agi_send(agi->fd, chan, "200 result=%u\n", ast_channel_state(chan));
3184  return RESULT_SUCCESS;
3185  } else if (argc == 3) {
3186  struct ast_channel_snapshot *snapshot;
3187 
3188  /* one argument: look for info on the specified channel */
3189  snapshot = ast_channel_snapshot_get_latest_by_name(argv[2]);
3190  if (snapshot) {
3191  ast_agi_send(agi->fd, chan, "200 result=%u\n", snapshot->state);
3192  ao2_ref(snapshot, -1);
3193  return RESULT_SUCCESS;
3194  }
3195  /* if we get this far no channel name matched the argument given */
3196  ast_agi_send(agi->fd, chan, "200 result=-1\n");
3197  return RESULT_SUCCESS;
3198  } else {
3199  return RESULT_SHOWUSAGE;
3200  }
3201 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
Structure representing a snapshot of channel state.
ast_channel_state
ast_channel states
Definition: channelstate.h:35
struct ast_channel_snapshot * ast_channel_snapshot_get_latest_by_name(const char *name)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int fd
Definition: agi.h:35
enum ast_channel_state state
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_cli_agi_add_cmd()

static char* handle_cli_agi_add_cmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

CLI command to add applications to execute in Async AGI.

Parameters
e
cmd
a
Return values
CLI_SUCCESSon success
NULLwhen init or tab completion is used

Definition at line 1657 of file res_agi.c.

References add_agi_cmd(), ast_cli_args::argc, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_cli(), ast_complete_channels(), ast_debug, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

1658 {
1659  struct ast_channel *chan;
1660  switch (cmd) {
1661  case CLI_INIT:
1662  e->command = "agi exec";
1663  e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n"
1664  " Add AGI command to the execute queue of the specified channel in Async AGI\n";
1665  return NULL;
1666  case CLI_GENERATE:
1667  if (a->pos == 2)
1668  return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
1669  return NULL;
1670  }
1671 
1672  if (a->argc < 4) {
1673  return CLI_SHOWUSAGE;
1674  }
1675 
1676  if (!(chan = ast_channel_get_by_name(a->argv[2]))) {
1677  ast_cli(a->fd, "Channel %s does not exist.\n", a->argv[2]);
1678  return CLI_FAILURE;
1679  }
1680 
1681  ast_channel_lock(chan);
1682 
1683  if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) {
1684  ast_cli(a->fd, "Failed to add AGI command to queue of channel %s\n", ast_channel_name(chan));
1685  ast_channel_unlock(chan);
1686  chan = ast_channel_unref(chan);
1687  return CLI_FAILURE;
1688  }
1689 
1690  ast_debug(1, "Added AGI command to channel %s queue\n", ast_channel_name(chan));
1691 
1692  ast_channel_unlock(chan);
1693  chan = ast_channel_unref(chan);
1694 
1695  return CLI_SUCCESS;
1696 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
const int argc
Definition: cli.h:160
static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
Definition: res_agi.c:1580
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * line
Definition: cli.h:162
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
const char * ast_channel_name(const struct ast_channel *chan)
const int pos
Definition: cli.h:164
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: main/cli.c:1830
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

◆ handle_cli_agi_debug()

static char* handle_cli_agi_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3362 of file res_agi.c.

References agidebug, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, and ast_cli_entry::usage.

3363 {
3364  switch (cmd) {
3365  case CLI_INIT:
3366  e->command = "agi set debug [on|off]";
3367  e->usage =
3368  "Usage: agi set debug [on|off]\n"
3369  " Enables/disables dumping of AGI transactions for\n"
3370  " debugging purposes.\n";
3371  return NULL;
3372 
3373  case CLI_GENERATE:
3374  return NULL;
3375  }
3376 
3377  if (a->argc != e->args)
3378  return CLI_SHOWUSAGE;
3379 
3380  if (strncasecmp(a->argv[3], "off", 3) == 0) {
3381  agidebug = 0;
3382  } else if (strncasecmp(a->argv[3], "on", 2) == 0) {
3383  agidebug = 1;
3384  } else {
3385  return CLI_SHOWUSAGE;
3386  }
3387  ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis");
3388  return CLI_SUCCESS;
3389 }
static int agidebug
Definition: res_agi.c:1400
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ handle_cli_agi_dump_html()

static char* handle_cli_agi_dump_html ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4470 of file res_agi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, ast_cli_entry::usage, and write_htmldump().

4471 {
4472  switch (cmd) {
4473  case CLI_INIT:
4474  e->command = "agi dump html";
4475  e->usage =
4476  "Usage: agi dump html <filename>\n"
4477  " Dumps the AGI command list in HTML format to the given\n"
4478  " file.\n";
4479  return NULL;
4480  case CLI_GENERATE:
4481  return NULL;
4482  }
4483  if (a->argc != e->args + 1)
4484  return CLI_SHOWUSAGE;
4485 
4486  if (write_htmldump(a->argv[e->args]) < 0) {
4487  ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]);
4488  return CLI_SHOWUSAGE;
4489  }
4490  ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]);
4491  return CLI_SUCCESS;
4492 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int write_htmldump(const char *filename)
Definition: res_agi.c:4418
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ handle_cli_agi_show()

static char* handle_cli_agi_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4284 of file res_agi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_free, ast_join, ast_malloc, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, agi_command::dead, agi_command::docsrc, error(), ast_cli_args::fd, find_command(), help_workhorse(), sip_to_pjsip::info(), MAX_CMD_LEN, NULL, S_OR, agi_command::seealso, agi_command::summary, synopsis, agi_command::syntax, term_color(), agi_command::usage, and ast_cli_entry::usage.

4285 {
4286  struct agi_command *command;
4287  char fullcmd[MAX_CMD_LEN];
4288  int error = 0;
4289 
4290  switch (cmd) {
4291  case CLI_INIT:
4292  e->command = "agi show commands [topic]";
4293  e->usage =
4294  "Usage: agi show commands [topic] <topic>\n"
4295  " When called with a topic as an argument, displays usage\n"
4296  " information on the given command. If called without a\n"
4297  " topic, it provides a list of AGI commands.\n";
4298  case CLI_GENERATE:
4299  return NULL;
4300  }
4301  if (a->argc < e->args - 1 || (a->argc >= e->args && strcasecmp(a->argv[e->args - 1], "topic")))
4302  return CLI_SHOWUSAGE;
4303  if (a->argc > e->args - 1) {
4304  command = find_command(a->argv + e->args, 1);
4305  if (command) {
4306  char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL;
4307  char info[30 + MAX_CMD_LEN]; /* '-= Info about...' */
4308  char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS]; /* '-= Info about...' with colors */
4309  char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
4310  char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Description]\n with colors */
4311  char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Runs Dead]\n with colors */
4312  char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS]; /* 'Yes' or 'No' with colors */
4313  char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS]; /* [See Also]\n with colors */
4314  char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
4315  size_t synlen, desclen, seealsolen, stxlen;
4316 
4317  term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle));
4318  term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle));
4319  term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle));
4320  term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle));
4321  term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle));
4322  term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent));
4323 
4324  ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
4325  snprintf(info, sizeof(info), "\n -= Info about agi '%s' =- ", fullcmd);
4326  term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle));
4327 #ifdef AST_XML_DOCS
4328  if (command->docsrc == AST_XML_DOC) {
4329  synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1);
4330  description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1);
4331  seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1);
4332  if (!seealso || !description || !synopsis) {
4333  error = 1;
4334  goto return_cleanup;
4335  }
4336  } else
4337 #endif
4338  {
4339  synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
4340  synopsis = ast_malloc(synlen);
4341 
4342  desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
4343  description = ast_malloc(desclen);
4344 
4345  seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
4346  seealso = ast_malloc(seealsolen);
4347 
4348  if (!synopsis || !description || !seealso) {
4349  error = 1;
4350  goto return_cleanup;
4351  }
4352  term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen);
4353  term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen);
4354  term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen);
4355  }
4356 
4357  stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
4358  syntax = ast_malloc(stxlen);
4359  if (!syntax) {
4360  error = 1;
4361  goto return_cleanup;
4362  }
4363  term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen);
4364 
4365  ast_cli(a->fd, "%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", infotitle, stxtitle, syntax,
4366  desctitle, description, syntitle, synopsis, deadtitle, deadcontent,
4367  seealsotitle, seealso);
4368 return_cleanup:
4369  ast_free(synopsis);
4370  ast_free(description);
4371  ast_free(syntax);
4372  ast_free(seealso);
4373  } else {
4374  if (find_command(a->argv + e->args, -1)) {
4375  return help_workhorse(a->fd, a->argv + e->args);
4376  } else {
4377  ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
4378  ast_cli(a->fd, "No such command '%s'.\n", fullcmd);
4379  }
4380  }
4381  } else {
4382  return help_workhorse(a->fd, NULL);
4383  }
4384  return (error ? CLI_FAILURE : CLI_SUCCESS);
4385 }
const char *const summary
Definition: agi.h:48
static const char synopsis[]
Definition: app_mysql.c:64
const char *const seealso
Definition: agi.h:56
static char * help_workhorse(int fd, const char *const match[])
Definition: res_agi.c:3757
#define ast_join(s, len, w)
Definition: strings.h:483
const int argc
Definition: cli.h:160
#define COLOR_CYAN
Definition: term.h:59
const char *const usage
Definition: agi.h:50
Definition: cli.h:152
static agi_command * find_command(const char *const cmds[], int exact)
Definition: res_agi.c:3909
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
#define MAX_CMD_LEN
Definition: res_agi.c:1389
#define AST_TERM_MAX_ESCAPE_CHARS
Maximum number of characters needed for a color escape sequence, and another one for a trailing reset...
Definition: term.h:71
const int dead
Definition: agi.h:52
const int fd
Definition: cli.h:159
const char *const syntax
Definition: agi.h:54
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
def info(msg)
#define CLI_FAILURE
Definition: cli.h:46
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:242
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
int error(const char *format,...)
Definition: utils/frame.c:999
enum ast_doc_src docsrc
Definition: agi.h:58
#define COLOR_MAGENTA
Definition: term.h:57

◆ handle_connection()

static int handle_connection ( const char *  agiurl,
const struct ast_sockaddr  addr,
const int  netsockfd 
)
static

Definition at line 2012 of file res_agi.c.

References ast_log, ast_poll, ast_sockaddr_stringify(), errno, LOG_WARNING, and MAX_AGI_CONNECT.

Referenced by launch_netscript().

2013 {
2014  struct pollfd pfds[1];
2015  int res, conresult;
2016  socklen_t reslen;
2017 
2018  reslen = sizeof(conresult);
2019 
2020  pfds[0].fd = netsockfd;
2021  pfds[0].events = POLLOUT;
2022 
2023  while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) {
2024  if (errno != EINTR) {
2025  if (!res) {
2026  ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n",
2027  agiurl, MAX_AGI_CONNECT);
2028  } else {
2029  ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
2030  }
2031 
2032  return 1;
2033  }
2034  }
2035 
2036  if (getsockopt(pfds[0].fd, SOL_SOCKET, SO_ERROR, &conresult, &reslen) < 0) {
2037  ast_log(LOG_WARNING, "Connection to %s failed with error: %s\n",
2038  ast_sockaddr_stringify(&addr), strerror(errno));
2039  return 1;
2040  }
2041 
2042  if (conresult) {
2043  ast_log(LOG_WARNING, "Connecting to '%s' failed for url '%s': %s\n",
2044  ast_sockaddr_stringify(&addr), agiurl, strerror(conresult));
2045  return 1;
2046  }
2047 
2048  return 0;
2049 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define MAX_AGI_CONNECT
Definition: res_agi.c:1405

◆ handle_controlstreamfile()

static int handle_controlstreamfile ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2495 of file res_agi.c.

References ast_agi_send(), AST_CONTROL_STREAM_STOP, ast_control_streamfile(), ast_strlen_zero, agi_state::fd, NULL, pbx_builtin_setvar_helper(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, skipms, stop, and suspend().

2496 {
2497  int res = 0, skipms = 3000;
2498  const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
2499  char stopkeybuf[2];
2500  long offsetms = 0;
2501  char offsetbuf[20];
2502 
2503  if (argc < 5 || argc > 10) {
2504  return RESULT_SHOWUSAGE;
2505  }
2506 
2507  if (!ast_strlen_zero(argv[4])) {
2508  stop = argv[4];
2509  }
2510 
2511  if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) {
2512  return RESULT_SHOWUSAGE;
2513  }
2514 
2515  if (argc > 6 && !ast_strlen_zero(argv[6])) {
2516  fwd = argv[6];
2517  }
2518 
2519  if (argc > 7 && !ast_strlen_zero(argv[7])) {
2520  rev = argv[7];
2521  }
2522 
2523  if (argc > 8 && !ast_strlen_zero(argv[8])) {
2524  suspend = argv[8];
2525  }
2526 
2527  if (argc > 9 && (sscanf(argv[9], "%30ld", &offsetms) != 1)) {
2528  return RESULT_SHOWUSAGE;
2529  }
2530 
2531  res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, &offsetms);
2532 
2533  /* If we stopped on one of our stop keys, return 0 */
2534  if (res > 0 && stop && strchr(stop, res)) {
2535  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
2536  snprintf(stopkeybuf, sizeof(stopkeybuf), "%c", res);
2537  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTOPKEY", stopkeybuf);
2538  } else if (res > 0 && res == AST_CONTROL_STREAM_STOP) {
2539  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "REMOTESTOPPED");
2540  res = 0;
2541  } else {
2542  if (res < 0) {
2543  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "ERROR");
2544  } else {
2545  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
2546  }
2547  }
2548 
2549  snprintf(offsetbuf, sizeof(offsetbuf), "%ld", offsetms);
2550  pbx_builtin_setvar_helper(chan, "CPLAYBACKOFFSET", offsetbuf);
2551 
2552  ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, offsetms);
2553 
2554  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2555 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
unsigned int stop
Definition: app_meetme.c:1096
#define NULL
Definition: resample.c:96
int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms, long *offsetms)
Stream a file with fast forward, pause, reverse, restart.
Definition: main/app.c:1319
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int skipms
int fd
Definition: agi.h:35
static void suspend(struct cc_core_instance *core_instance)
Definition: ccss.c:3193
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_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_dbdel()

static int handle_dbdel ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3334 of file res_agi.c.

References ast_agi_send(), ast_db_del(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3335 {
3336  int res;
3337 
3338  if (argc != 4)
3339  return RESULT_SHOWUSAGE;
3340  res = ast_db_del(argv[2], argv[3]);
3341  ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
3342  return RESULT_SUCCESS;
3343 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_dbdeltree()

static int handle_dbdeltree ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3345 of file res_agi.c.

References ast_agi_send(), ast_db_deltree(), agi_state::fd, NULL, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3346 {
3347  int num_deleted;
3348 
3349  if ((argc < 3) || (argc > 4)) {
3350  return RESULT_SHOWUSAGE;
3351  }
3352  if (argc == 4) {
3353  num_deleted = ast_db_deltree(argv[2], argv[3]);
3354  } else {
3355  num_deleted = ast_db_deltree(argv[2], NULL);
3356  }
3357 
3358  ast_agi_send(agi->fd, chan, "200 result=%c\n", num_deleted > 0 ? '0' : '1');
3359  return RESULT_SUCCESS;
3360 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
#define NULL
Definition: resample.c:96
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:457

◆ handle_dbget()

static int handle_dbget ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3290 of file res_agi.c.

References ast_agi_send(), ast_db_get(), ast_free, ast_str_buffer(), ast_str_create, ast_str_make_space, ast_str_size(), ast_str_strlen(), ast_str_update(), buf, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3291 {
3292  int res;
3293  struct ast_str *buf;
3294 
3295  if (argc != 4)
3296  return RESULT_SHOWUSAGE;
3297 
3298  if (!(buf = ast_str_create(16))) {
3299  ast_agi_send(agi->fd, chan, "200 result=-1\n");
3300  return RESULT_SUCCESS;
3301  }
3302 
3303  do {
3304  res = ast_db_get(argv[2], argv[3], ast_str_buffer(buf), ast_str_size(buf));
3305  ast_str_update(buf);
3306  if (ast_str_strlen(buf) < ast_str_size(buf) - 1) {
3307  break;
3308  }
3309  if (ast_str_make_space(&buf, ast_str_size(buf) * 2)) {
3310  break;
3311  }
3312  } while (1);
3313 
3314  if (res)
3315  ast_agi_send(agi->fd, chan, "200 result=0\n");
3316  else
3317  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(buf));
3318 
3319  ast_free(buf);
3320  return RESULT_SUCCESS;
3321 }
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:699
#define RESULT_SHOWUSAGE
Definition: cli.h:41
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_str_make_space(buf, new_len)
Definition: strings.h:780
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
int fd
Definition: agi.h:35
#define ast_free(a)
Definition: astmm.h:182
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:412
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:663
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ handle_dbput()

static int handle_dbput ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3323 of file res_agi.c.

References ast_agi_send(), ast_db_put(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3324 {
3325  int res;
3326 
3327  if (argc != 5)
3328  return RESULT_SHOWUSAGE;
3329  res = ast_db_put(argv[2], argv[3], argv[4]);
3330  ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
3331  return RESULT_SUCCESS;
3332 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_exec()

static int handle_exec ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3128 of file res_agi.c.

References ast_agi_send(), ast_channel_clear_flag(), ast_channel_flags(), ast_channel_lock, ast_channel_unlock, AST_FLAG_DISABLE_WORKAROUNDS, ast_log, ast_set_flag, ast_test_flag, ast_verb, agi_state::fd, LOG_WARNING, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.

3129 {
3130  int res, workaround;
3131  struct ast_app *app_to_exec;
3132 
3133  if (argc < 2)
3134  return RESULT_SHOWUSAGE;
3135 
3136  ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : "");
3137 
3138  if ((app_to_exec = pbx_findapp(argv[1]))) {
3139  ast_channel_lock(chan);
3140  if (!(workaround = ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_WORKAROUNDS))) {
3142  }
3143  ast_channel_unlock(chan);
3144  res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]);
3145  if (!workaround) {
3147  }
3148  } else {
3149  ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
3150  res = -2;
3151  }
3152  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
3153 
3154  /* Even though this is wrong, users are depending upon this result. */
3155  return res;
3156 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RESULT_SHOWUSAGE
Definition: cli.h:41
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Definition: channel.c:11235
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_log
Definition: astobj2.c:42
int fd
Definition: agi.h:35
#define ast_channel_unlock(chan)
Definition: channel.h:2946
ast_app: A registered application
Definition: pbx_app.c:45
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486

◆ handle_getdata()

static int handle_getdata ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2834 of file res_agi.c.

References ast_agi_send(), ast_app_getdata_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, max, RESULT_SHOWUSAGE, RESULT_SUCCESS, and timeout.

2835 {
2836  int res, max, timeout;
2837  char data[1024];
2838 
2839  if (argc < 3)
2840  return RESULT_SHOWUSAGE;
2841  if (argc >= 4)
2842  timeout = atoi(argv[3]);
2843  else
2844  timeout = 0;
2845  if (argc >= 5)
2846  max = atoi(argv[4]);
2847  else
2848  max = 1024;
2849  res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
2850  if (res == 2) /* New command */
2851  return RESULT_SUCCESS;
2852  else if (res == 1)
2853  ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
2854  else if (res < 0 )
2855  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2856  else
2857  ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
2858  return RESULT_SUCCESS;
2859 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
static int timeout
Definition: cdr_mysql.c:86
int ctrl
Definition: agi.h:37
int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
Full version with audiofd and controlfd. NOTE: returns &#39;2&#39; on ctrlfd available, not &#39;1&#39; like other fu...
Definition: main/app.c:250
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define max(a, b)
Definition: f2c.h:198

◆ handle_getoption()

static int handle_getoption ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

get option - really similar to the handle_streamfile, but with a timeout

Definition at line 2616 of file res_agi.c.

References ast_agi_send(), ast_applystream(), ast_channel_language(), ast_channel_pbx(), ast_channel_stream(), ast_debug, ast_log, ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verb, ast_waitfordigit_full(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, ast_pbx::dtimeoutms, agi_state::fd, LOG_WARNING, NULL, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, timeout, and ast_filestream::vfs.

2617 {
2618  int res;
2619  struct ast_filestream *fs, *vfs;
2620  long sample_offset = 0, max_length;
2621  int timeout = 0;
2622  const char *edigits = "";
2623 
2624  if ( argc < 4 || argc > 5 )
2625  return RESULT_SHOWUSAGE;
2626 
2627  if ( argv[3] )
2628  edigits = argv[3];
2629 
2630  if ( argc == 5 )
2631  timeout = atoi(argv[4]);
2632  else if (ast_channel_pbx(chan)->dtimeoutms) {
2633  /* by default dtimeout is set to 5sec */
2634  timeout = ast_channel_pbx(chan)->dtimeoutms; /* in msec */
2635  }
2636 
2637  if (!(fs = ast_openstream(chan, argv[2], ast_channel_language(chan)))) {
2638  ast_agi_send(agi->fd, chan, "200 result=-1 endpos=%ld\n", sample_offset);
2639  ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
2640  return RESULT_FAILURE;
2641  }
2642 
2643  if ((vfs = ast_openvstream(chan, argv[2], ast_channel_language(chan))))
2644  ast_debug(1, "Ooh, found a video stream, too\n");
2645 
2646  ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
2647 
2648  ast_seekstream(fs, 0, SEEK_END);
2649  max_length = ast_tellstream(fs);
2650  ast_seekstream(fs, sample_offset, SEEK_SET);
2651  res = ast_applystream(chan, fs);
2652  if (vfs)
2653  ast_applystream(chan, vfs);
2654  ast_playstream(fs);
2655  if (vfs)
2656  ast_playstream(vfs);
2657 
2658  res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
2659  /* this is to check for if ast_waitstream closed the stream, we probably are at
2660  * the end of the stream, return that amount, else check for the amount */
2661  sample_offset = (ast_channel_stream(chan))?ast_tellstream(fs):max_length;
2662  ast_stopstream(chan);
2663  if (res == 1) {
2664  /* Stop this command, don't print a result line, as there is a new command */
2665  return RESULT_SUCCESS;
2666  }
2667 
2668  /* If the user didnt press a key, wait for digitTimeout*/
2669  if (res == 0 ) {
2670  res = ast_waitfordigit_full(chan, timeout, NULL, agi->audio, agi->ctrl);
2671  /* Make sure the new result is in the escape digits of the GET OPTION */
2672  if ( !strchr(edigits,res) )
2673  res=0;
2674  }
2675 
2676  ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
2677  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2678 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
int ctrl
Definition: agi.h:37
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:1048
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int ast_playstream(struct ast_filestream *s)
Play a open stream on a channel.
Definition: file.c:1026
struct ast_filestream * ast_openvstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:812
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applys a open stream to a channel.
Definition: file.c:1020
int fd
Definition: agi.h:35
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:1038
int audio
Definition: agi.h:36
struct ast_filestream * ast_channel_stream(const struct ast_channel *chan)
int ast_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd, int monfd)
Definition: file.c:1785
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
int dtimeoutms
Definition: pbx.h:212
const char * ast_channel_language(const struct ast_channel *chan)
struct ast_filestream * vfs
Definition: mod_format.h:110
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
int ast_waitfordigit_full(struct ast_channel *c, int ms, const char *breakon, int audiofd, int ctrlfd)
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to mon...
Definition: channel.c:3248
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
#define RESULT_FAILURE
Definition: cli.h:42
struct ast_filestream * ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:755

◆ handle_getvariable()

static int handle_getvariable ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3216 of file res_agi.c.

References ast_agi_send(), ast_func_read(), ast_strlen_zero, agi_state::fd, NULL, pbx_retrieve_variable(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3217 {
3218  char *ret;
3219  char tempstr[1024] = "";
3220 
3221  if (argc != 3)
3222  return RESULT_SHOWUSAGE;
3223 
3224  /* check if we want to execute an ast_custom_function */
3225  if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
3226  ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
3227  } else {
3228  pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
3229  }
3230 
3231  if (ret)
3232  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
3233  else
3234  ast_agi_send(agi->fd, chan, "200 result=0\n");
3235 
3236  return RESULT_SUCCESS;
3237 }
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
#define RESULT_SHOWUSAGE
Definition: cli.h:41
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_getvariablefull()

static int handle_getvariablefull ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3239 of file res_agi.c.

References ast_agi_send(), ast_channel_get_by_name(), ast_channel_ref, ast_channel_unref, ast_free, ast_str_buffer(), ast_str_create, ast_str_substitute_variables(), agi_state::fd, NULL, RESULT_SHOWUSAGE, RESULT_SUCCESS, and str.

3240 {
3241  struct ast_channel *chan2 = NULL;
3242 
3243  if (argc != 4 && argc != 5) {
3244  return RESULT_SHOWUSAGE;
3245  }
3246 
3247  if (argc == 5) {
3248  chan2 = ast_channel_get_by_name(argv[4]);
3249  } else {
3250  chan2 = ast_channel_ref(chan);
3251  }
3252 
3253  if (chan2) {
3254  struct ast_str *str = ast_str_create(16);
3255  if (!str) {
3256  ast_agi_send(agi->fd, chan, "200 result=0\n");
3257  return RESULT_SUCCESS;
3258  }
3259  ast_str_substitute_variables(&str, 0, chan2, argv[3]);
3260  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(str));
3261  ast_free(str);
3262  } else {
3263  ast_agi_send(agi->fd, chan, "200 result=0\n");
3264  }
3265 
3266  if (chan2) {
3267  chan2 = ast_channel_unref(chan2);
3268  }
3269 
3270  return RESULT_SUCCESS;
3271 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define RESULT_SHOWUSAGE
Definition: cli.h:41
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
int fd
Definition: agi.h:35
#define ast_free(a)
Definition: astmm.h:182
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
#define RESULT_SUCCESS
Definition: cli.h:40
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ handle_hangup()

static int handle_hangup ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3100 of file res_agi.c.

References ast_agi_send(), ast_channel_get_by_name(), ast_channel_unref, ast_set_hangupsource(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, c, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3101 {
3102  struct ast_channel *c;
3103 
3104  if (argc == 1) {
3105  /* no argument: hangup the current channel */
3106  ast_set_hangupsource(chan, "dialplan/agi", 0);
3108  ast_agi_send(agi->fd, chan, "200 result=1\n");
3109  return RESULT_SUCCESS;
3110  } else if (argc == 2) {
3111  /* one argument: look for info on the specified channel */
3112  if ((c = ast_channel_get_by_name(argv[1]))) {
3113  /* we have a matching channel */
3114  ast_set_hangupsource(c, "dialplan/agi", 0);
3116  c = ast_channel_unref(c);
3117  ast_agi_send(agi->fd, chan, "200 result=1\n");
3118  return RESULT_SUCCESS;
3119  }
3120  /* if we get this far no channel name matched the argument given */
3121  ast_agi_send(agi->fd, chan, "200 result=-1\n");
3122  return RESULT_SUCCESS;
3123  } else {
3124  return RESULT_SHOWUSAGE;
3125  }
3126 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define RESULT_SHOWUSAGE
Definition: cli.h:41
static struct test_val c
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it&#39;s bridge.
Definition: channel.c:2504
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_noop()

static int handle_noop ( struct ast_channel chan,
AGI agi,
int  arg,
const char *const  argv[] 
)
static

Definition at line 3391 of file res_agi.c.

References ast_agi_send(), agi_state::fd, and RESULT_SUCCESS.

Referenced by AST_TEST_DEFINE().

3392 {
3393  ast_agi_send(agi->fd, chan, "200 result=0\n");
3394  return RESULT_SUCCESS;
3395 }
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_recordfile()

static int handle_recordfile ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2899 of file res_agi.c.

References ao2_bump, ao2_cleanup, ast_agi_send(), ast_applystream(), ast_channel_language(), ast_channel_name(), ast_channel_readformat(), ast_channel_stream_set(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_get_threshold_from_settings(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FILE_MODE, ast_format_slin, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate(), ast_log, ast_read(), ast_seekstream(), ast_set_read_format(), ast_stream_rewind(), ast_streamfile(), ast_tellstream(), ast_truncstream(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), agi_state::fd, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, RAII_VAR, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_frame::subclass, THRESHOLD_SILENCE, and ast_dsp::totalsilence.

2900 {
2901  struct ast_filestream *fs;
2902  struct ast_frame *f;
2903  struct timeval start;
2904  long sample_offset = 0;
2905  int res = 0;
2906  int ms;
2907 
2908  struct ast_dsp *sildet=NULL; /* silence detector dsp */
2909  int totalsilence = 0;
2910  int dspsilence = 0;
2911  int silence = 0; /* amount of silence to allow */
2912  int gotsilence = 0; /* did we timeout for silence? */
2913  char *silencestr = NULL;
2914  RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
2915 
2916  /* XXX EAGI FIXME XXX */
2917 
2918  if (argc < 6)
2919  return RESULT_SHOWUSAGE;
2920  if (sscanf(argv[5], "%30d", &ms) != 1)
2921  return RESULT_SHOWUSAGE;
2922 
2923  if (argc > 6)
2924  silencestr = strchr(argv[6],'s');
2925  if ((argc > 7) && (!silencestr))
2926  silencestr = strchr(argv[7],'s');
2927  if ((argc > 8) && (!silencestr))
2928  silencestr = strchr(argv[8],'s');
2929 
2930  if (silencestr) {
2931  if (strlen(silencestr) > 2) {
2932  if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
2933  silencestr++;
2934  silencestr++;
2935  if (silencestr)
2936  silence = atoi(silencestr);
2937  if (silence > 0)
2938  silence *= 1000;
2939  }
2940  }
2941  }
2942 
2943  if (silence > 0) {
2944  rfmt = ao2_bump(ast_channel_readformat(chan));
2945  res = ast_set_read_format(chan, ast_format_slin);
2946  if (res < 0) {
2947  ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
2948  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2949  return RESULT_FAILURE;
2950  }
2951  sildet = ast_dsp_new();
2952  if (!sildet) {
2953  ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
2954  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2955  return RESULT_FAILURE;
2956  }
2958  }
2959 
2960  /* backward compatibility, if no offset given, arg[6] would have been
2961  * caught below and taken to be a beep, else if it is a digit then it is a
2962  * offset */
2963  if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
2964  res = ast_streamfile(chan, "beep", ast_channel_language(chan));
2965 
2966  if ((argc > 7) && (!strchr(argv[7], '=')))
2967  res = ast_streamfile(chan, "beep", ast_channel_language(chan));
2968 
2969  if (!res)
2970  res = ast_waitstream(chan, argv[4]);
2971  if (res) {
2972  ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
2973  } else {
2974  fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE);
2975  if (!fs) {
2976  res = -1;
2977  ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res);
2978  if (sildet)
2979  ast_dsp_free(sildet);
2980  return RESULT_FAILURE;
2981  }
2982 
2983  /* Request a video update */
2985 
2986  ast_channel_stream_set(chan, fs);
2987  ast_applystream(chan,fs);
2988  /* really should have checks */
2989  ast_seekstream(fs, sample_offset, SEEK_SET);
2990  ast_truncstream(fs);
2991 
2992  start = ast_tvnow();
2993  while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
2994  res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
2995  if (res < 0) {
2996  ast_closestream(fs);
2997  ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
2998  if (sildet)
2999  ast_dsp_free(sildet);
3000  return RESULT_FAILURE;
3001  }
3002  f = ast_read(chan);
3003  if (!f) {
3004  ast_closestream(fs);
3005  ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
3006  if (sildet)
3007  ast_dsp_free(sildet);
3008  return RESULT_FAILURE;
3009  }
3010  switch(f->frametype) {
3011  case AST_FRAME_DTMF:
3012  if (strchr(argv[4], f->subclass.integer)) {
3013  /* This is an interrupting chracter, so rewind to chop off any small
3014  amount of DTMF that may have been recorded
3015  */
3016  ast_stream_rewind(fs, 200);
3017  ast_truncstream(fs);
3018  sample_offset = ast_tellstream(fs);
3019  ast_closestream(fs);
3020  ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass.integer, sample_offset);
3021  ast_frfree(f);
3022  if (sildet)
3023  ast_dsp_free(sildet);
3024  return RESULT_SUCCESS;
3025  }
3026  break;
3027  case AST_FRAME_VOICE:
3028  ast_writestream(fs, f);
3029  /* this is a safe place to check progress since we know that fs
3030  * is valid after a write, and it will then have our current
3031  * location */
3032  sample_offset = ast_tellstream(fs);
3033  if (silence > 0) {
3034  dspsilence = 0;
3035  ast_dsp_silence(sildet, f, &dspsilence);
3036  if (dspsilence) {
3037  totalsilence = dspsilence;
3038  } else {
3039  totalsilence = 0;
3040  }
3041  if (totalsilence > silence) {
3042  /* Ended happily with silence */
3043  gotsilence = 1;
3044  break;
3045  }
3046  }
3047  break;
3048  case AST_FRAME_VIDEO:
3049  ast_writestream(fs, f);
3050  default:
3051  /* Ignore all other frames */
3052  break;
3053  }
3054  ast_frfree(f);
3055  if (gotsilence)
3056  break;
3057  }
3058 
3059  if (gotsilence) {
3060  ast_stream_rewind(fs, silence-1000);
3061  ast_truncstream(fs);
3062  sample_offset = ast_tellstream(fs);
3063  }
3064  ast_closestream(fs);
3065  ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
3066  }
3067 
3068  if (silence > 0) {
3069  res = ast_set_read_format(chan, rfmt);
3070  if (res)
3071  ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
3072  ast_dsp_free(sildet);
3073  }
3074 
3075  return RESULT_SUCCESS;
3076 }
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4322
#define RESULT_SHOWUSAGE
Definition: cli.h:41
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
#define LOG_WARNING
Definition: logger.h:274
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
Definition of a media format.
Definition: format.c:43
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
#define AST_FILE_MODE
Definition: asterisk.h:32
struct ast_frame_subclass subclass
int totalsilence
Definition: dsp.c:409
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:1048
void ast_channel_stream_set(struct ast_channel *chan, struct ast_filestream *value)
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
#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:911
Definition: dsp.c:405
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Definition: dsp.c:1775
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applys a open stream to a channel.
Definition: file.c:1020
int ast_stream_rewind(struct ast_filestream *fs, off_t ms)
Rewind stream ms.
Definition: file.c:1063
int fd
Definition: agi.h:35
struct ast_filestream * ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts writing a file.
Definition: file.c:1361
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:1038
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1068
int ast_truncstream(struct ast_filestream *fs)
Trunc stream at current location.
Definition: file.c:1043
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1483
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
Writes a frame to a stream.
Definition: file.c:209
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1776
#define ast_frfree(fr)
Data structure associated with a single frame of data.
const char * ast_channel_language(const struct ast_channel *chan)
enum ast_frame_type frametype
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1996
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_recvchar()

static int handle_recvchar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2414 of file res_agi.c.

References ast_agi_send(), ast_recvchar(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2415 {
2416  int res;
2417 
2418  if (argc != 3)
2419  return RESULT_SHOWUSAGE;
2420 
2421  res = ast_recvchar(chan,atoi(argv[2]));
2422  if (res == 0) {
2423  ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
2424  return RESULT_SUCCESS;
2425  }
2426  if (res > 0) {
2427  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2428  return RESULT_SUCCESS;
2429  }
2430  ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
2431  return RESULT_FAILURE;
2432 }
int ast_recvchar(struct ast_channel *chan, int timeout)
Receives a text character from a channel.
Definition: channel.c:4751
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_recvtext()

static int handle_recvtext ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2434 of file res_agi.c.

References ast_agi_send(), ast_free, ast_recvtext(), buf, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2435 {
2436  char *buf;
2437 
2438  if (argc != 3)
2439  return RESULT_SHOWUSAGE;
2440 
2441  buf = ast_recvtext(chan, atoi(argv[2]));
2442  if (buf) {
2443  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
2444  ast_free(buf);
2445  } else {
2446  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2447  }
2448  return RESULT_SUCCESS;
2449 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_recvtext(struct ast_channel *chan, int timeout)
Receives a text string from a channel Read a string of text from a channel.
Definition: channel.c:4762
int fd
Definition: agi.h:35
#define ast_free(a)
Definition: astmm.h:182
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_sayalpha()

static int handle_sayalpha ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2716 of file res_agi.c.

References ast_agi_send(), ast_channel_language(), AST_SAY_CASE_ALL, AST_SAY_CASE_LOWER, AST_SAY_CASE_NONE, AST_SAY_CASE_UPPER, ast_say_character_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2717 {
2718  int res;
2719  int sensitivity = AST_SAY_CASE_NONE;
2720 
2721  if (argc < 4 || argc > 5) {
2722  return RESULT_SHOWUSAGE;
2723  }
2724 
2725  if (argc > 4) {
2726  switch (argv[4][0]) {
2727  case 'a':
2728  case 'A':
2729  sensitivity = AST_SAY_CASE_ALL;
2730  break;
2731  case 'l':
2732  case 'L':
2733  sensitivity = AST_SAY_CASE_LOWER;
2734  break;
2735  case 'n':
2736  case 'N':
2737  sensitivity = AST_SAY_CASE_NONE;
2738  break;
2739  case 'u':
2740  case 'U':
2741  sensitivity = AST_SAY_CASE_UPPER;
2742  break;
2743  case '\0':
2744  break;
2745  default:
2746  return RESULT_SHOWUSAGE;
2747  }
2748  }
2749  res = ast_say_character_str_full(chan, argv[2], argv[3], ast_channel_language(chan), sensitivity, agi->audio, agi->ctrl);
2750  if (res == 1) /* New command */
2751  return RESULT_SUCCESS;
2752  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2753  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2754 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ctrl
Definition: agi.h:37
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
const char * ast_channel_language(const struct ast_channel *chan)
SAY_EXTERN int(* ast_say_character_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity, int audiofd, int ctrlfd) SAY_INIT(ast_say_character_str_full)
Definition: say.h:175
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_saydate()

static int handle_saydate ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2756 of file res_agi.c.

References ast_agi_send(), ast_channel_language(), ast_say_date, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2757 {
2758  int res, num;
2759 
2760  if (argc != 4)
2761  return RESULT_SHOWUSAGE;
2762  if (sscanf(argv[2], "%30d", &num) != 1)
2763  return RESULT_SHOWUSAGE;
2764  res = ast_say_date(chan, num, argv[3], ast_channel_language(chan));
2765  if (res == 1)
2766  return RESULT_SUCCESS;
2767  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2768  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2769 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
SAY_EXTERN int(* ast_say_date)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_date)
Definition: say.h:185
int fd
Definition: agi.h:35
const char * ast_channel_language(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_saydatetime()

static int handle_saydatetime ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2786 of file res_agi.c.

References ast_agi_send(), ast_channel_language(), ast_get_time_t(), ast_say_date_with_format, ast_strlen_zero, agi_state::fd, format, NULL, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2787 {
2788  int res = 0;
2789  time_t unixtime;
2790  const char *format, *zone = NULL;
2791 
2792  if (argc < 4)
2793  return RESULT_SHOWUSAGE;
2794 
2795  if (argc > 4) {
2796  format = argv[4];
2797  } else {
2798  /* XXX this doesn't belong here, but in the 'say' module */
2799  if (!strcasecmp(ast_channel_language(chan), "de")) {
2800  format = "A dBY HMS";
2801  } else {
2802  format = "ABdY 'digits/at' IMp";
2803  }
2804  }
2805 
2806  if (argc > 5 && !ast_strlen_zero(argv[5]))
2807  zone = argv[5];
2808 
2809  if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
2810  return RESULT_SHOWUSAGE;
2811 
2812  res = ast_say_date_with_format(chan, unixtime, argv[3], ast_channel_language(chan), format, zone);
2813  if (res == 1)
2814  return RESULT_SUCCESS;
2815 
2816  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2817  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2818 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
Definition: main/utils.c:2198
SAY_EXTERN int(* ast_say_date_with_format)(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone) SAY_INIT(ast_say_date_with_format)
Definition: say.h:189
int fd
Definition: agi.h:35
const char * ast_channel_language(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_saydigits()

static int handle_saydigits ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2700 of file res_agi.c.

References ast_agi_send(), ast_channel_language(), ast_say_digit_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2701 {
2702  int res, num;
2703 
2704  if (argc != 4)
2705  return RESULT_SHOWUSAGE;
2706  if (sscanf(argv[2], "%30d", &num) != 1)
2707  return RESULT_SHOWUSAGE;
2708 
2709  res = ast_say_digit_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl);
2710  if (res == 1) /* New command */
2711  return RESULT_SUCCESS;
2712  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2713  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2714 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ctrl
Definition: agi.h:37
SAY_EXTERN int(* ast_say_digit_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_digit_str_full)
Same as ast_say_digit_str() with audiofd for received audio and returns 1 on ctrlfd being readable...
Definition: say.h:143
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
const char * ast_channel_language(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_saynumber()

static int handle_saynumber ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Say number in various language syntaxes.

Definition at line 2685 of file res_agi.c.

References ast_agi_send(), ast_channel_language(), ast_say_number_full, agi_state::audio, agi_state::ctrl, agi_state::fd, NULL, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2686 {
2687  int res, num;
2688 
2689  if (argc < 4 || argc > 5)
2690  return RESULT_SHOWUSAGE;
2691  if (sscanf(argv[2], "%30d", &num) != 1)
2692  return RESULT_SHOWUSAGE;
2693  res = ast_say_number_full(chan, num, argv[3], ast_channel_language(chan), argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
2694  if (res == 1)
2695  return RESULT_SUCCESS;
2696  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2697  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2698 }
SAY_EXTERN int(* ast_say_number_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_number_full)
Same as ast_say_number() with audiofd for received audio and returns 1 on ctrlfd being readable...
Definition: say.h:86
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ctrl
Definition: agi.h:37
#define NULL
Definition: resample.c:96
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
const char * ast_channel_language(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_sayphonetic()

static int handle_sayphonetic ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2820 of file res_agi.c.

References ast_agi_send(), ast_channel_language(), ast_say_phonetic_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2821 {
2822  int res;
2823 
2824  if (argc != 4)
2825  return RESULT_SHOWUSAGE;
2826 
2827  res = ast_say_phonetic_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl);
2828  if (res == 1) /* New command */
2829  return RESULT_SUCCESS;
2830  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2831  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2832 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ctrl
Definition: agi.h:37
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
const char * ast_channel_language(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
SAY_EXTERN int(* ast_say_phonetic_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_phonetic_str_full)
Definition: say.h:180
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_saytime()

static int handle_saytime ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2771 of file res_agi.c.

References ast_agi_send(), ast_channel_language(), ast_say_time, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2772 {
2773  int res, num;
2774 
2775  if (argc != 4)
2776  return RESULT_SHOWUSAGE;
2777  if (sscanf(argv[2], "%30d", &num) != 1)
2778  return RESULT_SHOWUSAGE;
2779  res = ast_say_time(chan, num, argv[3], ast_channel_language(chan));
2780  if (res == 1)
2781  return RESULT_SUCCESS;
2782  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2783  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2784 }
SAY_EXTERN int(* ast_say_time)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_time)
Definition: say.h:183
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
const char * ast_channel_language(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_sendimage()

static int handle_sendimage ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2479 of file res_agi.c.

References ast_agi_send(), ast_check_hangup(), ast_send_image(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2480 {
2481  int res;
2482 
2483  if (argc != 3) {
2484  return RESULT_SHOWUSAGE;
2485  }
2486 
2487  res = ast_send_image(chan, argv[2]);
2488  if (!ast_check_hangup(chan)) {
2489  res = 0;
2490  }
2491  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2492  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2493 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ast_send_image(struct ast_channel *chan, const char *filename)
Sends an image.
Definition: image.c:158
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_sendtext()

static int handle_sendtext ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2395 of file res_agi.c.

References ast_agi_send(), ast_sendtext(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2396 {
2397  int res;
2398 
2399  if (argc != 3)
2400  return RESULT_SHOWUSAGE;
2401 
2402  /* At the moment, the parser (perhaps broken) returns with
2403  the last argument PLUS the newline at the end of the input
2404  buffer. This probably needs to be fixed, but I wont do that
2405  because other stuff may break as a result. The right way
2406  would probably be to strip off the trailing newline before
2407  parsing, then here, add a newline at the end of the string
2408  before sending it to ast_sendtext --DUDE */
2409  res = ast_sendtext(chan, argv[2]);
2410  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2411  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2412 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42
int ast_sendtext(struct ast_channel *chan, const char *text)
Sends text to a channel.
Definition: channel.c:4854

◆ handle_setcallerid()

static int handle_setcallerid ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3158 of file res_agi.c.

References ast_agi_send(), ast_callerid_parse(), ast_copy_string(), ast_set_callerid(), ast_shrink_phone_number(), agi_state::fd, NULL, RESULT_SUCCESS, and tmp().

3159 {
3160  char tmp[256]="";
3161  char *l = NULL, *n = NULL;
3162 
3163  if (argv[2]) {
3164  ast_copy_string(tmp, argv[2], sizeof(tmp));
3165  ast_callerid_parse(tmp, &n, &l);
3166  if (l)
3168  else
3169  l = "";
3170  if (!n)
3171  n = "";
3172  ast_set_callerid(chan, l, n, NULL);
3173  }
3174 
3175  ast_agi_send(agi->fd, chan, "200 result=1\n");
3176  return RESULT_SUCCESS;
3177 }
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7434
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
int fd
Definition: agi.h:35
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()&#39;s, .&#39;s, and -&#39;s...
Definition: callerid.c:947
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1008

◆ handle_setcontext()

static int handle_setcontext ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2861 of file res_agi.c.

References ast_agi_send(), ast_channel_context_set(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2862 {
2863 
2864  if (argc != 3)
2865  return RESULT_SHOWUSAGE;
2866  ast_channel_context_set(chan, argv[2]);
2867  ast_agi_send(agi->fd, chan, "200 result=0\n");
2868  return RESULT_SUCCESS;
2869 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
void ast_channel_context_set(struct ast_channel *chan, const char *value)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_setextension()

static int handle_setextension ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2871 of file res_agi.c.

References ast_agi_send(), ast_channel_exten_set(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2872 {
2873  if (argc != 3)
2874  return RESULT_SHOWUSAGE;
2875  ast_channel_exten_set(chan, argv[2]);
2876  ast_agi_send(agi->fd, chan, "200 result=0\n");
2877  return RESULT_SUCCESS;
2878 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_setmusic()

static int handle_setmusic ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3397 of file res_agi.c.

References ast_agi_send(), ast_moh_start(), ast_moh_stop(), agi_state::fd, NULL, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3398 {
3399  if (argc < 3) {
3400  return RESULT_SHOWUSAGE;
3401  }
3402  if (!strncasecmp(argv[2], "on", 2))
3403  ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
3404  else if (!strncasecmp(argv[2], "off", 3))
3405  ast_moh_stop(chan);
3406  ast_agi_send(agi->fd, chan, "200 result=0\n");
3407  return RESULT_SUCCESS;
3408 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
#define NULL
Definition: resample.c:96
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
int fd
Definition: agi.h:35
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:7866
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_setpriority()

static int handle_setpriority ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2880 of file res_agi.c.

References ast_agi_send(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_explicit_goto(), ast_findlabel_extension(), agi_state::fd, NULL, RESULT_SHOWUSAGE, RESULT_SUCCESS, and S_COR.

2881 {
2882  int pri;
2883 
2884  if (argc != 3)
2885  return RESULT_SHOWUSAGE;
2886 
2887  if (sscanf(argv[2], "%30d", &pri) != 1) {
2888  pri = ast_findlabel_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), argv[2],
2889  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
2890  if (pri < 1)
2891  return RESULT_SHOWUSAGE;
2892  }
2893 
2894  ast_explicit_goto(chan, NULL, NULL, pri);
2895  ast_agi_send(agi->fd, chan, "200 result=0\n");
2896  return RESULT_SUCCESS;
2897 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6987
#define NULL
Definition: resample.c:96
Number structure.
Definition: app_followme.c:154
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
const char * ast_channel_exten(const struct ast_channel *chan)
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:4184
int fd
Definition: agi.h:35
const char * ast_channel_context(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_setvariable()

static int handle_setvariable ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3203 of file res_agi.c.

References ast_agi_send(), agi_state::fd, pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3204 {
3205  if (argc != 4) {
3206  return RESULT_SHOWUSAGE;
3207  }
3208 
3209  if (argv[3])
3210  pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
3211 
3212  ast_agi_send(agi->fd, chan, "200 result=1\n");
3213  return RESULT_SUCCESS;
3214 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
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_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_speechactivategrammar()

static int handle_speechactivategrammar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3501 of file res_agi.c.

References ast_agi_send(), ast_speech_grammar_activate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

3502 {
3503  if (argc != 4)
3504  return RESULT_SHOWUSAGE;
3505 
3506  if (!agi->speech) {
3507  ast_agi_send(agi->fd, chan, "200 result=0\n");
3508  return RESULT_SUCCESS;
3509  }
3510 
3511  if (ast_speech_grammar_activate(agi->speech, argv[3]))
3512  ast_agi_send(agi->fd, chan, "200 result=0\n");
3513  else
3514  ast_agi_send(agi->fd, chan, "200 result=1\n");
3515 
3516  return RESULT_SUCCESS;
3517 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ast_speech_grammar_activate(struct ast_speech *speech, const char *grammar_name)
Activate a grammar on a speech structure.
Definition: res_speech.c:65
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_speechcreate()

static int handle_speechcreate ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3410 of file res_agi.c.

References ao2_ref, ast_agi_send(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_speech_new(), agi_state::fd, RESULT_FAILURE, RESULT_SUCCESS, and agi_state::speech.

3411 {
3412  struct ast_format_cap *cap;
3413 
3414  /* If a structure already exists, return an error */
3415  if (agi->speech) {
3416  ast_agi_send(agi->fd, chan, "200 result=0\n");
3417  return RESULT_SUCCESS;
3418  }
3419 
3421  return RESULT_FAILURE;
3422  }
3424  if ((agi->speech = ast_speech_new(argv[2], cap))) {
3425  ast_agi_send(agi->fd, chan, "200 result=1\n");
3426  } else {
3427  ast_agi_send(agi->fd, chan, "200 result=0\n");
3428  }
3429  ao2_ref(cap, -1);
3430 
3431  return RESULT_SUCCESS;
3432 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
struct ast_speech * ast_speech_new(const char *engine_name, const struct ast_format_cap *formats)
Create a new speech structure.
Definition: res_speech.c:180
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define RESULT_FAILURE
Definition: cli.h:42

◆ handle_speechdeactivategrammar()

static int handle_speechdeactivategrammar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3519 of file res_agi.c.

References ast_agi_send(), ast_speech_grammar_deactivate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

3520 {
3521  if (argc != 4)
3522  return RESULT_SHOWUSAGE;
3523 
3524  if (!agi->speech) {
3525  ast_agi_send(agi->fd, chan, "200 result=0\n");
3526  return RESULT_SUCCESS;
3527  }
3528 
3529  if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
3530  ast_agi_send(agi->fd, chan, "200 result=0\n");
3531  else
3532  ast_agi_send(agi->fd, chan, "200 result=1\n");
3533 
3534  return RESULT_SUCCESS;
3535 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ast_speech_grammar_deactivate(struct ast_speech *speech, const char *grammar_name)
Deactivate a grammar on a speech structure.
Definition: res_speech.c:71
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_speechdestroy()

static int handle_speechdestroy ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3452 of file res_agi.c.

References ast_agi_send(), ast_speech_destroy(), agi_state::fd, NULL, RESULT_SUCCESS, and agi_state::speech.

3453 {
3454  if (agi->speech) {
3455  ast_speech_destroy(agi->speech);
3456  agi->speech = NULL;
3457  ast_agi_send(agi->fd, chan, "200 result=1\n");
3458  } else {
3459  ast_agi_send(agi->fd, chan, "200 result=0\n");
3460  }
3461 
3462  return RESULT_SUCCESS;
3463 }
int ast_speech_destroy(struct ast_speech *speech)
Destroy a speech structure.
Definition: res_speech.c:240
#define NULL
Definition: resample.c:96
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_speechloadgrammar()

static int handle_speechloadgrammar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3465 of file res_agi.c.

References ast_agi_send(), ast_speech_grammar_load(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

3466 {
3467  if (argc != 5)
3468  return RESULT_SHOWUSAGE;
3469 
3470  if (!agi->speech) {
3471  ast_agi_send(agi->fd, chan, "200 result=0\n");
3472  return RESULT_SUCCESS;
3473  }
3474 
3475  if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
3476  ast_agi_send(agi->fd, chan, "200 result=0\n");
3477  else
3478  ast_agi_send(agi->fd, chan, "200 result=1\n");
3479 
3480  return RESULT_SUCCESS;
3481 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
int ast_speech_grammar_load(struct ast_speech *speech, const char *grammar_name, const char *grammar)
Load a grammar on a speech structure (not globally)
Definition: res_speech.c:77
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_speechrecognize()

static int handle_speechrecognize ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3556 of file res_agi.c.

References ast_agi_send(), ast_build_string(), ast_channel_language(), ast_channel_sched(), ast_channel_stream(), ast_channel_streamid(), ast_channel_timingfunc(), ast_clear_flag, AST_CONTROL_HANGUP, ast_format_slin, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_LIST_NEXT, ast_mutex_lock, ast_mutex_unlock, ast_read(), ast_sched_runq(), ast_sched_wait(), ast_set_read_format(), ast_speech_change_state(), AST_SPEECH_QUIET, ast_speech_results_get(), ast_speech_start(), AST_SPEECH_STATE_DONE, AST_SPEECH_STATE_NOT_READY, AST_SPEECH_STATE_READY, AST_SPEECH_STATE_WAIT, ast_speech_write(), ast_stopstream(), ast_strlen_zero, ast_tellstream(), ast_test_flag, ast_waitfor(), buf, ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, ast_speech_result::grammar, ast_frame_subclass::integer, ast_speech::lock, NULL, ast_speech::processing_sound, prompt, ast_frame::ptr, result, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_speech::results, ast_speech_result::score, agi_state::speech, speech_streamfile(), ast_speech::state, ast_frame::subclass, ast_speech_result::text, timeout, and tmp().

3557 {
3558  struct ast_speech *speech = agi->speech;
3559  const char *prompt;
3560  char dtmf = 0, tmp[4096] = "", *buf = tmp;
3561  int timeout = 0, offset = 0, res = 0, i = 0;
3562  long current_offset = 0;
3563  const char *reason = NULL;
3564  struct ast_frame *fr = NULL;
3565  struct ast_speech_result *result = NULL;
3566  size_t left = sizeof(tmp);
3567  time_t start = 0, current;
3568 
3569  if (argc < 4)
3570  return RESULT_SHOWUSAGE;
3571 
3572  if (!speech) {
3573  ast_agi_send(agi->fd, chan, "200 result=0\n");
3574  return RESULT_SUCCESS;
3575  }
3576 
3577  prompt = argv[2];
3578  timeout = atoi(argv[3]);
3579 
3580  /* If offset is specified then convert from text to integer */
3581  if (argc == 5)
3582  offset = atoi(argv[4]);
3583 
3584  /* We want frames coming in signed linear */
3585  if (ast_set_read_format(chan, ast_format_slin)) {
3586  ast_agi_send(agi->fd, chan, "200 result=0\n");
3587  return RESULT_SUCCESS;
3588  }
3589 
3590  /* Setup speech structure */
3591  if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
3593  ast_speech_start(speech);
3594  }
3595 
3596  /* Start playing prompt */
3597  speech_streamfile(chan, prompt, ast_channel_language(chan), offset);
3598 
3599  /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */
3600  while (ast_strlen_zero(reason)) {
3601  /* Run scheduled items */
3603 
3604  /* See maximum time of waiting */
3605  if ((res = ast_sched_wait(ast_channel_sched(chan))) < 0)
3606  res = 1000;
3607 
3608  /* Wait for frame */
3609  if (ast_waitfor(chan, res) > 0) {
3610  if (!(fr = ast_read(chan))) {
3611  reason = "hangup";
3612  break;
3613  }
3614  }
3615 
3616  /* Perform timeout check */
3617  if ((timeout > 0) && (start > 0)) {
3618  time(&current);
3619  if ((current - start) >= timeout) {
3620  reason = "timeout";
3621  if (fr)
3622  ast_frfree(fr);
3623  break;
3624  }
3625  }
3626 
3627  /* Check the speech structure for any changes */
3628  ast_mutex_lock(&speech->lock);
3629 
3630  /* See if we need to quiet the audio stream playback */
3631  if (ast_test_flag(speech, AST_SPEECH_QUIET) && ast_channel_stream(chan)) {
3632  current_offset = ast_tellstream(ast_channel_stream(chan));
3633  ast_stopstream(chan);
3635  }
3636 
3637  /* Check each state */
3638  switch (speech->state) {
3640  /* If the stream is done, start timeout calculation */
3641  if ((timeout > 0) && start == 0 && ((!ast_channel_stream(chan)) || (ast_channel_streamid(chan) == -1 && ast_channel_timingfunc(chan) == NULL))) {
3642  ast_stopstream(chan);
3643  time(&start);
3644  }
3645  /* Write audio frame data into speech engine if possible */
3646  if (fr && fr->frametype == AST_FRAME_VOICE)
3647  ast_speech_write(speech, fr->data.ptr, fr->datalen);
3648  break;
3649  case AST_SPEECH_STATE_WAIT:
3650  /* Cue waiting sound if not already playing */
3651  if ((!ast_channel_stream(chan)) || (ast_channel_streamid(chan) == -1 && ast_channel_timingfunc(chan) == NULL)) {
3652  ast_stopstream(chan);
3653  /* If a processing sound exists, or is not none - play it */
3654  if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none"))
3655  speech_streamfile(chan, speech->processing_sound, ast_channel_language(chan), 0);
3656  }
3657  break;
3658  case AST_SPEECH_STATE_DONE:
3659  /* Get the results */
3660  speech->results = ast_speech_results_get(speech);
3661  /* Change state to not ready */
3663  reason = "speech";
3664  break;
3665  default:
3666  break;
3667  }
3668  ast_mutex_unlock(&speech->lock);
3669 
3670  /* Check frame for DTMF or hangup */
3671  if (fr) {
3672  if (fr->frametype == AST_FRAME_DTMF) {
3673  reason = "dtmf";
3674  dtmf = fr->subclass.integer;
3675  } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_HANGUP) {
3676  reason = "hangup";
3677  }
3678  ast_frfree(fr);
3679  }
3680  }
3681 
3682  if (!strcasecmp(reason, "speech")) {
3683  /* Build string containing speech results */
3684  for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) {
3685  /* Build result string */
3686  ast_build_string(&buf, &left, "%sscore%d=%d text%d=\"%s\" grammar%d=%s", (i > 0 ? " " : ""), i, result->score, i, result->text, i, result->grammar);
3687  /* Increment result count */
3688  i++;
3689  }
3690  /* Print out */
3691  ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
3692  } else if (!strcasecmp(reason, "dtmf")) {
3693  ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
3694  } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
3695  ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
3696  } else {
3697  ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset);
3698  }
3699 
3700  return RESULT_SUCCESS;
3701 }
int state
Definition: speech.h:59
void ast_speech_start(struct ast_speech *speech)
Indicate to the speech engine that audio is now going to start being written.
Definition: res_speech.c:121
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RESULT_SHOWUSAGE
Definition: cli.h:41
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int timeout
Definition: cdr_mysql.c:86
static int tmp()
Definition: bt_open.c:389
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
struct ast_speech_result * ast_speech_results_get(struct ast_speech *speech)
Get speech recognition results.
Definition: res_speech.c:89
static int speech_streamfile(struct ast_channel *chan, const char *filename, const char *preflang, int offset)
Definition: res_agi.c:3537
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
char * grammar
Definition: speech.h:116
struct ast_frame_subclass subclass
#define ast_strlen_zero(foo)
Definition: strings.h:52
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:1048
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: main/utils.c:1919
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
int ast_speech_change_state(struct ast_speech *speech, int state)
Change state of a speech structure.
Definition: res_speech.c:267
struct ast_speech_result * results
Definition: speech.h:65
struct ast_sched_context * ast_channel_sched(const struct ast_channel *chan)
int ast_channel_streamid(const struct ast_channel *chan)
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
struct ast_filestream * ast_channel_stream(const struct ast_channel *chan)
#define ast_clear_flag(p, flag)
Definition: utils.h:77
ast_mutex_t lock
Definition: speech.h:53
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
#define ast_frfree(fr)
static PGresult * result
Definition: cel_pgsql.c:88
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:431
Data structure associated with a single frame of data.
const char * ast_channel_language(const struct ast_channel *chan)
char * processing_sound
Definition: speech.h:57
union ast_frame::@263 data
enum ast_frame_type frametype
static struct ast_str * prompt
Definition: asterisk.c:2725
int ast_speech_write(struct ast_speech *speech, void *data, int len)
Write audio to the speech engine.
Definition: res_speech.c:143
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
ast_timing_func_t ast_channel_timingfunc(const struct ast_channel *chan)
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ handle_speechset()

static int handle_speechset ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3434 of file res_agi.c.

References ast_agi_send(), ast_speech_change(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

3435 {
3436  /* Check for minimum arguments */
3437  if (argc != 4)
3438  return RESULT_SHOWUSAGE;
3439 
3440  /* Check to make sure speech structure exists */
3441  if (!agi->speech) {
3442  ast_agi_send(agi->fd, chan, "200 result=0\n");
3443  return RESULT_SUCCESS;
3444  }
3445 
3446  ast_speech_change(agi->speech, argv[2], argv[3]);
3447  ast_agi_send(agi->fd, chan, "200 result=1\n");
3448 
3449  return RESULT_SUCCESS;
3450 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
int ast_speech_change(struct ast_speech *speech, const char *name, const char *value)
Change an engine specific attribute.
Definition: res_speech.c:168

◆ handle_speechunloadgrammar()

static int handle_speechunloadgrammar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3483 of file res_agi.c.

References ast_agi_send(), ast_speech_grammar_unload(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

3484 {
3485  if (argc != 4)
3486  return RESULT_SHOWUSAGE;
3487 
3488  if (!agi->speech) {
3489  ast_agi_send(agi->fd, chan, "200 result=0\n");
3490  return RESULT_SUCCESS;
3491  }
3492 
3493  if (ast_speech_grammar_unload(agi->speech, argv[3]))
3494  ast_agi_send(agi->fd, chan, "200 result=0\n");
3495  else
3496  ast_agi_send(agi->fd, chan, "200 result=1\n");
3497 
3498  return RESULT_SUCCESS;
3499 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ast_speech_grammar_unload(struct ast_speech *speech, const char *grammar_name)
Unload a grammar.
Definition: res_speech.c:83
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_streamfile()

static int handle_streamfile ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2557 of file res_agi.c.

References ast_agi_send(), ast_applystream(), ast_channel_language(), ast_channel_name(), ast_channel_stream(), ast_channel_writeformat(), ast_debug, ast_format_get_name(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verb, ast_waitstream_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, pbx_builtin_setvar_helper(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, S_OR, and ast_filestream::vfs.

2558 {
2559  int res;
2560  struct ast_filestream *fs, *vfs;
2561  long sample_offset = 0, max_length;
2562  const char *edigits = "";
2563 
2564  if (argc < 4 || argc > 5) {
2565  return RESULT_SHOWUSAGE;
2566  }
2567 
2568  if (argv[3]) {
2569  edigits = argv[3];
2570  }
2571 
2572  if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1)) {
2573  return RESULT_SHOWUSAGE;
2574  }
2575 
2576  if (!(fs = ast_openstream(chan, argv[2], ast_channel_language(chan)))) {
2577  ast_agi_send(agi->fd, chan, "200 result=-1 endpos=%ld\n", sample_offset);
2578  return RESULT_FAILURE;
2579  }
2580 
2581  if ((vfs = ast_openvstream(chan, argv[2], ast_channel_language(chan)))) {
2582  ast_debug(1, "Ooh, found a video stream, too\n");
2583  }
2584  ast_verb(3, "<%s> Playing '%s.%s' (escape_digits=%s) (sample_offset %ld) (language '%s')\n",
2586  edigits, sample_offset, S_OR(ast_channel_language(chan), "default"));
2587 
2588  ast_seekstream(fs, 0, SEEK_END);
2589  max_length = ast_tellstream(fs);
2590  ast_seekstream(fs, sample_offset, SEEK_SET);
2591  res = ast_applystream(chan, fs);
2592  if (vfs) {
2593  ast_applystream(chan, vfs);
2594  }
2595  ast_playstream(fs);
2596  if (vfs) {
2597  ast_playstream(vfs);
2598  }
2599 
2600  res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
2601  /* this is to check for if ast_waitstream closed the stream, we probably are at
2602  * the end of the stream, return that amount, else check for the amount */
2603  sample_offset = (ast_channel_stream(chan)) ? ast_tellstream(fs) : max_length;
2604  ast_stopstream(chan);
2605  if (res == 1) {
2606  /* Stop this command, don't print a result line, as there is a new command */
2607  return RESULT_SUCCESS;
2608  }
2609  ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
2610  pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", res ? "FAILED" : "SUCCESS");
2611 
2612  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2613 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ctrl
Definition: agi.h:37
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define ast_verb(level,...)
Definition: logger.h:463
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:1048
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int ast_playstream(struct ast_filestream *s)
Play a open stream on a channel.
Definition: file.c:1026
struct ast_filestream * ast_openvstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:812
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applys a open stream to a channel.
Definition: file.c:1020
int fd
Definition: agi.h:35
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:1038
int audio
Definition: agi.h:36
struct ast_filestream * ast_channel_stream(const struct ast_channel *chan)
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_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd, int monfd)
Definition: file.c:1785
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_language(const struct ast_channel *chan)
struct ast_filestream * vfs
Definition: mod_format.h:110
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
#define RESULT_FAILURE
Definition: cli.h:42
struct ast_filestream * ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:755

◆ handle_tddmode()

static int handle_tddmode ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2451 of file res_agi.c.

References ast_agi_send(), ast_channel_setoption(), AST_OPTION_TDD, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2452 {
2453  int res, x;
2454 
2455  if (argc != 3)
2456  return RESULT_SHOWUSAGE;
2457 
2458  if (!strncasecmp(argv[2],"on",2)) {
2459  x = 1;
2460  } else {
2461  x = 0;
2462  }
2463  if (!strncasecmp(argv[2],"mate",4)) {
2464  x = 2;
2465  }
2466  if (!strncasecmp(argv[2],"tdd",3)) {
2467  x = 1;
2468  }
2469  res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
2470  if (res) {
2471  /* Set channel option failed */
2472  ast_agi_send(agi->fd, chan, "200 result=0\n");
2473  } else {
2474  ast_agi_send(agi->fd, chan, "200 result=1\n");
2475  }
2476  return RESULT_SUCCESS;
2477 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
#define AST_OPTION_TDD
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7522
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_verbose()

static int handle_verbose ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 3273 of file res_agi.c.

References ast_agi_send(), ast_channel_data(), ast_verb, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

3274 {
3275  int level = 0;
3276 
3277  if (argc < 2)
3278  return RESULT_SHOWUSAGE;
3279 
3280  if (argv[2])
3281  sscanf(argv[2], "%30d", &level);
3282 
3283  ast_verb(level, "%s: %s\n", ast_channel_data(chan), argv[1]);
3284 
3285  ast_agi_send(agi->fd, chan, "200 result=1\n");
3286 
3287  return RESULT_SUCCESS;
3288 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
#define ast_verb(level,...)
Definition: logger.h:463
int fd
Definition: agi.h:35
const char * ast_channel_data(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ handle_waitfordigit()

static int handle_waitfordigit ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2382 of file res_agi.c.

References ast_agi_send(), ast_waitfordigit_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, NULL, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2383 {
2384  int res, to;
2385 
2386  if (argc != 4)
2387  return RESULT_SHOWUSAGE;
2388  if (sscanf(argv[3], "%30d", &to) != 1)
2389  return RESULT_SHOWUSAGE;
2390  res = ast_waitfordigit_full(chan, to, NULL, agi->audio, agi->ctrl);
2391  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2392  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2393 }
#define RESULT_SHOWUSAGE
Definition: cli.h:41
int ctrl
Definition: agi.h:37
#define NULL
Definition: resample.c:96
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40
int ast_waitfordigit_full(struct ast_channel *c, int ms, const char *breakon, int audiofd, int ctrlfd)
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to mon...
Definition: channel.c:3248
#define RESULT_FAILURE
Definition: cli.h:42

◆ help_workhorse()

static char* help_workhorse ( int  fd,
const char *const  match[] 
)
static

Definition at line 3757 of file res_agi.c.

References ast_cli(), ast_join, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_SUCCESS, agi_command::cmda, agi_command::dead, agi_command::list, MAX_CMD_LEN, S_OR, and agi_command::summary.

Referenced by handle_cli_agi_show().

3758 {
3759  char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN];
3760  struct agi_command *e;
3761 
3762  if (match)
3763  ast_join(matchstr, sizeof(matchstr), match);
3764 
3765  ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description");
3768  if (!e->cmda[0])
3769  break;
3770  /* Hide commands that start with '_' */
3771  if ((e->cmda[0])[0] == '_')
3772  continue;
3773  ast_join(fullcmd, sizeof(fullcmd), e->cmda);
3774  if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
3775  continue;
3776  ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, S_OR(e->summary, "Not available"));
3777  }
3779 
3780  return CLI_SUCCESS;
3781 }
const char *const summary
Definition: agi.h:48
#define ast_join(s, len, w)
Definition: strings.h:483
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define MAX_CMD_LEN
Definition: res_agi.c:1389
const int dead
Definition: agi.h:52
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
struct agi_command::@219 list
#define CLI_SUCCESS
Definition: cli.h:44
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79

◆ launch_asyncagi()

static enum agi_result launch_asyncagi ( struct ast_channel chan,
int  argc,
char *  argv[],
int *  efd 
)
static

Definition at line 1787 of file res_agi.c.

References add_to_agi(), AGI_BUF_SIZE, agi_handle_command(), AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, AMI_BUF_SIZE, ast_channel_name(), ast_channel_publish_cached_blob(), ast_check_hangup(), ast_check_hangup_locked(), ast_debug, ast_json_object_set(), ast_json_pack(), ast_json_string_create(), ast_json_unref(), ast_log, ast_speech_destroy(), ast_strlen_zero, ast_uri_encode(), ast_uri_http, ast_waitfor(), async_agi_read_frame(), agi_state::audio, agi_cmd::cmd_buffer, agi_cmd::cmd_id, agi_state::ctrl, errno, agi_state::fast, agi_state::fd, free_agi_cmd(), get_agi_cmd(), LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, setup_env(), agi_state::speech, and timeout.

Referenced by launch_script().

1788 {
1789 /* This buffer sizes might cause truncation if the AGI command writes more data
1790  than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command
1791  that writes a response larger than 1024 bytes?, I don't think so, most of
1792  them are just result=blah stuff. However probably if GET VARIABLE is called
1793  and the variable has large amount of data, that could be a problem. We could
1794  make this buffers dynamic, but let's leave that as a second step.
1795 
1796  AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe
1797  number. Some characters of AGI buf will be url encoded to be sent to manager
1798  clients. An URL encoded character will take 3 bytes, but again, to cause
1799  truncation more than about 70% of the AGI buffer should be URL encoded for
1800  that to happen. Not likely at all.
1801 
1802  On the other hand. I wonder if read() could eventually return less data than
1803  the amount already available in the pipe? If so, how to deal with that?
1804  So far, my tests on Linux have not had any problems.
1805  */
1806 #define AGI_BUF_SIZE 1024
1807 #define AMI_BUF_SIZE 2048
1808  enum agi_result cmd_status;
1809  struct agi_cmd *cmd;
1810  int res;
1811  int fds[2];
1812  int hungup;
1813  int timeout = 100;
1814  char agi_buffer[AGI_BUF_SIZE + 1];
1815  char ami_buffer[AMI_BUF_SIZE];
1816  enum agi_result returnstatus = AGI_RESULT_SUCCESS;
1817  AGI async_agi;
1818  RAII_VAR(struct ast_json *, startblob, NULL, ast_json_unref);
1819 
1820  if (efd) {
1821  ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n");
1822  return AGI_RESULT_FAILURE;
1823  }
1824 
1825  /* add AsyncAGI datastore to the channel */
1826  if (add_to_agi(chan)) {
1827  ast_log(LOG_ERROR, "Failed to start Async AGI on channel %s\n", ast_channel_name(chan));
1828  return AGI_RESULT_FAILURE;
1829  }
1830 
1831  /* this pipe allows us to create a "fake" AGI struct to use
1832  the AGI commands */
1833  res = pipe(fds);
1834  if (res) {
1835  ast_log(LOG_ERROR, "Failed to create Async AGI pipe\n");
1836  /*
1837  * Intentionally do not remove the datastore added with
1838  * add_to_agi() the from channel. It will be removed when the
1839  * channel is hung up anyway.
1840  */
1841  return AGI_RESULT_FAILURE;
1842  }
1843 
1844  /* handlers will get the pipe write fd and we read the AGI responses
1845  from the pipe read fd */
1846  async_agi.fd = fds[1];
1847  async_agi.ctrl = fds[1];
1848  async_agi.audio = -1; /* no audio support */
1849  async_agi.fast = 0;
1850  async_agi.speech = NULL;
1851 
1852  /* notify possible manager users of a new channel ready to
1853  receive commands */
1854  setup_env(chan, "async", fds[1], 0, argc, argv);
1855  /* read the environment */
1856  res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1857  if (res <= 0) {
1858  ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s: %s\n",
1859  ast_channel_name(chan), res < 0 ? strerror(errno) : "EOF");
1860  returnstatus = AGI_RESULT_FAILURE;
1861  goto async_agi_abort;
1862  }
1863  agi_buffer[res] = '\0';
1864  /* encode it and send it thru the manager so whoever is going to take
1865  care of AGI commands on this channel can decide which AGI commands
1866  to execute based on the setup info */
1867  ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
1868  startblob = ast_json_pack("{s: s}", "Env", ami_buffer);
1869 
1870  ast_channel_publish_cached_blob(chan, agi_async_start_type(), startblob);
1871 
1872  hungup = ast_check_hangup_locked(chan);
1873 
1874  for (;;) {
1875  /*
1876  * Process as many commands as we can. Commands are added via
1877  * the manager or the cli threads.
1878  */
1879  while (!hungup) {
1880  RAII_VAR(struct ast_json *, execblob, NULL, ast_json_unref);
1881  res = get_agi_cmd(chan, &cmd);
1882 
1883  if (res) {
1884  returnstatus = AGI_RESULT_FAILURE;
1885  goto async_agi_done;
1886  } else if (!cmd) {
1887  break;
1888  }
1889 
1890  /* OK, we have a command, let's call the command handler. */
1891  cmd_status = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0);
1892 
1893  /*
1894  * The command handler must have written to our fake AGI struct
1895  * fd (the pipe), let's read the response.
1896  */
1897  res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1898  if (res <= 0) {
1899  ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s: %s\n",
1900  ast_channel_name(chan), res < 0 ? strerror(errno) : "EOF");
1901  free_agi_cmd(cmd);
1902  returnstatus = AGI_RESULT_FAILURE;
1903  goto async_agi_done;
1904  }
1905  /*
1906  * We have a response, let's send the response thru the manager.
1907  * Include the CommandID if it was specified when the command
1908  * was added.
1909  */
1910  agi_buffer[res] = '\0';
1911  ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
1912 
1913  execblob = ast_json_pack("{s: s}", "Result", ami_buffer);
1914  if (execblob && !ast_strlen_zero(cmd->cmd_id)) {
1915  ast_json_object_set(execblob, "CommandId", ast_json_string_create(cmd->cmd_id));
1916  }
1917  ast_channel_publish_cached_blob(chan, agi_async_exec_type(), execblob);
1918 
1919  free_agi_cmd(cmd);
1920 
1921  /*
1922  * Check the command status to determine if we should continue
1923  * executing more commands.
1924  */
1925  hungup = ast_check_hangup(chan);
1926  switch (cmd_status) {
1927  case AGI_RESULT_FAILURE:
1928  if (!hungup) {
1929  /* The failure was not because of a hangup. */
1930  returnstatus = AGI_RESULT_FAILURE;
1931  goto async_agi_done;
1932  }
1933  break;
1935  /* Only the "asyncagi break" command does this. */
1936  returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1937  goto async_agi_done;
1938  default:
1939  break;
1940  }
1941  }
1942 
1943  if (!hungup) {
1944  /* Wait a bit for a frame to read or to poll for a new command. */
1945  res = ast_waitfor(chan, timeout);
1946  if (res < 0) {
1947  ast_debug(1, "ast_waitfor returned <= 0 on chan %s\n", ast_channel_name(chan));
1948  returnstatus = AGI_RESULT_FAILURE;
1949  break;
1950  }
1951  } else {
1952  /*
1953  * Read the channel control queue until it is dry so we can
1954  * quit.
1955  */
1956  res = 1;
1957  }
1958  if (0 < res) {
1959  do {
1960  cmd_status = async_agi_read_frame(chan);
1961  if (cmd_status != AGI_RESULT_SUCCESS) {
1962  returnstatus = cmd_status;
1963  goto async_agi_done;
1964  }
1965  hungup = ast_check_hangup(chan);
1966  } while (hungup);
1967  } else {
1968  hungup = ast_check_hangup(chan);
1969  }
1970  }
1971 async_agi_done:
1972 
1973  if (async_agi.speech) {
1974  ast_speech_destroy(async_agi.speech);
1975  }
1976  /* notify manager users this channel cannot be controlled anymore by Async AGI */
1977  ast_channel_publish_cached_blob(chan, agi_async_end_type(), NULL);
1978 
1979 async_agi_abort:
1980  /* close the pipe */
1981  close(fds[0]);
1982  close(fds[1]);
1983 
1984  /*
1985  * Intentionally do not remove the datastore added with
1986  * add_to_agi() the from channel. There might be commands still
1987  * in the queue or in-flight to us and AsyncAGI may get called
1988  * again. The datastore destructor will be called on channel
1989  * destruction anyway.
1990  */
1991 
1992  if (returnstatus == AGI_RESULT_SUCCESS) {
1993  returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1994  }
1995  return returnstatus;
1996 
1997 #undef AGI_BUF_SIZE
1998 #undef AMI_BUF_SIZE
1999 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
agi_result
Definition: res_agi.c:1412
int ast_speech_destroy(struct ast_speech *speech)
Destroy a speech structure.
Definition: res_speech.c:240
static enum agi_result async_agi_read_frame(struct ast_channel *chan)
Definition: res_agi.c:1759
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message using the latest snapshot from the cache.
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:459
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition: main/utils.c:577
#define AMI_BUF_SIZE
int ctrl
Definition: agi.h:37
#define NULL
Definition: resample.c:96
static int get_agi_cmd(struct ast_channel *chan, struct agi_cmd **cmd)
Retrieve the list head to the requested channel&#39;s AGI datastore.
Definition: res_agi.c:1558
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:404
#define ast_strlen_zero(foo)
Definition: strings.h:52
char * cmd_id
Definition: res_agi.c:1518
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#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:911
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
Definition: res_agi.c:2318
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
#define LOG_ERROR
Definition: logger.h:285
static int add_to_agi(struct ast_channel *chan)
Definition: res_agi.c:1613
int errno
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
int audio
Definition: agi.h:36
static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
Definition: res_agi.c:4021
#define AGI_BUF_SIZE
unsigned int fast
Definition: agi.h:38
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
char * cmd_buffer
Definition: res_agi.c:1517
const char * ast_channel_name(const struct ast_channel *chan)
static void free_agi_cmd(struct agi_cmd *cmd)
Definition: res_agi.c:1522
Abstract JSON element (object, array, string, int, ...).
const struct ast_flags ast_uri_http
Definition: main/utils.c:573
Definition: agi.h:34

◆ launch_ha_netscript()

static enum agi_result launch_ha_netscript ( char *  agiurl,
char *  argv[],
int *  fds 
)
static

Definition at line 2146 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_NOTFOUND, ast_log, ast_srv_cleanup(), ast_srv_lookup(), ast_strdupa, context, host, launch_netscript(), LOG_WARNING, NULL, result, service, and SRV_PREFIX.

Referenced by launch_script().

2147 {
2148  char *host, *script;
2149  enum agi_result result;
2150  struct srv_context *context = NULL;
2151  int srv_ret;
2152  char service[256];
2153  char resolved_uri[1024];
2154  const char *srvhost;
2155  unsigned short srvport;
2156 
2157  /* format of agiurl is "hagi://host.domain[:port][/script/name]" */
2158  if (strlen(agiurl) < 7) { /* Remove hagi:// */
2159  ast_log(LOG_WARNING, "An error occurred parsing the AGI URI: %s", agiurl);
2160  return AGI_RESULT_FAILURE;
2161  }
2162  host = ast_strdupa(agiurl + 7);
2163 
2164  /* Strip off any script name */
2165  if ((script = strchr(host, '/'))) {
2166  *script++ = '\0';
2167  } else {
2168  script = "";
2169  }
2170 
2171  if (strchr(host, ':')) {
2172  ast_log(LOG_WARNING, "Specifying a port number disables SRV lookups: %s\n", agiurl);
2173  return launch_netscript(agiurl + 1, argv, fds); /* +1 to strip off leading h from hagi:// */
2174  }
2175 
2176  snprintf(service, sizeof(service), "%s%s", SRV_PREFIX, host);
2177 
2178  while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) {
2179  snprintf(resolved_uri, sizeof(resolved_uri), "agi://%s:%d/%s", srvhost, srvport, script);
2180  result = launch_netscript(resolved_uri, argv, fds);
2181  if (result == AGI_RESULT_FAILURE || result == AGI_RESULT_NOTFOUND) {
2182  ast_log(LOG_WARNING, "AGI request failed for host '%s' (%s:%d)\n", host, srvhost, srvport);
2183  } else {
2184  /* The script launched so we must cleanup the context. */
2185  ast_srv_cleanup(&context);
2186  return result;
2187  }
2188  }
2189  /*
2190  * The DNS SRV lookup failed or we ran out of servers to check.
2191  * ast_srv_lookup() has already cleaned up the context for us.
2192  */
2193  if (srv_ret < 0) {
2194  ast_log(LOG_WARNING, "SRV lookup failed for %s\n", agiurl);
2195  }
2196 
2197  return AGI_RESULT_FAILURE;
2198 }
agi_result
Definition: res_agi.c:1412
#define LOG_WARNING
Definition: logger.h:274
void ast_srv_cleanup(struct srv_context **context)
Cleanup resources associated with ast_srv_lookup.
Definition: srv.c:248
enum ast_cc_service_type service
Definition: chan_sip.c:949
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static char host[256]
Definition: muted.c:77
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_srv_lookup(struct srv_context **context, const char *service, const char **host, unsigned short *port)
Retrieve set of SRV lookups, in order.
Definition: srv.c:202
static PGresult * result
Definition: cel_pgsql.c:88
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define SRV_PREFIX
Definition: res_agi.c:1392
static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
Definition: res_agi.c:2053

◆ launch_netscript()

static enum agi_result launch_netscript ( char *  agiurl,
char *  argv[],
int *  fds 
)
static

Definition at line 2053 of file res_agi.c.

References AGI_PORT, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS_FAST, AST_AF_UNSPEC, ast_agi_send(), ast_connect(), ast_debug, ast_free, ast_log, ast_sockaddr_port, ast_sockaddr_resolve(), ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_socket_nonblock, ast_strdupa, ast_strlen_zero, errno, handle_connection(), host, LOG_WARNING, NULL, and ast_sockaddr::ss.

Referenced by launch_ha_netscript(), and launch_script().

2054 {
2055  int s = 0;
2056  char *host, *script;
2057  int num_addrs = 0, i = 0;
2058  struct ast_sockaddr *addrs;
2059 
2060  /* agiurl is "agi://host.domain[:port][/script/name]" */
2061  host = ast_strdupa(agiurl + 6); /* Remove agi:// */
2062 
2063  /* Strip off any script name */
2064  if ((script = strchr(host, '/'))) {
2065  *script++ = '\0';
2066  } else {
2067  script = "";
2068  }
2069 
2070  if (!(num_addrs = ast_sockaddr_resolve(&addrs, host, 0, AST_AF_UNSPEC))) {
2071  ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
2072  return AGI_RESULT_FAILURE;
2073  }
2074 
2075  for (i = 0; i < num_addrs; i++) {
2076  if (!ast_sockaddr_port(&addrs[i])) {
2077  ast_sockaddr_set_port(&addrs[i], AGI_PORT);
2078  }
2079 
2080  if ((s = ast_socket_nonblock(addrs[i].ss.ss_family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
2081  ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
2082  continue;
2083  }
2084 
2085  if (ast_connect(s, &addrs[i]) && errno == EINPROGRESS) {
2086 
2087  if (handle_connection(agiurl, addrs[i], s)) {
2088  close(s);
2089  continue;
2090  }
2091 
2092  } else {
2093  ast_log(LOG_WARNING, "Connection to %s failed with unexpected error: %s\n",
2094  ast_sockaddr_stringify(&addrs[i]), strerror(errno));
2095  }
2096 
2097  break;
2098  }
2099 
2100  ast_free(addrs);
2101 
2102  if (i == num_addrs) {
2103  ast_log(LOG_WARNING, "Couldn't connect to any host. FastAGI failed.\n");
2104  return AGI_RESULT_FAILURE;
2105  }
2106 
2107  if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) {
2108  if (errno != EINTR) {
2109  ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
2110  close(s);
2111  return AGI_RESULT_FAILURE;
2112  }
2113  }
2114 
2115  /* If we have a script parameter, relay it to the fastagi server */
2116  /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */
2117  if (!ast_strlen_zero(script)) {
2118  ast_agi_send(s, NULL, "agi_network_script: %s\n", script);
2119  }
2120 
2121  ast_debug(4, "Wow, connected!\n");
2122  fds[0] = s;
2123  fds[1] = s;
2124  return AGI_RESULT_SUCCESS_FAST;
2125 }
struct sockaddr_storage ss
Definition: netsock2.h:98
static int handle_connection(const char *agiurl, const struct ast_sockaddr addr, const int netsockfd)
Definition: res_agi.c:2012
#define LOG_WARNING
Definition: logger.h:274
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1043
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static char host[256]
Definition: muted.c:77
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ast_free(a)
Definition: astmm.h:182
#define AGI_PORT
Definition: res_agi.c:1407
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
int ast_connect(int sockfd, const struct ast_sockaddr *addr)
Wrapper around connect(2) that uses struct ast_sockaddr.
Definition: netsock2.c:595
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition: netsock2.c:280

◆ launch_script()

static enum agi_result launch_script ( struct ast_channel chan,
char *  script,
int  argc,
char *  argv[],
int *  fds,
int *  efd,
int *  opid 
)
static

Definition at line 2200 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_NOTFOUND, AGI_RESULT_SUCCESS, ast_child_verbose(), ast_close_fds_above_n(), ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_CONFIG_FILE, ast_config_AST_DATA_DIR, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_MONITOR_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_VAR_DIR, ast_fd_set_flags, ast_log, ast_safe_fork(), ast_set_priority(), ast_verb, errno, launch_asyncagi(), launch_ha_netscript(), launch_netscript(), LOG_WARNING, NULL, setenv(), and tmp().

Referenced by agi_exec_full().

2201 {
2202  char tmp[256];
2203  int pid, toast[2], fromast[2], audio[2], res;
2204  struct stat st;
2205 
2206  if (!strncasecmp(script, "agi://", 6)) {
2207  return (efd == NULL) ? launch_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
2208  }
2209  if (!strncasecmp(script, "hagi://", 7)) {
2210  return (efd == NULL) ? launch_ha_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
2211  }
2212  if (!strncasecmp(script, "agi:async", sizeof("agi:async") - 1)) {
2213  return launch_asyncagi(chan, argc, argv, efd);
2214  }
2215 
2216  if (script[0] != '/') {
2217  snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script);
2218  script = tmp;
2219  }
2220 
2221  /* Before even trying let's see if the file actually exists */
2222  if (stat(script, &st)) {
2223  ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script);
2224  return AGI_RESULT_NOTFOUND;
2225  }
2226 
2227  if (pipe(toast)) {
2228  ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
2229  return AGI_RESULT_FAILURE;
2230  }
2231  if (pipe(fromast)) {
2232  ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
2233  close(toast[0]);
2234  close(toast[1]);
2235  return AGI_RESULT_FAILURE;
2236  }
2237  if (efd) {
2238  if (pipe(audio)) {
2239  ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
2240  close(fromast[0]);
2241  close(fromast[1]);
2242  close(toast[0]);
2243  close(toast[1]);
2244  return AGI_RESULT_FAILURE;
2245  }
2246 
2247  res = ast_fd_set_flags(audio[1], O_NONBLOCK);
2248  if (res < 0) {
2249  ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
2250  close(fromast[0]);
2251  close(fromast[1]);
2252  close(toast[0]);
2253  close(toast[1]);
2254  close(audio[0]);
2255  close(audio[1]);
2256  return AGI_RESULT_FAILURE;
2257  }
2258  }
2259 
2260  if ((pid = ast_safe_fork(1)) < 0) {
2261  ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
2262  return AGI_RESULT_FAILURE;
2263  }
2264  if (!pid) {
2265  /* Pass paths to AGI via environmental variables */
2266  setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
2267  setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
2268  setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
2269  setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
2270  setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
2271  setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
2272  setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
2273  setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
2274  setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
2275  setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
2276  setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
2277 
2278  /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
2279  ast_set_priority(0);
2280 
2281  /* Redirect stdin and out, provide enhanced audio channel if desired */
2282  dup2(fromast[0], STDIN_FILENO);
2283  dup2(toast[1], STDOUT_FILENO);
2284  if (efd)
2285  dup2(audio[0], STDERR_FILENO + 1);
2286  else
2287  close(STDERR_FILENO + 1);
2288 
2289  /* Close everything but stdin/out/error */
2290  ast_close_fds_above_n(STDERR_FILENO + 1);
2291 
2292  /* Execute script */
2293  /* XXX argv should be deprecated in favor of passing agi_argX paramaters */
2294  execv(script, argv);
2295  /* Can't use ast_log since FD's are closed */
2296  ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno));
2297  /* Special case to set status of AGI to failure */
2298  fprintf(stdout, "failure\n");
2299  fflush(stdout);
2300  _exit(1);
2301  }
2302  ast_verb(3, "Launched AGI Script %s\n", script);
2303  fds[0] = toast[0];
2304  fds[1] = fromast[1];
2305  if (efd)
2306  *efd = audio[1];
2307  /* close what we're not using in the parent */
2308  close(toast[1]);
2309  close(fromast[0]);
2310 
2311  if (efd)
2312  close(audio[0]);
2313 
2314  *opid = pid;
2315  return AGI_RESULT_SUCCESS;
2316 }
const char * ast_config_AST_KEY_DIR
Definition: options.c:161
const char * ast_config_AST_MODULE_DIR
Definition: options.c:153
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: main/app.c:3042
static enum agi_result launch_asyncagi(struct ast_channel *chan, int argc, char *argv[], int *efd)
Definition: res_agi.c:1787
const char * ast_config_AST_RUN_DIR
Definition: options.c:162
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
void ast_child_verbose(int level, const char *fmt,...)
Definition: logger.c:850
const char * ast_config_AST_CONFIG_FILE
Definition: options.c:152
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition: utils.h:1009
#define ast_log
Definition: astobj2.c:42
const char * ast_config_AST_AGI_DIR
Definition: options.c:160
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1799
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
static enum agi_result launch_ha_netscript(char *agiurl, char *argv[], int *fds)
Definition: res_agi.c:2146
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
int errno
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: main/app.c:3047
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
const char * ast_config_AST_MONITOR_DIR
Definition: options.c:155
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
int setenv(const char *name, const char *value, int overwrite)
const char * ast_config_AST_VAR_DIR
Definition: options.c:157
static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
Definition: res_agi.c:2053

◆ load_module()

static int load_module ( void  )
static

Definition at line 4682 of file res_agi.c.

References action_add_agi_cmd(), agi_exec(), app, ARRAY_LEN, ast_agi_register_multiple(), ast_cli_register_multiple, ast_manager_register_xml, AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, ast_register_application_xml, AST_TEST_REGISTER, ASTERISK_GPL_KEY, deadagi_exec(), deadapp, eagi_exec(), eapp, EVENT_FLAG_AGI, ast_module_info::self, STASIS_MESSAGE_TYPE_INIT, and unload_module().

4683 {
4684  int err = 0;
4685 
4686  err |= STASIS_MESSAGE_TYPE_INIT(agi_exec_start_type);
4687  err |= STASIS_MESSAGE_TYPE_INIT(agi_exec_end_type);
4688  err |= STASIS_MESSAGE_TYPE_INIT(agi_async_start_type);
4689  err |= STASIS_MESSAGE_TYPE_INIT(agi_async_exec_type);
4690  err |= STASIS_MESSAGE_TYPE_INIT(agi_async_end_type);
4691 
4698 
4699  AST_TEST_REGISTER(test_agi_null_docs);
4700 
4701  if (err) {
4702  unload_module();
4703  return AST_MODULE_LOAD_DECLINE;
4704  }
4705 
4706  return AST_MODULE_LOAD_SUCCESS;
4707 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static char * deadapp
Definition: res_agi.c:1398
static int eagi_exec(struct ast_channel *chan, const char *data)
Definition: res_agi.c:4569
static int action_add_agi_cmd(struct mansession *s, const struct message *m)
Add a new command to execute by the Async AGI application.
Definition: res_agi.c:1709
static int agi_exec(struct ast_channel *chan, const char *data)
Definition: res_agi.c:4561
struct ast_module * self
Definition: module.h:342
static struct agi_command commands[]
AGI commands list.
Definition: res_agi.c:3706
static struct ast_cli_entry cli_agi[]
Definition: res_agi.c:4617
#define EVENT_FLAG_AGI
Definition: manager.h:84
int AST_OPTIONAL_API_NAME() ast_agi_register_multiple(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
Definition: res_agi.c:3863
static char * app
Definition: res_agi.c:1394
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static char * eapp
Definition: res_agi.c:1396
static int deadagi_exec(struct ast_channel *chan, const char *data)
Definition: res_agi.c:4611
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
static int unload_module(void)
Definition: res_agi.c:4664
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ parse_args()

static int parse_args ( char *  s,
int *  max,
const char *  argv[] 
)
static

Definition at line 3947 of file res_agi.c.

References ast_log, LOG_WARNING, MAX_ARGS, and NULL.

Referenced by agi_handle_command().

3948 {
3949  int x = 0, quoted = 0, escaped = 0, whitespace = 1;
3950  char *cur;
3951 
3952  cur = s;
3953  while(*s) {
3954  switch(*s) {
3955  case '"':
3956  /* If it's escaped, put a literal quote */
3957  if (escaped)
3958  goto normal;
3959  else
3960  quoted = !quoted;
3961  if (quoted && whitespace) {
3962  /* If we're starting a quote, coming off white space start a new word, too */
3963  argv[x++] = cur;
3964  whitespace=0;
3965  }
3966  escaped = 0;
3967  break;
3968  case ' ':
3969  case '\t':
3970  if (!quoted && !escaped) {
3971  /* If we're not quoted, mark this as whitespace, and
3972  end the previous argument */
3973  whitespace = 1;
3974  *(cur++) = '\0';
3975  } else
3976  /* Otherwise, just treat it as anything else */
3977  goto normal;
3978  break;
3979  case '\\':
3980  /* If we're escaped, print a literal, otherwise enable escaping */
3981  if (escaped) {
3982  goto normal;
3983  } else {
3984  escaped=1;
3985  }
3986  break;
3987  default:
3988 normal:
3989  if (whitespace) {
3990  if (x >= MAX_ARGS -1) {
3991  ast_log(LOG_WARNING, "Too many arguments, truncating\n");
3992  break;
3993  }
3994  /* Coming off of whitespace, start the next argument */
3995  argv[x++] = cur;
3996  whitespace=0;
3997  }
3998  *(cur++) = *s;
3999  escaped=0;
4000  }
4001  s++;
4002  }
4003  /* Null terminate */
4004  *(cur++) = '\0';
4005  argv[x] = NULL;
4006  *max = x;
4007  return 0;
4008 }
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define MAX_ARGS
Definition: res_agi.c:1388
#define max(a, b)
Definition: f2c.h:198

◆ publish_async_exec_end()

static void publish_async_exec_end ( struct ast_channel chan,
int  command_id,
const char *  command,
int  result_code,
const char *  result 
)
static

Definition at line 4010 of file res_agi.c.

References ast_channel_publish_cached_blob(), ast_json_pack(), ast_json_unref(), NULL, and RAII_VAR.

Referenced by agi_handle_command().

4011 {
4012  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
4013  blob = ast_json_pack("{s: i, s: s, s: i, s: s}",
4014  "CommandId", command_id,
4015  "Command", command,
4016  "ResultCode", result_code,
4017  "Result", result);
4018  ast_channel_publish_cached_blob(chan, agi_exec_end_type(), blob);
4019 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message using the latest snapshot from the cache.
#define NULL
Definition: resample.c:96
#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:911
static PGresult * result
Definition: cel_pgsql.c:88
Abstract JSON element (object, array, string, int, ...).

◆ run_agi()

static enum agi_result run_agi ( struct ast_channel chan,
char *  request,
AGI agi,
int  pid,
int *  status,
int  dead,
int  argc,
char *  argv[] 
)
static

Running in an interception routine is like DeadAGI mode. No touchy the channel frames.

Definition at line 4112 of file res_agi.c.

References AGI_BUF_LEN, agi_handle_command(), AGI_NANDFS_RETRY, AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS, agidebug, ast_agi_send(), ast_channel_get_intercept_mode(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_check_hangup(), ast_debug, ast_false(), AST_FRAME_VOICE, ast_frfree, ast_log, ast_read(), ast_speech_destroy(), ast_true(), ast_verb, ast_verbose(), ast_waitfor_nandfds(), agi_state::audio, buf, c, agi_state::ctrl, ast_frame::data, ast_frame::datalen, errno, agi_state::fast, agi_state::fd, ast_frame::frametype, len(), LOG_WARNING, NULL, pbx_builtin_getvar_helper(), ast_frame::ptr, setup_env(), and agi_state::speech.

Referenced by agi_exec_full().

4113 {
4114  struct ast_channel *c;
4115  int outfd;
4116  int ms;
4117  int needhup = 0;
4118  enum agi_result returnstatus = AGI_RESULT_SUCCESS;
4119  struct ast_frame *f;
4120  char buf[AGI_BUF_LEN];
4121  char *res = NULL;
4122  FILE *readf;
4123  /* how many times we'll retry if ast_waitfor_nandfs will return without either
4124  channel or file descriptor in case select is interrupted by a system call (EINTR) */
4125  int retry = AGI_NANDFS_RETRY;
4126  int send_sighup;
4127  const char *sighup_str;
4128  const char *exit_on_hangup_str;
4129  int exit_on_hangup;
4130  /*! Running in an interception routine is like DeadAGI mode. No touchy the channel frames. */
4131  int in_intercept = ast_channel_get_intercept_mode();
4132 
4133  ast_channel_lock(chan);
4134  sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
4135  send_sighup = !ast_false(sighup_str);
4136  exit_on_hangup_str = pbx_builtin_getvar_helper(chan, "AGIEXITONHANGUP");
4137  exit_on_hangup = ast_true(exit_on_hangup_str);
4138  ast_channel_unlock(chan);
4139 
4140  if (!(readf = fdopen(agi->ctrl, "r"))) {
4141  ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
4142  if (send_sighup && pid > -1)
4143  kill(pid, SIGHUP);
4144  close(agi->ctrl);
4145  return AGI_RESULT_FAILURE;
4146  }
4147 
4148  setlinebuf(readf);
4149  setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv);
4150  for (;;) {
4151  if (needhup) {
4152  needhup = 0;
4153  dead = 1;
4154  if (send_sighup) {
4155  if (pid > -1) {
4156  kill(pid, SIGHUP);
4157  } else if (agi->fast) {
4158  ast_agi_send(agi->fd, chan, "HANGUP\n");
4159  }
4160  }
4161  if (exit_on_hangup) {
4162  break;
4163  }
4164  }
4165  ms = -1;
4166  if (dead || in_intercept) {
4167  c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
4168  } else if (!ast_check_hangup(chan)) {
4169  c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
4170  } else {
4171  /*
4172  * Read the channel control queue until it is dry so we can
4173  * switch to dead mode.
4174  */
4175  c = chan;
4176  }
4177  if (c) {
4178  retry = AGI_NANDFS_RETRY;
4179  /* Idle the channel until we get a command */
4180  f = ast_read(c);
4181  if (!f) {
4182  ast_debug(1, "%s hungup\n", ast_channel_name(chan));
4183  needhup = 1;
4184  if (!returnstatus) {
4185  returnstatus = AGI_RESULT_HANGUP;
4186  }
4187  } else {
4188  /* If it's voice, write it to the audio pipe */
4189  if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
4190  /* Write, ignoring errors */
4191  if (write(agi->audio, f->data.ptr, f->datalen) < 0) {
4192  }
4193  }
4194  ast_frfree(f);
4195  }
4196  } else if (outfd > -1) {
4197  size_t len = sizeof(buf);
4198  size_t buflen = 0;
4199  enum agi_result cmd_status;
4200 
4201  retry = AGI_NANDFS_RETRY;
4202  buf[0] = '\0';
4203 
4204  while (len > 1) {
4205  res = fgets(buf + buflen, len, readf);
4206  if (feof(readf))
4207  break;
4208  if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN)))
4209  break;
4210  if (res != NULL && !agi->fast)
4211  break;
4212  buflen = strlen(buf);
4213  if (buflen && buf[buflen - 1] == '\n')
4214  break;
4215  len = sizeof(buf) - buflen;
4216  if (agidebug)
4217  ast_verbose("AGI Rx << temp buffer %s - errno %s\nNo \\n received, checking again.\n", buf, strerror(errno));
4218  }
4219 
4220  if (!buf[0]) {
4221  /* Program terminated */
4222  ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", ast_channel_name(chan), request, returnstatus);
4223  if (pid > 0)
4224  waitpid(pid, status, 0);
4225  /* No need to kill the pid anymore, since they closed us */
4226  pid = -1;
4227  break;
4228  }
4229 
4230  /* Special case for inability to execute child process */
4231  if (*buf && strncasecmp(buf, "failure", 7) == 0) {
4232  returnstatus = AGI_RESULT_FAILURE;
4233  break;
4234  }
4235 
4236  /* get rid of trailing newline, if any */
4237  buflen = strlen(buf);
4238  if (buflen && buf[buflen - 1] == '\n') {
4239  buf[buflen - 1] = '\0';
4240  }
4241 
4242  if (agidebug)
4243  ast_verbose("<%s>AGI Rx << %s\n", ast_channel_name(chan), buf);
4244  cmd_status = agi_handle_command(chan, agi, buf, dead || in_intercept);
4245  switch (cmd_status) {
4246  case AGI_RESULT_FAILURE:
4247  if (dead || in_intercept || !ast_check_hangup(chan)) {
4248  /* The failure was not because of a hangup. */
4249  returnstatus = AGI_RESULT_FAILURE;
4250  }
4251  break;
4252  default:
4253  break;
4254  }
4255  } else {
4256  if (--retry <= 0) {
4257  ast_log(LOG_WARNING, "No channel, no fd?\n");
4258  returnstatus = AGI_RESULT_FAILURE;
4259  break;
4260  }
4261  }
4262  }
4263 
4264  if (agi->speech) {
4265  ast_speech_destroy(agi->speech);
4266  }
4267  /* Notify process */
4268  if (send_sighup) {
4269  if (pid > -1) {
4270  if (kill(pid, SIGHUP)) {
4271  ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
4272  } else { /* Give the process a chance to die */
4273  usleep(1);
4274  }
4275  waitpid(pid, status, WNOHANG);
4276  } else if (agi->fast) {
4277  ast_agi_send(agi->fd, chan, "HANGUP\n");
4278  }
4279  }
4280  fclose(readf);
4281  return returnstatus;
4282 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
agi_result
Definition: res_agi.c:1412
int ast_speech_destroy(struct ast_speech *speech)
Destroy a speech structure.
Definition: res_speech.c:240
static int agidebug
Definition: res_agi.c:1400
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
#define AGI_NANDFS_RETRY
Definition: res_agi.c:1390
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
int ctrl
Definition: agi.h:37
static struct test_val c
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:2997
#define ast_verb(level,...)
Definition: logger.h:463
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
Definition: res_agi.c:2318
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int audio
Definition: agi.h:36
static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
Definition: res_agi.c:4021
static int request(void *obj)
Definition: chan_pjsip.c:2559
unsigned int fast
Definition: agi.h:38
const char * ast_channel_name(const struct ast_channel *chan)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1968
#define ast_frfree(fr)
#define AGI_BUF_LEN
Definition: res_agi.c:1391
Data structure associated with a single frame of data.
int ast_channel_get_intercept_mode(void)
Am I currently running an intercept dialplan routine.
Definition: channel.c:10430
union ast_frame::@263 data
enum ast_frame_type frametype
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
jack_status_t status
Definition: app_jack.c:146

◆ setup_env()

static void setup_env ( struct ast_channel chan,
char *  request,
int  fd,
int  enhanced,
int  argc,
char *  argv[] 
)
static

Definition at line 2318 of file res_agi.c.

References ast_agi_send(), ast_channel_accountcode(), ast_channel_caller(), ast_channel_context(), ast_channel_dialed(), ast_channel_exten(), ast_channel_language(), ast_channel_name(), ast_channel_priority(), ast_channel_redirecting(), ast_channel_tech(), ast_channel_uniqueid(), ast_get_version(), ast_party_id_presentation(), name, S_COR, S_OR, and type.

Referenced by action_add_agi_cmd(), launch_asyncagi(), and run_agi().

2319 {
2320  int count;
2321 
2322  /* Print initial environment, with agi_request always being the first
2323  thing */
2324  ast_agi_send(fd, chan, "agi_request: %s\n", request);
2325  ast_agi_send(fd, chan, "agi_channel: %s\n", ast_channel_name(chan));
2326  ast_agi_send(fd, chan, "agi_language: %s\n", ast_channel_language(chan));
2327  ast_agi_send(fd, chan, "agi_type: %s\n", ast_channel_tech(chan)->type);
2328  ast_agi_send(fd, chan, "agi_uniqueid: %s\n", ast_channel_uniqueid(chan));
2329  ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
2330 
2331  /* ANI/DNIS */
2332  ast_agi_send(fd, chan, "agi_callerid: %s\n",
2333  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "unknown"));
2334  ast_agi_send(fd, chan, "agi_calleridname: %s\n",
2335  S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "unknown"));
2336  ast_agi_send(fd, chan, "agi_callingpres: %d\n",
2338  ast_agi_send(fd, chan, "agi_callingani2: %d\n", ast_channel_caller(chan)->ani2);
2339  ast_agi_send(fd, chan, "agi_callington: %d\n", ast_channel_caller(chan)->id.number.plan);
2340  ast_agi_send(fd, chan, "agi_callingtns: %d\n", ast_channel_dialed(chan)->transit_network_select);
2341  ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(ast_channel_dialed(chan)->number.str, "unknown"));
2342  ast_agi_send(fd, chan, "agi_rdnis: %s\n",
2343  S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "unknown"));
2344 
2345  /* Context information */
2346  ast_agi_send(fd, chan, "agi_context: %s\n", ast_channel_context(chan));
2347  ast_agi_send(fd, chan, "agi_extension: %s\n", ast_channel_exten(chan));
2348  ast_agi_send(fd, chan, "agi_priority: %d\n", ast_channel_priority(chan));
2349  ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
2350 
2351  /* User information */
2352  ast_agi_send(fd, chan, "agi_accountcode: %s\n", ast_channel_accountcode(chan) ? ast_channel_accountcode(chan) : "");
2353  ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
2354 
2355  /* Send any parameters to the fastagi server that have been passed via the agi application */
2356  /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
2357  for(count = 1; count < argc; count++)
2358  ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
2359 
2360  /* End with empty return */
2361  ast_agi_send(fd, chan, "\n");
2362 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
static const char type[]
Definition: chan_ooh323.c:109
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:16
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1821
int ast_channel_priority(const struct ast_channel *chan)
Number structure.
Definition: app_followme.c:154
const char * ast_channel_accountcode(const struct ast_channel *chan)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
const char * ast_channel_exten(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
static const char name[]
Definition: cdr_mysql.c:74
static int request(void *obj)
Definition: chan_pjsip.c:2559
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_language(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)

◆ speech_streamfile()

static int speech_streamfile ( struct ast_channel chan,
const char *  filename,
const char *  preflang,
int  offset 
)
static

Definition at line 3537 of file res_agi.c.

References ast_applystream(), ast_openstream(), ast_playstream(), ast_seekstream(), and NULL.

Referenced by handle_speechrecognize().

3538 {
3539  struct ast_filestream *fs = NULL;
3540 
3541  if (!(fs = ast_openstream(chan, filename, preflang)))
3542  return -1;
3543 
3544  if (offset)
3545  ast_seekstream(fs, offset, SEEK_SET);
3546 
3547  if (ast_applystream(chan, fs))
3548  return -1;
3549 
3550  if (ast_playstream(fs))
3551  return -1;
3552 
3553  return 0;
3554 }
#define NULL
Definition: resample.c:96
int ast_playstream(struct ast_filestream *s)
Play a open stream on a channel.
Definition: file.c:1026
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applys a open stream to a channel.
Definition: file.c:1020
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:1038
char * filename
Definition: mod_format.h:107
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
struct ast_filestream * ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:755

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [1/5]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( agi_exec_start_type  ,
to_ami = agi_exec_start_to_ami 
)

Referenced by agi_async_end_to_ami().

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [2/5]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( agi_exec_end_type  ,
to_ami = agi_exec_end_to_ami 
)

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [3/5]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( agi_async_start_type  ,
to_ami = agi_async_start_to_ami 
)

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [4/5]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( agi_async_exec_type  ,
to_ami = agi_async_exec_to_ami 
)

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [5/5]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( agi_async_end_type  ,
to_ami = agi_async_end_to_ami 
)

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 4664 of file res_agi.c.

References app, ARRAY_LEN, ast_agi_unregister_multiple(), ast_cli_unregister_multiple(), ast_manager_unregister(), AST_TEST_UNREGISTER, ast_unregister_application(), deadapp, eapp, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module().

4665 {
4666  STASIS_MESSAGE_TYPE_CLEANUP(agi_exec_start_type);
4667  STASIS_MESSAGE_TYPE_CLEANUP(agi_exec_end_type);
4668  STASIS_MESSAGE_TYPE_CLEANUP(agi_async_start_type);
4669  STASIS_MESSAGE_TYPE_CLEANUP(agi_async_exec_type);
4670  STASIS_MESSAGE_TYPE_CLEANUP(agi_async_end_type);
4671 
4676  ast_manager_unregister("AGI");
4678  AST_TEST_UNREGISTER(test_agi_null_docs);
4679  return 0;
4680 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
static char * deadapp
Definition: res_agi.c:1398
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static struct agi_command commands[]
AGI commands list.
Definition: res_agi.c:3706
static struct ast_cli_entry cli_agi[]
Definition: res_agi.c:4617
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
int AST_OPTIONAL_API_NAME() ast_agi_unregister_multiple(struct agi_command *cmd, unsigned int len)
Definition: res_agi.c:3893
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
static char * app
Definition: res_agi.c:1394
static char * eapp
Definition: res_agi.c:1396

◆ write_html_escaped()

static void write_html_escaped ( FILE *  htmlfile,
char *  str 
)
static

Convert string to use HTML escaped characters.

Note
Maybe this should be a generic function?

Definition at line 4390 of file res_agi.c.

References str.

Referenced by write_htmldump().

4391 {
4392  char *cur = str;
4393 
4394  while(*cur) {
4395  switch (*cur) {
4396  case '<':
4397  fprintf(htmlfile, "%s", "&lt;");
4398  break;
4399  case '>':
4400  fprintf(htmlfile, "%s", "&gt;");
4401  break;
4402  case '&':
4403  fprintf(htmlfile, "%s", "&amp;");
4404  break;
4405  case '"':
4406  fprintf(htmlfile, "%s", "&quot;");
4407  break;
4408  default:
4409  fprintf(htmlfile, "%c", *cur);
4410  break;
4411  }
4412  cur++;
4413  }
4414 
4415  return;
4416 }
const char * str
Definition: app_jack.c:147

◆ write_htmldump()

static int write_htmldump ( const char *  filename)
static

Definition at line 4418 of file res_agi.c.

References ast_free, ast_join, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_xmldoc_printable(), agi_command::cmda, agi_command::list, MAX_CMD_LEN, NULL, strsep(), agi_command::summary, agi_command::usage, and write_html_escaped().

Referenced by handle_cli_agi_dump_html().

4419 {
4420  struct agi_command *command;
4421  char fullcmd[MAX_CMD_LEN];
4422  FILE *htmlfile;
4423 
4424  if (!(htmlfile = fopen(filename, "wt")))
4425  return -1;
4426 
4427  fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
4428  fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
4429  fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
4430 
4432  AST_RWLIST_TRAVERSE(&agi_commands, command, list) {
4433  char *tempstr, *stringp;
4434 
4435  if (!command->cmda[0]) /* end ? */
4436  break;
4437  /* Hide commands that start with '_' */
4438  if ((command->cmda[0])[0] == '_')
4439  continue;
4440  ast_join(fullcmd, sizeof(fullcmd), command->cmda);
4441 
4442  fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
4443  fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary);
4444 #ifdef AST_XML_DOCS
4445  stringp = ast_xmldoc_printable(command->usage, 0);
4446 #else
4447  stringp = ast_strdup(command->usage);
4448 #endif
4449  tempstr = strsep(&stringp, "\n");
4450 
4451  fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">");
4452  write_html_escaped(htmlfile, tempstr);
4453  fprintf(htmlfile, "</TD></TR>\n");
4454  fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
4455 
4456  while ((tempstr = strsep(&stringp, "\n")) != NULL) {
4457  write_html_escaped(htmlfile, tempstr);
4458  fprintf(htmlfile, "<BR>\n");
4459  }
4460  fprintf(htmlfile, "</TD></TR>\n");
4461  fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
4462  ast_free(stringp);
4463  }
4465  fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
4466  fclose(htmlfile);
4467  return 0;
4468 }
const char *const summary
Definition: agi.h:48
#define ast_join(s, len, w)
Definition: strings.h:483
const char *const usage
Definition: agi.h:50
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define MAX_CMD_LEN
Definition: res_agi.c:1389
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
#define ast_free(a)
Definition: astmm.h:182
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:242
struct agi_command::@219 list
char * strsep(char **str, const char *delims)
static void write_html_escaped(FILE *htmlfile, char *str)
Convert string to use HTML escaped characters.
Definition: res_agi.c:4390

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk Gateway Interface (AGI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_speech", }
static

Definition at line 4715 of file res_agi.c.

◆ agi_buf

struct ast_threadstorage agi_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_agi_buf , .custom_init = NULL , }
static

Definition at line 1483 of file res_agi.c.

Referenced by ast_agi_send().

◆ agi_commands

struct agi_commands agi_commands = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

Referenced by add_agi_cmd(), and get_agi_cmd().

◆ agi_commands_datastore_info

const struct ast_datastore_info agi_commands_datastore_info
static
Initial value:
= {
.type = "AsyncAGI",
}
static void agi_destroy_commands_cb(void *data)
Definition: res_agi.c:1530

Definition at line 1544 of file res_agi.c.

◆ agidebug

int agidebug = 0
static

Definition at line 1400 of file res_agi.c.

Referenced by ast_agi_send(), handle_cli_agi_debug(), and run_agi().

◆ app

char* app = "AGI"
static

Definition at line 1394 of file res_agi.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4715 of file res_agi.c.

◆ cli_agi

struct ast_cli_entry cli_agi[]
static

Definition at line 4617 of file res_agi.c.

◆ commands

struct agi_command commands[]
static

AGI commands list.

Definition at line 3706 of file res_agi.c.

Referenced by dundi_showframe(), and xmpp_component_service_discovery_get_hook().

◆ deadapp

char* deadapp = "DeadAGI"
static

Definition at line 1398 of file res_agi.c.

Referenced by load_module(), and unload_module().

◆ eapp

char* eapp = "EAGI"
static

Definition at line 1396 of file res_agi.c.

Referenced by load_module(), and unload_module().