#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/agi.h"

Go to the source code of this file.
Data Structures | |
| struct | agi_cmd |
| struct | agi_commands |
Defines | |
| #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 | __fini_agi_commands (void) |
| static void | __init_agi_buf (void) |
| static void | __init_agi_commands (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. | |
| 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 void | agi_destroy_commands_cb (void *data) |
| static int | agi_exec (struct ast_channel *chan, const char *data) |
| static int | agi_exec_full (struct ast_channel *chan, const char *data, int enhanced, int dead) |
| 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) |
| Registers an AGI command. | |
| int AST_OPTIONAL_API_NAME() | ast_agi_register_multiple (struct ast_module *mod, struct agi_command *cmd, unsigned int len) |
| Registers a group of AGI commands, provided as an array of struct agi_command entries. | |
| int AST_OPTIONAL_API_NAME() | ast_agi_send (int fd, struct ast_channel *chan, char *fmt,...) |
| Sends a string of text to an application connected via AGI. | |
| int AST_OPTIONAL_API_NAME() | ast_agi_unregister (struct ast_module *mod, agi_command *cmd) |
| Unregisters an AGI command. | |
| int AST_OPTIONAL_API_NAME() | ast_agi_unregister_multiple (struct ast_module *mod, struct agi_command *cmd, unsigned int len) |
| Unregisters a group of AGI commands, provided as an array of struct agi_command entries. | |
| 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_command * | find_command (const char *const cmds[], int exact) |
| static void | free_agi_cmd (struct agi_cmd *cmd) |
| static struct agi_cmd * | get_agi_cmd (struct ast_channel *chan) |
| 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. | |
| 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_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 | |
| 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. | |
| 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, 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, 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 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) |
| static int | unload_module (void) |
| static void | write_html_escaped (FILE *htmlfile, char *str) |
| Convert string to use HTML escaped characters. | |
| 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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, } |
| static struct ast_threadstorage | agi_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_agi_buf , .custom_init = NULL , } |
| static struct ast_datastore_info | agi_commands_datastore_info |
| static int | agidebug = 0 |
| static char * | app = "AGI" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_cli_entry | cli_agi [] |
| static struct agi_command | commands [] |
| AGI commands list. | |
| static char * | deadapp = "DeadAGI" |
| static char * | eapp = "EAGI" |
Definition in file res_agi.c.
| #define AGI_BUF_INITSIZE 256 |
| #define AGI_BUF_SIZE 1024 |
Referenced by launch_asyncagi().
| #define AGI_PORT 4573 |
| #define AMI_BUF_SIZE 2048 |
Referenced by launch_asyncagi().
| #define ASYNC_AGI_BREAK 3 |
Special return code for "asyncagi break" command.
Definition at line 923 of file res_agi.c.
Referenced by agi_handle_command(), and handle_asyncagi_break().
| #define MAX_AGI_CONNECT 2000 |
| #define MAX_CMD_LEN 80 |
Definition at line 902 of file res_agi.c.
Referenced by ast_agi_register(), ast_agi_unregister(), handle_cli_agi_show(), help_workhorse(), and write_htmldump().
| #define SRV_PREFIX "_agi._tcp." |
| enum agi_result |
| AGI_RESULT_FAILURE | |
| AGI_RESULT_SUCCESS | |
| AGI_RESULT_SUCCESS_FAST | |
| AGI_RESULT_SUCCESS_ASYNC | |
| AGI_RESULT_NOTFOUND | |
| AGI_RESULT_HANGUP |
Definition at line 925 of file res_agi.c.
00925 { 00926 AGI_RESULT_FAILURE = -1, 00927 AGI_RESULT_SUCCESS, 00928 AGI_RESULT_SUCCESS_FAST, 00929 AGI_RESULT_SUCCESS_ASYNC, 00930 AGI_RESULT_NOTFOUND, 00931 AGI_RESULT_HANGUP, 00932 };
| static void __fini_agi_commands | ( | void | ) | [static] |
| static void __init_agi_commands | ( | void | ) | [static] |
| 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.
| s | ||
| m | It will append the application to the specified channel's queue if the channel is not inside Async AGI application it will return an error |
| 0 | on success or incorrect use | |
| 1 | on failure to add the command ( most likely because the channel is not in Async AGI loop ) |
Definition at line 1153 of file res_agi.c.
References add_agi_cmd(), 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(), and astman_send_error().
Referenced by load_module().
01154 { 01155 const char *channel = astman_get_header(m, "Channel"); 01156 const char *cmdbuff = astman_get_header(m, "Command"); 01157 const char *cmdid = astman_get_header(m, "CommandID"); 01158 struct ast_channel *chan; 01159 char buf[256]; 01160 01161 if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) { 01162 astman_send_error(s, m, "Both, Channel and Command are *required*"); 01163 return 0; 01164 } 01165 01166 if (!(chan = ast_channel_get_by_name(channel))) { 01167 snprintf(buf, sizeof(buf), "Channel %s does not exist.", channel); 01168 astman_send_error(s, m, buf); 01169 return 0; 01170 } 01171 01172 ast_channel_lock(chan); 01173 01174 if (add_agi_cmd(chan, cmdbuff, cmdid)) { 01175 snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", ast_channel_name(chan)); 01176 astman_send_error(s, m, buf); 01177 ast_channel_unlock(chan); 01178 chan = ast_channel_unref(chan); 01179 return 0; 01180 } 01181 01182 ast_channel_unlock(chan); 01183 chan = ast_channel_unref(chan); 01184 01185 astman_send_ack(s, m, "Added AGI command to queue"); 01186 01187 return 0; 01188 }
| static int add_agi_cmd | ( | struct ast_channel * | chan, | |
| const char * | cmd_buff, | |||
| const char * | cmd_id | |||
| ) | [static] |
Definition at line 1024 of file res_agi.c.
References agi_commands_datastore_info, 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, agi_cmd::entry, and LOG_WARNING.
Referenced by action_add_agi_cmd(), and handle_cli_agi_add_cmd().
01025 { 01026 struct ast_datastore *store; 01027 struct agi_cmd *cmd; 01028 AST_LIST_HEAD(, agi_cmd) *agi_commands; 01029 01030 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 01031 if (!store) { 01032 ast_log(LOG_WARNING, "Channel %s is not setup for Async AGI.\n", ast_channel_name(chan)); 01033 return -1; 01034 } 01035 agi_commands = store->data; 01036 cmd = ast_calloc(1, sizeof(*cmd)); 01037 if (!cmd) { 01038 return -1; 01039 } 01040 cmd->cmd_buffer = ast_strdup(cmd_buff); 01041 if (!cmd->cmd_buffer) { 01042 ast_free(cmd); 01043 return -1; 01044 } 01045 cmd->cmd_id = ast_strdup(cmd_id); 01046 if (!cmd->cmd_id) { 01047 ast_free(cmd->cmd_buffer); 01048 ast_free(cmd); 01049 return -1; 01050 } 01051 AST_LIST_LOCK(agi_commands); 01052 AST_LIST_INSERT_TAIL(agi_commands, cmd, entry); 01053 AST_LIST_UNLOCK(agi_commands); 01054 return 0; 01055 }
| static int add_to_agi | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1057 of file res_agi.c.
References agi_commands_datastore_info, 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, and LOG_ERROR.
Referenced by launch_asyncagi().
01058 { 01059 struct ast_datastore *datastore; 01060 AST_LIST_HEAD(, agi_cmd) *agi_cmds_list; 01061 01062 /* check if already on AGI */ 01063 ast_channel_lock(chan); 01064 datastore = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 01065 ast_channel_unlock(chan); 01066 if (datastore) { 01067 /* we already have an AGI datastore, let's just 01068 return success */ 01069 return 0; 01070 } 01071 01072 /* the channel has never been on Async AGI, 01073 let's allocate it's datastore */ 01074 datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI"); 01075 if (!datastore) { 01076 return -1; 01077 } 01078 agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list)); 01079 if (!agi_cmds_list) { 01080 ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n"); 01081 ast_datastore_free(datastore); 01082 return -1; 01083 } 01084 datastore->data = agi_cmds_list; 01085 AST_LIST_HEAD_INIT(agi_cmds_list); 01086 ast_channel_lock(chan); 01087 ast_channel_datastore_add(chan, datastore); 01088 ast_channel_unlock(chan); 01089 return 0; 01090 }
| static void agi_destroy_commands_cb | ( | void * | data | ) | [static] |
Definition at line 983 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, agi_cmd::entry, and free_agi_cmd().
00984 { 00985 struct agi_cmd *cmd; 00986 AST_LIST_HEAD(, agi_cmd) *chan_cmds = data; 00987 AST_LIST_LOCK(chan_cmds); 00988 while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) { 00989 free_agi_cmd(cmd); 00990 } 00991 AST_LIST_UNLOCK(chan_cmds); 00992 AST_LIST_HEAD_DESTROY(chan_cmds); 00993 ast_free(chan_cmds); 00994 }
| static int agi_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 3910 of file res_agi.c.
References agi_exec_full(), and ast_check_hangup().
Referenced by deadagi_exec(), and load_module().
03911 { 03912 if (!ast_check_hangup(chan)) 03913 return agi_exec_full(chan, data, 0, 0); 03914 else 03915 return agi_exec_full(chan, data, 0, 1); 03916 }
| static int agi_exec_full | ( | struct ast_channel * | chan, | |
| const char * | data, | |||
| int | enhanced, | |||
| int | dead | |||
| ) | [static] |
Definition at line 3843 of file res_agi.c.
References ast_channel::_state, 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(), launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), run_agi(), and status.
Referenced by agi_exec(), and eagi_exec().
03844 { 03845 enum agi_result res; 03846 char *buf; 03847 int fds[2], efd = -1, pid = -1; 03848 AST_DECLARE_APP_ARGS(args, 03849 AST_APP_ARG(arg)[MAX_ARGS]; 03850 ); 03851 AGI agi; 03852 03853 if (ast_strlen_zero(data)) { 03854 ast_log(LOG_WARNING, "AGI requires an argument (script)\n"); 03855 return -1; 03856 } 03857 if (dead) 03858 ast_debug(3, "Hungup channel detected, running agi in dead mode.\n"); 03859 memset(&agi, 0, sizeof(agi)); 03860 buf = ast_strdupa(data); 03861 AST_STANDARD_APP_ARGS(args, buf); 03862 args.argv[args.argc] = NULL; 03863 #if 0 03864 /* Answer if need be */ 03865 if (chan->_state != AST_STATE_UP) { 03866 if (ast_answer(chan)) 03867 return -1; 03868 } 03869 #endif 03870 res = launch_script(chan, args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid); 03871 /* Async AGI do not require run_agi(), so just proceed if normal AGI 03872 or Fast AGI are setup with success. */ 03873 if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) { 03874 int status = 0; 03875 agi.fd = fds[1]; 03876 agi.ctrl = fds[0]; 03877 agi.audio = efd; 03878 agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0; 03879 res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv); 03880 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */ 03881 if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status) 03882 res = AGI_RESULT_FAILURE; 03883 if (fds[1] != fds[0]) 03884 close(fds[1]); 03885 if (efd > -1) 03886 close(efd); 03887 } 03888 ast_safe_fork_cleanup(); 03889 03890 switch (res) { 03891 case AGI_RESULT_SUCCESS: 03892 case AGI_RESULT_SUCCESS_FAST: 03893 case AGI_RESULT_SUCCESS_ASYNC: 03894 pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS"); 03895 break; 03896 case AGI_RESULT_FAILURE: 03897 pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE"); 03898 break; 03899 case AGI_RESULT_NOTFOUND: 03900 pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND"); 03901 break; 03902 case AGI_RESULT_HANGUP: 03903 pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP"); 03904 return -1; 03905 } 03906 03907 return 0; 03908 }
| static enum agi_result agi_handle_command | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| char * | buf, | |||
| int | dead | |||
| ) | [static] |
Definition at line 3368 of file res_agi.c.
References AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, ast_agi_send(), ast_cdr_setapp(), ast_channel_name(), ast_check_hangup(), ast_module_ref(), ast_module_unref(), ast_random(), ast_strdupa, ast_strlen_zero(), ASYNC_AGI_BREAK, ast_channel::cdr, agi_command::dead, EVENT_FLAG_AGI, agi_state::fd, find_command(), agi_command::handler, manager_event, MAX_ARGS, agi_command::mod, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.
Referenced by launch_asyncagi(), and run_agi().
03369 { 03370 const char *argv[MAX_ARGS]; 03371 int argc = MAX_ARGS; 03372 int res; 03373 agi_command *c; 03374 const char *ami_res; 03375 char *ami_cmd = ast_strdupa(buf); 03376 int command_id = ast_random(); 03377 int resultcode; 03378 03379 manager_event(EVENT_FLAG_AGI, "AGIExec", 03380 "SubEvent: Start\r\n" 03381 "Channel: %s\r\n" 03382 "CommandId: %d\r\n" 03383 "Command: %s\r\n", ast_channel_name(chan), command_id, ami_cmd); 03384 parse_args(buf, &argc, argv); 03385 c = find_command(argv, 0); 03386 if (c && (!dead || (dead && c->dead))) { 03387 /* if this command wasn't registered by res_agi, be sure to usecount 03388 the module we are using */ 03389 if (c->mod != ast_module_info->self) 03390 ast_module_ref(c->mod); 03391 /* If the AGI command being executed is an actual application (using agi exec) 03392 the app field will be updated in pbx_exec via handle_exec */ 03393 if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC")) 03394 ast_cdr_setapp(chan->cdr, "AGI", buf); 03395 03396 res = c->handler(chan, agi, argc, argv); 03397 if (c->mod != ast_module_info->self) 03398 ast_module_unref(c->mod); 03399 switch (res) { 03400 case RESULT_SHOWUSAGE: 03401 ami_res = "Usage"; 03402 resultcode = 520; 03403 break; 03404 case RESULT_FAILURE: 03405 ami_res = "Failure"; 03406 resultcode = -1; 03407 break; 03408 case ASYNC_AGI_BREAK: 03409 case RESULT_SUCCESS: 03410 ami_res = "Success"; 03411 resultcode = 200; 03412 break; 03413 default: 03414 ami_res = "Unknown Result"; 03415 resultcode = 200; 03416 break; 03417 } 03418 manager_event(EVENT_FLAG_AGI, "AGIExec", 03419 "SubEvent: End\r\n" 03420 "Channel: %s\r\n" 03421 "CommandId: %d\r\n" 03422 "Command: %s\r\n" 03423 "ResultCode: %d\r\n" 03424 "Result: %s\r\n", ast_channel_name(chan), command_id, ami_cmd, resultcode, ami_res); 03425 switch (res) { 03426 case RESULT_SHOWUSAGE: 03427 if (ast_strlen_zero(c->usage)) { 03428 ast_agi_send(agi->fd, chan, "520 Invalid command syntax. Proper usage not available.\n"); 03429 } else { 03430 ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n"); 03431 ast_agi_send(agi->fd, chan, "%s", c->usage); 03432 ast_agi_send(agi->fd, chan, "520 End of proper usage.\n"); 03433 } 03434 break; 03435 case ASYNC_AGI_BREAK: 03436 return AGI_RESULT_SUCCESS_ASYNC; 03437 case RESULT_FAILURE: 03438 /* The RESULT_FAILURE code is usually because the channel hungup. */ 03439 return AGI_RESULT_FAILURE; 03440 default: 03441 break; 03442 } 03443 } else if (c) { 03444 ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n"); 03445 manager_event(EVENT_FLAG_AGI, "AGIExec", 03446 "SubEvent: End\r\n" 03447 "Channel: %s\r\n" 03448 "CommandId: %d\r\n" 03449 "Command: %s\r\n" 03450 "ResultCode: 511\r\n" 03451 "Result: Command not permitted on a dead channel\r\n", ast_channel_name(chan), command_id, ami_cmd); 03452 } else { 03453 ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n"); 03454 manager_event(EVENT_FLAG_AGI, "AGIExec", 03455 "SubEvent: End\r\n" 03456 "Channel: %s\r\n" 03457 "CommandId: %d\r\n" 03458 "Command: %s\r\n" 03459 "ResultCode: 510\r\n" 03460 "Result: Invalid or unknown command\r\n", ast_channel_name(chan), command_id, ami_cmd); 03461 } 03462 return AGI_RESULT_SUCCESS; 03463 }
| int AST_OPTIONAL_API_NAME() ast_agi_register | ( | struct ast_module * | mod, | |
| agi_command * | cmd | |||
| ) |
Registers an AGI command.
| mod | Pointer to the module_info structure for the module that is registering the command | |
| cmd | Pointer to the descriptor for the command |
| 1 | on success | |
| 0 | the command is already registered | |
| AST_OPTIONAL_API_UNAVAILABLE | the module is not loaded. |
Definition at line 3136 of file res_agi.c.
References ast_join(), AST_LIST_INSERT_TAIL, ast_log(), ast_module_ref(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_strdup, ast_strlen_zero(), ast_verb, AST_XML_DOC, find_command(), LOG_WARNING, and MAX_CMD_LEN.
Referenced by ast_agi_register_multiple(), and load_module().
03137 { 03138 char fullcmd[MAX_CMD_LEN]; 03139 03140 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 03141 03142 if (!find_command(cmd->cmda, 1)) { 03143 *((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC; 03144 if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) { 03145 #ifdef AST_XML_DOCS 03146 *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd, NULL); 03147 *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd, NULL); 03148 *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd, NULL); 03149 *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd, NULL); 03150 *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC; 03151 #endif 03152 #ifndef HAVE_NULLSAFE_PRINTF 03153 if (!cmd->summary) { 03154 *((char **) &cmd->summary) = ast_strdup(""); 03155 } 03156 if (!cmd->usage) { 03157 *((char **) &cmd->usage) = ast_strdup(""); 03158 } 03159 if (!cmd->syntax) { 03160 *((char **) &cmd->syntax) = ast_strdup(""); 03161 } 03162 if (!cmd->seealso) { 03163 *((char **) &cmd->seealso) = ast_strdup(""); 03164 } 03165 #endif 03166 } 03167 03168 cmd->mod = mod; 03169 AST_RWLIST_WRLOCK(&agi_commands); 03170 AST_LIST_INSERT_TAIL(&agi_commands, cmd, list); 03171 AST_RWLIST_UNLOCK(&agi_commands); 03172 if (mod != ast_module_info->self) 03173 ast_module_ref(ast_module_info->self); 03174 ast_verb(2, "AGI Command '%s' registered\n",fullcmd); 03175 return 1; 03176 } else { 03177 ast_log(LOG_WARNING, "Command already registered!\n"); 03178 return 0; 03179 } 03180 }
| int AST_OPTIONAL_API_NAME() ast_agi_register_multiple | ( | struct ast_module * | mod, | |
| struct agi_command * | cmd, | |||
| unsigned int | len | |||
| ) |
Registers a group of AGI commands, provided as an array of struct agi_command entries.
| mod | Pointer to the module_info structure for the module that is registering the commands | |
| cmd | Pointer to the first entry in the array of command descriptors | |
| len | Length of the array (use the ARRAY_LEN macro to determine this easily) |
Definition at line 3221 of file res_agi.c.
References ast_agi_register(), ast_agi_unregister(), len(), and agi_command::mod.
Referenced by load_module().
03222 { 03223 unsigned int i, x = 0; 03224 03225 for (i = 0; i < len; i++) { 03226 if (ast_agi_register(mod, cmd + i) == 1) { 03227 x++; 03228 continue; 03229 } 03230 03231 /* registration failed, unregister everything 03232 that had been registered up to that point 03233 */ 03234 for (; x > 0; x--) { 03235 /* we are intentionally ignoring the 03236 result of ast_agi_unregister() here, 03237 but it should be safe to do so since 03238 we just registered these commands and 03239 the only possible way for unregistration 03240 to fail is if the command is not 03241 registered 03242 */ 03243 (void) ast_agi_unregister(mod, cmd + x - 1); 03244 } 03245 return -1; 03246 } 03247 03248 return 0; 03249 }
| int AST_OPTIONAL_API_NAME() ast_agi_send | ( | int | fd, | |
| struct ast_channel * | chan, | |||
| char * | fmt, | |||
| ... | ||||
| ) |
Sends a string of text to an application connected via AGI.
| fd | The file descriptor for the AGI session (from struct agi_state) | |
| chan | Pointer to an associated Asterisk channel, if any | |
| fmt | printf-style format string |
Definition at line 939 of file res_agi.c.
References agi_buf, AGI_BUF_INITSIZE, ast_carefulwrite(), ast_channel_name(), ast_log(), ast_str_buffer(), ast_str_set_va(), ast_str_strlen(), ast_str_thread_get(), ast_verbose, and LOG_ERROR.
Referenced by 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().
00940 { 00941 int res = 0; 00942 va_list ap; 00943 struct ast_str *buf; 00944 00945 if (!(buf = ast_str_thread_get(&agi_buf, AGI_BUF_INITSIZE))) 00946 return -1; 00947 00948 va_start(ap, fmt); 00949 res = ast_str_set_va(&buf, 0, fmt, ap); 00950 va_end(ap); 00951 00952 if (res == -1) { 00953 ast_log(LOG_ERROR, "Out of memory\n"); 00954 return -1; 00955 } 00956 00957 if (agidebug) { 00958 if (chan) { 00959 ast_verbose("<%s>AGI Tx >> %s", ast_channel_name(chan), ast_str_buffer(buf)); 00960 } else { 00961 ast_verbose("AGI Tx >> %s", ast_str_buffer(buf)); 00962 } 00963 } 00964 00965 return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100); 00966 }
| int AST_OPTIONAL_API_NAME() ast_agi_unregister | ( | struct ast_module * | mod, | |
| agi_command * | cmd | |||
| ) |
Unregisters an AGI command.
| mod | Pointer to the module_info structure for the module that is unregistering the command | |
| cmd | Pointer to the descriptor for the command |
Definition at line 3182 of file res_agi.c.
References ast_free, ast_join(), ast_log(), ast_module_unref(), 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, LOG_WARNING, MAX_CMD_LEN, agi_command::mod, agi_command::seealso, agi_command::summary, agi_command::syntax, and agi_command::usage.
Referenced by ast_agi_register_multiple(), ast_agi_unregister_multiple(), and unload_module().
03183 { 03184 struct agi_command *e; 03185 int unregistered = 0; 03186 char fullcmd[MAX_CMD_LEN]; 03187 03188 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 03189 03190 AST_RWLIST_WRLOCK(&agi_commands); 03191 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) { 03192 if (cmd == e) { 03193 AST_RWLIST_REMOVE_CURRENT(list); 03194 if (mod != ast_module_info->self) 03195 ast_module_unref(ast_module_info->self); 03196 #ifdef AST_XML_DOCS 03197 if (e->docsrc == AST_XML_DOC) { 03198 ast_free((char *) e->summary); 03199 ast_free((char *) e->usage); 03200 ast_free((char *) e->syntax); 03201 ast_free((char *) e->seealso); 03202 *((char **) &e->summary) = NULL; 03203 *((char **) &e->usage) = NULL; 03204 *((char **) &e->syntax) = NULL; 03205 *((char **) &e->seealso) = NULL; 03206 } 03207 #endif 03208 unregistered=1; 03209 break; 03210 } 03211 } 03212 AST_RWLIST_TRAVERSE_SAFE_END; 03213 AST_RWLIST_UNLOCK(&agi_commands); 03214 if (unregistered) 03215 ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd); 03216 else 03217 ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd); 03218 return unregistered; 03219 }
| int AST_OPTIONAL_API_NAME() ast_agi_unregister_multiple | ( | struct ast_module * | mod, | |
| struct agi_command * | cmd, | |||
| unsigned int | len | |||
| ) |
Unregisters a group of AGI commands, provided as an array of struct agi_command entries.
| mod | Pointer to the module_info structure for the module that is unregistering the commands | |
| cmd | Pointer to the first entry in the array of command descriptors | |
| len | Length of the array (use the ARRAY_LEN macro to determine this easily) |
Definition at line 3251 of file res_agi.c.
References ast_agi_unregister(), len(), and agi_command::mod.
Referenced by unload_module().
03252 { 03253 unsigned int i; 03254 int res = 0; 03255 03256 for (i = 0; i < len; i++) { 03257 /* remember whether any of the unregistration 03258 attempts failed... there is no recourse if 03259 any of them do 03260 */ 03261 res |= ast_agi_unregister(mod, cmd + i); 03262 } 03263 03264 return res; 03265 }
| static enum agi_result async_agi_read_frame | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1203 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(), f, ast_frame::frametype, ast_frame_subclass::integer, and ast_frame::subclass.
Referenced by launch_asyncagi().
01204 { 01205 struct ast_frame *f; 01206 01207 f = ast_read(chan); 01208 if (!f) { 01209 ast_debug(3, "No frame read on channel %s, going out ...\n", ast_channel_name(chan)); 01210 return AGI_RESULT_HANGUP; 01211 } 01212 if (f->frametype == AST_FRAME_CONTROL) { 01213 /* 01214 * Is there any other frame we should care about besides 01215 * AST_CONTROL_HANGUP? 01216 */ 01217 switch (f->subclass.integer) { 01218 case AST_CONTROL_HANGUP: 01219 ast_debug(3, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan)); 01220 ast_frfree(f); 01221 return AGI_RESULT_HANGUP; 01222 default: 01223 break; 01224 } 01225 } 01226 ast_frfree(f); 01227 01228 return AGI_RESULT_SUCCESS; 01229 }
| static int deadagi_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 3941 of file res_agi.c.
References agi_exec(), ast_log(), and LOG_WARNING.
Referenced by load_module().
03942 { 03943 ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n"); 03944 return agi_exec(chan, data); 03945 }
| static int eagi_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 3918 of file res_agi.c.
References agi_exec_full(), ast_channel_name(), ast_check_hangup(), ast_format_copy(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), ast_set_read_format(), ast_set_read_format_by_id(), LOG_ERROR, LOG_WARNING, and ast_channel::readformat.
Referenced by load_module().
03919 { 03920 int res; 03921 struct ast_format readformat; 03922 03923 if (ast_check_hangup(chan)) { 03924 ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n"); 03925 return 0; 03926 } 03927 ast_format_copy(&readformat, &chan->readformat); 03928 if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) { 03929 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", ast_channel_name(chan)); 03930 return -1; 03931 } 03932 res = agi_exec_full(chan, data, 1, 0); 03933 if (!res) { 03934 if (ast_set_read_format(chan, &readformat)) { 03935 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", ast_channel_name(chan), ast_getformatname(&readformat)); 03936 } 03937 } 03938 return res; 03939 }
| static agi_command * find_command | ( | const char *const | cmds[], | |
| int | exact | |||
| ) | [static] |
Definition at line 3267 of file res_agi.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, agi_command::list, and match().
03268 { 03269 int y, match; 03270 struct agi_command *e; 03271 03272 AST_RWLIST_RDLOCK(&agi_commands); 03273 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 03274 if (!e->cmda[0]) 03275 break; 03276 /* start optimistic */ 03277 match = 1; 03278 for (y = 0; match && cmds[y]; y++) { 03279 /* If there are no more words in the command (and we're looking for 03280 an exact match) or there is a difference between the two words, 03281 then this is not a match */ 03282 if (!e->cmda[y] && !exact) 03283 break; 03284 /* don't segfault if the next part of a command doesn't exist */ 03285 if (!e->cmda[y]) { 03286 AST_RWLIST_UNLOCK(&agi_commands); 03287 return NULL; 03288 } 03289 if (strcasecmp(e->cmda[y], cmds[y])) 03290 match = 0; 03291 } 03292 /* If more words are needed to complete the command then this is not 03293 a candidate (unless we're looking for a really inexact answer */ 03294 if ((exact > -1) && e->cmda[y]) 03295 match = 0; 03296 if (match) { 03297 AST_RWLIST_UNLOCK(&agi_commands); 03298 return e; 03299 } 03300 } 03301 AST_RWLIST_UNLOCK(&agi_commands); 03302 return NULL; 03303 }
| static void free_agi_cmd | ( | struct agi_cmd * | cmd | ) | [static] |
Definition at line 975 of file res_agi.c.
References ast_free.
Referenced by agi_destroy_commands_cb(), and launch_asyncagi().
00976 { 00977 ast_free(cmd->cmd_buffer); 00978 ast_free(cmd->cmd_id); 00979 ast_free(cmd); 00980 }
| static struct agi_cmd* get_agi_cmd | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 1002 of file res_agi.c.
References agi_commands_datastore_info, 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, agi_cmd::entry, and LOG_ERROR.
Referenced by launch_asyncagi().
01003 { 01004 struct ast_datastore *store; 01005 struct agi_cmd *cmd; 01006 AST_LIST_HEAD(, agi_cmd) *agi_commands; 01007 01008 ast_channel_lock(chan); 01009 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 01010 ast_channel_unlock(chan); 01011 if (!store) { 01012 ast_log(LOG_ERROR, "Huh? Async AGI datastore disappeared on Channel %s!\n", 01013 ast_channel_name(chan)); 01014 return NULL; 01015 } 01016 agi_commands = store->data; 01017 AST_LIST_LOCK(agi_commands); 01018 cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry); 01019 AST_LIST_UNLOCK(agi_commands); 01020 return cmd; 01021 }
| static int handle_answer | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1763 of file res_agi.c.
References ast_channel::_state, ast_agi_send(), ast_answer(), AST_STATE_UP, agi_state::fd, RESULT_FAILURE, and RESULT_SUCCESS.
01764 { 01765 int res = 0; 01766 01767 /* Answer the channel */ 01768 if (chan->_state != AST_STATE_UP) 01769 res = ast_answer(chan); 01770 01771 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01772 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01773 }
| static int handle_asyncagi_break | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1775 of file res_agi.c.
References ast_agi_send(), ASYNC_AGI_BREAK, and agi_state::fd.
01776 { 01777 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01778 return ASYNC_AGI_BREAK; 01779 }
| static int handle_autohangup | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2423 of file res_agi.c.
References ast_agi_send(), ast_channel_setwhentohangup_tv(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02424 { 02425 double timeout; 02426 struct timeval whentohangup = { 0, 0 }; 02427 02428 if (argc != 3) 02429 return RESULT_SHOWUSAGE; 02430 if (sscanf(argv[2], "%30lf", &timeout) != 1) 02431 return RESULT_SHOWUSAGE; 02432 if (timeout < 0) 02433 timeout = 0; 02434 if (timeout) { 02435 whentohangup.tv_sec = timeout; 02436 whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0; 02437 } 02438 ast_channel_setwhentohangup_tv(chan, whentohangup); 02439 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02440 return RESULT_SUCCESS; 02441 }
| static int handle_channelstatus | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2537 of file res_agi.c.
References ast_channel::_state, ast_agi_send(), ast_channel_get_by_name(), ast_channel_unref, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02538 { 02539 struct ast_channel *c; 02540 if (argc == 2) { 02541 /* no argument: supply info on the current channel */ 02542 ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state); 02543 return RESULT_SUCCESS; 02544 } else if (argc == 3) { 02545 /* one argument: look for info on the specified channel */ 02546 if ((c = ast_channel_get_by_name(argv[2]))) { 02547 ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state); 02548 c = ast_channel_unref(c); 02549 return RESULT_SUCCESS; 02550 } 02551 /* if we get this far no channel name matched the argument given */ 02552 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 02553 return RESULT_SUCCESS; 02554 } else { 02555 return RESULT_SHOWUSAGE; 02556 } 02557 }
| 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.
| e | ||
| cmd | ||
| a |
| CLI_SUCCESS | on success | |
| NULL | when init or tab completion is used |
Definition at line 1101 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, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
01102 { 01103 struct ast_channel *chan; 01104 switch (cmd) { 01105 case CLI_INIT: 01106 e->command = "agi exec"; 01107 e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n" 01108 " Add AGI command to the execute queue of the specified channel in Async AGI\n"; 01109 return NULL; 01110 case CLI_GENERATE: 01111 if (a->pos == 2) 01112 return ast_complete_channels(a->line, a->word, a->pos, a->n, 2); 01113 return NULL; 01114 } 01115 01116 if (a->argc < 4) { 01117 return CLI_SHOWUSAGE; 01118 } 01119 01120 if (!(chan = ast_channel_get_by_name(a->argv[2]))) { 01121 ast_cli(a->fd, "Channel %s does not exist.\n", a->argv[2]); 01122 return CLI_FAILURE; 01123 } 01124 01125 ast_channel_lock(chan); 01126 01127 if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) { 01128 ast_cli(a->fd, "Failed to add AGI command to queue of channel %s\n", ast_channel_name(chan)); 01129 ast_channel_unlock(chan); 01130 chan = ast_channel_unref(chan); 01131 return CLI_FAILURE; 01132 } 01133 01134 ast_debug(1, "Added AGI command to channel %s queue\n", ast_channel_name(chan)); 01135 01136 ast_channel_unlock(chan); 01137 chan = ast_channel_unref(chan); 01138 01139 return CLI_SUCCESS; 01140 }
| static char* handle_cli_agi_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2712 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, and ast_cli_entry::usage.
02713 { 02714 switch (cmd) { 02715 case CLI_INIT: 02716 e->command = "agi set debug [on|off]"; 02717 e->usage = 02718 "Usage: agi set debug [on|off]\n" 02719 " Enables/disables dumping of AGI transactions for\n" 02720 " debugging purposes.\n"; 02721 return NULL; 02722 02723 case CLI_GENERATE: 02724 return NULL; 02725 } 02726 02727 if (a->argc != e->args) 02728 return CLI_SHOWUSAGE; 02729 02730 if (strncasecmp(a->argv[3], "off", 3) == 0) { 02731 agidebug = 0; 02732 } else if (strncasecmp(a->argv[3], "on", 2) == 0) { 02733 agidebug = 1; 02734 } else { 02735 return CLI_SHOWUSAGE; 02736 } 02737 ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis"); 02738 return CLI_SUCCESS; 02739 }
| static char* handle_cli_agi_dump_html | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3819 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, ast_cli_entry::usage, and write_htmldump().
03820 { 03821 switch (cmd) { 03822 case CLI_INIT: 03823 e->command = "agi dump html"; 03824 e->usage = 03825 "Usage: agi dump html <filename>\n" 03826 " Dumps the AGI command list in HTML format to the given\n" 03827 " file.\n"; 03828 return NULL; 03829 case CLI_GENERATE: 03830 return NULL; 03831 } 03832 if (a->argc != e->args + 1) 03833 return CLI_SHOWUSAGE; 03834 03835 if (write_htmldump(a->argv[e->args]) < 0) { 03836 ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]); 03837 return CLI_SHOWUSAGE; 03838 } 03839 ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]); 03840 return CLI_SUCCESS; 03841 }
| static char* handle_cli_agi_show | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3626 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, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, agi_command::dead, agi_command::docsrc, ast_cli_args::fd, find_command(), help_workhorse(), MAX_CMD_LEN, S_OR, agi_command::seealso, agi_command::summary, synopsis, agi_command::syntax, term_color(), agi_command::usage, and ast_cli_entry::usage.
03627 { 03628 struct agi_command *command; 03629 char fullcmd[MAX_CMD_LEN]; 03630 int error = 0; 03631 03632 switch (cmd) { 03633 case CLI_INIT: 03634 e->command = "agi show commands [topic]"; 03635 e->usage = 03636 "Usage: agi show commands [topic] <topic>\n" 03637 " When called with a topic as an argument, displays usage\n" 03638 " information on the given command. If called without a\n" 03639 " topic, it provides a list of AGI commands.\n"; 03640 case CLI_GENERATE: 03641 return NULL; 03642 } 03643 if (a->argc < e->args - 1 || (a->argc >= e->args && strcasecmp(a->argv[e->args - 1], "topic"))) 03644 return CLI_SHOWUSAGE; 03645 if (a->argc > e->args - 1) { 03646 command = find_command(a->argv + e->args, 1); 03647 if (command) { 03648 char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL; 03649 char info[30 + MAX_CMD_LEN]; /* '-= Info about...' */ 03650 char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS]; /* '-= Info about...' with colors */ 03651 char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */ 03652 char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Description]\n with colors */ 03653 char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Runs Dead]\n with colors */ 03654 char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS]; /* 'Yes' or 'No' with colors */ 03655 char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS]; /* [See Also]\n with colors */ 03656 char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */ 03657 size_t synlen, desclen, seealsolen, stxlen; 03658 03659 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle)); 03660 term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle)); 03661 term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle)); 03662 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle)); 03663 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle)); 03664 term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent)); 03665 03666 ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args); 03667 snprintf(info, sizeof(info), "\n -= Info about agi '%s' =- ", fullcmd); 03668 term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle)); 03669 #ifdef AST_XML_DOCS 03670 if (command->docsrc == AST_XML_DOC) { 03671 synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1); 03672 description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1); 03673 seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1); 03674 if (!seealso || !description || !synopsis) { 03675 error = 1; 03676 goto return_cleanup; 03677 } 03678 } else 03679 #endif 03680 { 03681 synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; 03682 synopsis = ast_malloc(synlen); 03683 03684 desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; 03685 description = ast_malloc(desclen); 03686 03687 seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; 03688 seealso = ast_malloc(seealsolen); 03689 03690 if (!synopsis || !description || !seealso) { 03691 error = 1; 03692 goto return_cleanup; 03693 } 03694 term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen); 03695 term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen); 03696 term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen); 03697 } 03698 03699 stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; 03700 syntax = ast_malloc(stxlen); 03701 if (!syntax) { 03702 error = 1; 03703 goto return_cleanup; 03704 } 03705 term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen); 03706 03707 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, 03708 desctitle, description, syntitle, synopsis, deadtitle, deadcontent, 03709 seealsotitle, seealso); 03710 return_cleanup: 03711 ast_free(synopsis); 03712 ast_free(description); 03713 ast_free(syntax); 03714 ast_free(seealso); 03715 } else { 03716 if (find_command(a->argv + e->args, -1)) { 03717 return help_workhorse(a->fd, a->argv + e->args); 03718 } else { 03719 ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args); 03720 ast_cli(a->fd, "No such command '%s'.\n", fullcmd); 03721 } 03722 } 03723 } else { 03724 return help_workhorse(a->fd, NULL); 03725 } 03726 return (error ? CLI_FAILURE : CLI_SUCCESS); 03727 }
| static int handle_controlstreamfile | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1894 of file res_agi.c.
References ast_agi_send(), ast_control_streamfile(), ast_strlen_zero(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, skipms, stop, and suspend().
01895 { 01896 int res = 0, skipms = 3000; 01897 const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */ 01898 01899 if (argc < 5 || argc > 9) { 01900 return RESULT_SHOWUSAGE; 01901 } 01902 01903 if (!ast_strlen_zero(argv[4])) { 01904 stop = argv[4]; 01905 } 01906 01907 if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) { 01908 return RESULT_SHOWUSAGE; 01909 } 01910 01911 if (argc > 6 && !ast_strlen_zero(argv[6])) { 01912 fwd = argv[6]; 01913 } 01914 01915 if (argc > 7 && !ast_strlen_zero(argv[7])) { 01916 rev = argv[7]; 01917 } 01918 01919 if (argc > 8 && !ast_strlen_zero(argv[8])) { 01920 suspend = argv[8]; 01921 } 01922 01923 res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL); 01924 01925 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01926 01927 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01928 }
| static int handle_dbdel | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2686 of file res_agi.c.
References ast_agi_send(), ast_db_del(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02687 { 02688 int res; 02689 02690 if (argc != 4) 02691 return RESULT_SHOWUSAGE; 02692 res = ast_db_del(argv[2], argv[3]); 02693 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 02694 return RESULT_SUCCESS; 02695 }
| static int handle_dbdeltree | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2697 of file res_agi.c.
References ast_agi_send(), ast_db_deltree(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02698 { 02699 int res; 02700 02701 if ((argc < 3) || (argc > 4)) 02702 return RESULT_SHOWUSAGE; 02703 if (argc == 4) 02704 res = ast_db_deltree(argv[2], argv[3]); 02705 else 02706 res = ast_db_deltree(argv[2], NULL); 02707 02708 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 02709 return RESULT_SUCCESS; 02710 }
| static int handle_dbget | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2642 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(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02643 { 02644 int res; 02645 struct ast_str *buf; 02646 02647 if (argc != 4) 02648 return RESULT_SHOWUSAGE; 02649 02650 if (!(buf = ast_str_create(16))) { 02651 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 02652 return RESULT_SUCCESS; 02653 } 02654 02655 do { 02656 res = ast_db_get(argv[2], argv[3], ast_str_buffer(buf), ast_str_size(buf)); 02657 ast_str_update(buf); 02658 if (ast_str_strlen(buf) < ast_str_size(buf) - 1) { 02659 break; 02660 } 02661 if (ast_str_make_space(&buf, ast_str_size(buf) * 2)) { 02662 break; 02663 } 02664 } while (1); 02665 02666 if (res) 02667 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02668 else 02669 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(buf)); 02670 02671 ast_free(buf); 02672 return RESULT_SUCCESS; 02673 }
| static int handle_dbput | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2675 of file res_agi.c.
References ast_agi_send(), ast_db_put(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02676 { 02677 int res; 02678 02679 if (argc != 5) 02680 return RESULT_SHOWUSAGE; 02681 res = ast_db_put(argv[2], argv[3], argv[4]); 02682 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 02683 return RESULT_SUCCESS; 02684 }
| static int handle_exec | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2471 of file res_agi.c.
References ast_agi_send(), ast_clear_flag, ast_compat_res_agi, AST_FLAG_DISABLE_WORKAROUNDS, ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_verb, agi_state::fd, LOG_WARNING, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.
02472 { 02473 int res, workaround; 02474 struct ast_app *app_to_exec; 02475 02476 if (argc < 2) 02477 return RESULT_SHOWUSAGE; 02478 02479 ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : ""); 02480 02481 if ((app_to_exec = pbx_findapp(argv[1]))) { 02482 if (!(workaround = ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS))) { 02483 ast_set_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS); 02484 } 02485 if (ast_compat_res_agi && argc >= 3 && !ast_strlen_zero(argv[2])) { 02486 char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr; 02487 const char *vptr; 02488 for (cptr = compat, vptr = argv[2]; *vptr; vptr++) { 02489 if (*vptr == ',') { 02490 *cptr++ = '\\'; 02491 *cptr++ = ','; 02492 } else if (*vptr == '|') { 02493 *cptr++ = ','; 02494 } else { 02495 *cptr++ = *vptr; 02496 } 02497 } 02498 *cptr = '\0'; 02499 res = pbx_exec(chan, app_to_exec, compat); 02500 } else { 02501 res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]); 02502 } 02503 if (!workaround) { 02504 ast_clear_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS); 02505 } 02506 } else { 02507 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]); 02508 res = -2; 02509 } 02510 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02511 02512 /* Even though this is wrong, users are depending upon this result. */ 02513 return res; 02514 }
| static int handle_getdata | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2178 of file res_agi.c.
References ast_agi_send(), ast_app_getdata_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02179 { 02180 int res, max, timeout; 02181 char data[1024]; 02182 02183 if (argc < 3) 02184 return RESULT_SHOWUSAGE; 02185 if (argc >= 4) 02186 timeout = atoi(argv[3]); 02187 else 02188 timeout = 0; 02189 if (argc >= 5) 02190 max = atoi(argv[4]); 02191 else 02192 max = 1024; 02193 res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl); 02194 if (res == 2) /* New command */ 02195 return RESULT_SUCCESS; 02196 else if (res == 1) 02197 ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data); 02198 else if (res < 0 ) 02199 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 02200 else 02201 ast_agi_send(agi->fd, chan, "200 result=%s\n", data); 02202 return RESULT_SUCCESS; 02203 }
| 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 1986 of file res_agi.c.
References ast_agi_send(), ast_applystream(), ast_channel_language(), 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, ast_channel::pbx, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.
01987 { 01988 int res; 01989 struct ast_filestream *fs, *vfs; 01990 long sample_offset = 0, max_length; 01991 int timeout = 0; 01992 const char *edigits = ""; 01993 01994 if ( argc < 4 || argc > 5 ) 01995 return RESULT_SHOWUSAGE; 01996 01997 if ( argv[3] ) 01998 edigits = argv[3]; 01999 02000 if ( argc == 5 ) 02001 timeout = atoi(argv[4]); 02002 else if (chan->pbx->dtimeoutms) { 02003 /* by default dtimeout is set to 5sec */ 02004 timeout = chan->pbx->dtimeoutms; /* in msec */ 02005 } 02006 02007 if (!(fs = ast_openstream(chan, argv[2], ast_channel_language(chan)))) { 02008 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset); 02009 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]); 02010 return RESULT_SUCCESS; 02011 } 02012 02013 if ((vfs = ast_openvstream(chan, argv[2], ast_channel_language(chan)))) 02014 ast_debug(1, "Ooh, found a video stream, too\n"); 02015 02016 ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout); 02017 02018 ast_seekstream(fs, 0, SEEK_END); 02019 max_length = ast_tellstream(fs); 02020 ast_seekstream(fs, sample_offset, SEEK_SET); 02021 res = ast_applystream(chan, fs); 02022 if (vfs) 02023 ast_applystream(chan, vfs); 02024 ast_playstream(fs); 02025 if (vfs) 02026 ast_playstream(vfs); 02027 02028 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 02029 /* this is to check for if ast_waitstream closed the stream, we probably are at 02030 * the end of the stream, return that amount, else check for the amount */ 02031 sample_offset = (chan->stream)?ast_tellstream(fs):max_length; 02032 ast_stopstream(chan); 02033 if (res == 1) { 02034 /* Stop this command, don't print a result line, as there is a new command */ 02035 return RESULT_SUCCESS; 02036 } 02037 02038 /* If the user didnt press a key, wait for digitTimeout*/ 02039 if (res == 0 ) { 02040 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl); 02041 /* Make sure the new result is in the escape digits of the GET OPTION */ 02042 if ( !strchr(edigits,res) ) 02043 res=0; 02044 } 02045 02046 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset); 02047 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 02048 }
| static int handle_getvariable | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2568 of file res_agi.c.
References ast_agi_send(), ast_func_read(), ast_strlen_zero(), agi_state::fd, pbx_retrieve_variable(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02569 { 02570 char *ret; 02571 char tempstr[1024] = ""; 02572 02573 if (argc != 3) 02574 return RESULT_SHOWUSAGE; 02575 02576 /* check if we want to execute an ast_custom_function */ 02577 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) { 02578 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr; 02579 } else { 02580 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL); 02581 } 02582 02583 if (ret) 02584 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret); 02585 else 02586 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02587 02588 return RESULT_SUCCESS; 02589 }
| static int handle_getvariablefull | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2591 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, RESULT_SHOWUSAGE, RESULT_SUCCESS, and str.
02592 { 02593 struct ast_channel *chan2 = NULL; 02594 02595 if (argc != 4 && argc != 5) { 02596 return RESULT_SHOWUSAGE; 02597 } 02598 02599 if (argc == 5) { 02600 chan2 = ast_channel_get_by_name(argv[4]); 02601 } else { 02602 chan2 = ast_channel_ref(chan); 02603 } 02604 02605 if (chan2) { 02606 struct ast_str *str = ast_str_create(16); 02607 if (!str) { 02608 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02609 return RESULT_SUCCESS; 02610 } 02611 ast_str_substitute_variables(&str, 0, chan2, argv[3]); 02612 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(str)); 02613 ast_free(str); 02614 } else { 02615 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02616 } 02617 02618 if (chan2) { 02619 chan2 = ast_channel_unref(chan2); 02620 } 02621 02622 return RESULT_SUCCESS; 02623 }
| static int handle_hangup | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2443 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, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02444 { 02445 struct ast_channel *c; 02446 02447 if (argc == 1) { 02448 /* no argument: hangup the current channel */ 02449 ast_set_hangupsource(chan, "dialplan/agi", 0); 02450 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT); 02451 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02452 return RESULT_SUCCESS; 02453 } else if (argc == 2) { 02454 /* one argument: look for info on the specified channel */ 02455 if ((c = ast_channel_get_by_name(argv[1]))) { 02456 /* we have a matching channel */ 02457 ast_set_hangupsource(c, "dialplan/agi", 0); 02458 ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT); 02459 c = ast_channel_unref(c); 02460 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02461 return RESULT_SUCCESS; 02462 } 02463 /* if we get this far no channel name matched the argument given */ 02464 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 02465 return RESULT_SUCCESS; 02466 } else { 02467 return RESULT_SHOWUSAGE; 02468 } 02469 }
| static int handle_noop | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | arg, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2741 of file res_agi.c.
References ast_agi_send(), agi_state::fd, and RESULT_SUCCESS.
02742 { 02743 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02744 return RESULT_SUCCESS; 02745 }
| static int handle_recordfile | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2243 of file res_agi.c.
References ast_agi_send(), ast_applystream(), ast_channel_language(), ast_channel_name(), 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_clear(), ast_format_copy(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate(), ast_log(), ast_read(), ast_seekstream(), ast_set_read_format(), ast_set_read_format_by_id(), ast_stream_rewind(), ast_streamfile(), ast_tellstream(), ast_truncstream(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), f, agi_state::fd, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, ast_frame::subclass, THRESHOLD_SILENCE, and ast_dsp::totalsilence.
02244 { 02245 struct ast_filestream *fs; 02246 struct ast_frame *f; 02247 struct timeval start; 02248 long sample_offset = 0; 02249 int res = 0; 02250 int ms; 02251 02252 struct ast_dsp *sildet=NULL; /* silence detector dsp */ 02253 int totalsilence = 0; 02254 int dspsilence = 0; 02255 int silence = 0; /* amount of silence to allow */ 02256 int gotsilence = 0; /* did we timeout for silence? */ 02257 char *silencestr = NULL; 02258 struct ast_format rfmt; 02259 ast_format_clear(&rfmt); 02260 02261 /* XXX EAGI FIXME XXX */ 02262 02263 if (argc < 6) 02264 return RESULT_SHOWUSAGE; 02265 if (sscanf(argv[5], "%30d", &ms) != 1) 02266 return RESULT_SHOWUSAGE; 02267 02268 if (argc > 6) 02269 silencestr = strchr(argv[6],'s'); 02270 if ((argc > 7) && (!silencestr)) 02271 silencestr = strchr(argv[7],'s'); 02272 if ((argc > 8) && (!silencestr)) 02273 silencestr = strchr(argv[8],'s'); 02274 02275 if (silencestr) { 02276 if (strlen(silencestr) > 2) { 02277 if ((silencestr[0] == 's') && (silencestr[1] == '=')) { 02278 silencestr++; 02279 silencestr++; 02280 if (silencestr) 02281 silence = atoi(silencestr); 02282 if (silence > 0) 02283 silence *= 1000; 02284 } 02285 } 02286 } 02287 02288 if (silence > 0) { 02289 ast_format_copy(&rfmt, &chan->readformat); 02290 res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR); 02291 if (res < 0) { 02292 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 02293 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02294 return RESULT_FAILURE; 02295 } 02296 sildet = ast_dsp_new(); 02297 if (!sildet) { 02298 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 02299 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 02300 return RESULT_FAILURE; 02301 } 02302 ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE)); 02303 } 02304 02305 /* backward compatibility, if no offset given, arg[6] would have been 02306 * caught below and taken to be a beep, else if it is a digit then it is a 02307 * offset */ 02308 if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '='))) 02309 res = ast_streamfile(chan, "beep", ast_channel_language(chan)); 02310 02311 if ((argc > 7) && (!strchr(argv[7], '='))) 02312 res = ast_streamfile(chan, "beep", ast_channel_language(chan)); 02313 02314 if (!res) 02315 res = ast_waitstream(chan, argv[4]); 02316 if (res) { 02317 ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset); 02318 } else { 02319 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE); 02320 if (!fs) { 02321 res = -1; 02322 ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res); 02323 if (sildet) 02324 ast_dsp_free(sildet); 02325 return RESULT_FAILURE; 02326 } 02327 02328 /* Request a video update */ 02329 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 02330 02331 chan->stream = fs; 02332 ast_applystream(chan,fs); 02333 /* really should have checks */ 02334 ast_seekstream(fs, sample_offset, SEEK_SET); 02335 ast_truncstream(fs); 02336 02337 start = ast_tvnow(); 02338 while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) { 02339 res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start)); 02340 if (res < 0) { 02341 ast_closestream(fs); 02342 ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset); 02343 if (sildet) 02344 ast_dsp_free(sildet); 02345 return RESULT_FAILURE; 02346 } 02347 f = ast_read(chan); 02348 if (!f) { 02349 ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset); 02350 ast_closestream(fs); 02351 if (sildet) 02352 ast_dsp_free(sildet); 02353 return RESULT_FAILURE; 02354 } 02355 switch(f->frametype) { 02356 case AST_FRAME_DTMF: 02357 if (strchr(argv[4], f->subclass.integer)) { 02358 /* This is an interrupting chracter, so rewind to chop off any small 02359 amount of DTMF that may have been recorded 02360 */ 02361 ast_stream_rewind(fs, 200); 02362 ast_truncstream(fs); 02363 sample_offset = ast_tellstream(fs); 02364 ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass.integer, sample_offset); 02365 ast_closestream(fs); 02366 ast_frfree(f); 02367 if (sildet) 02368 ast_dsp_free(sildet); 02369 return RESULT_SUCCESS; 02370 } 02371 break; 02372 case AST_FRAME_VOICE: 02373 ast_writestream(fs, f); 02374 /* this is a safe place to check progress since we know that fs 02375 * is valid after a write, and it will then have our current 02376 * location */ 02377 sample_offset = ast_tellstream(fs); 02378 if (silence > 0) { 02379 dspsilence = 0; 02380 ast_dsp_silence(sildet, f, &dspsilence); 02381 if (dspsilence) { 02382 totalsilence = dspsilence; 02383 } else { 02384 totalsilence = 0; 02385 } 02386 if (totalsilence > silence) { 02387 /* Ended happily with silence */ 02388 gotsilence = 1; 02389 break; 02390 } 02391 } 02392 break; 02393 case AST_FRAME_VIDEO: 02394 ast_writestream(fs, f); 02395 default: 02396 /* Ignore all other frames */ 02397 break; 02398 } 02399 ast_frfree(f); 02400 if (gotsilence) 02401 break; 02402 } 02403 02404 if (gotsilence) { 02405 ast_stream_rewind(fs, silence-1000); 02406 ast_truncstream(fs); 02407 sample_offset = ast_tellstream(fs); 02408 } 02409 ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset); 02410 ast_closestream(fs); 02411 } 02412 02413 if (silence > 0) { 02414 res = ast_set_read_format(chan, &rfmt); 02415 if (res) 02416 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan)); 02417 ast_dsp_free(sildet); 02418 } 02419 02420 return RESULT_SUCCESS; 02421 }
| static int handle_recvchar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1813 of file res_agi.c.
References ast_agi_send(), ast_recvchar(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01814 { 01815 int res; 01816 01817 if (argc != 3) 01818 return RESULT_SHOWUSAGE; 01819 01820 res = ast_recvchar(chan,atoi(argv[2])); 01821 if (res == 0) { 01822 ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res); 01823 return RESULT_SUCCESS; 01824 } 01825 if (res > 0) { 01826 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01827 return RESULT_SUCCESS; 01828 } 01829 ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res); 01830 return RESULT_FAILURE; 01831 }
| static int handle_recvtext | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1833 of file res_agi.c.
References ast_agi_send(), ast_free, ast_recvtext(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01834 { 01835 char *buf; 01836 01837 if (argc != 3) 01838 return RESULT_SHOWUSAGE; 01839 01840 buf = ast_recvtext(chan, atoi(argv[2])); 01841 if (buf) { 01842 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf); 01843 ast_free(buf); 01844 } else { 01845 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01846 } 01847 return RESULT_SUCCESS; 01848 }
| static int handle_sayalpha | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2086 of file res_agi.c.
References ast_agi_send(), ast_channel_language(), ast_say_character_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02087 { 02088 int res; 02089 02090 if (argc != 4) 02091 return RESULT_SHOWUSAGE; 02092 02093 res = ast_say_character_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl); 02094 if (res == 1) /* New command */ 02095 return RESULT_SUCCESS; 02096 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02097 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 02098 }
| static int handle_saydate | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2100 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.
02101 { 02102 int res, num; 02103 02104 if (argc != 4) 02105 return RESULT_SHOWUSAGE; 02106 if (sscanf(argv[2], "%30d", &num) != 1) 02107 return RESULT_SHOWUSAGE; 02108 res = ast_say_date(chan, num, argv[3], ast_channel_language(chan)); 02109 if (res == 1) 02110 return RESULT_SUCCESS; 02111 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02112 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 02113 }
| static int handle_saydatetime | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2130 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, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02131 { 02132 int res = 0; 02133 time_t unixtime; 02134 const char *format, *zone = NULL; 02135 02136 if (argc < 4) 02137 return RESULT_SHOWUSAGE; 02138 02139 if (argc > 4) { 02140 format = argv[4]; 02141 } else { 02142 /* XXX this doesn't belong here, but in the 'say' module */ 02143 if (!strcasecmp(ast_channel_language(chan), "de")) { 02144 format = "A dBY HMS"; 02145 } else { 02146 format = "ABdY 'digits/at' IMp"; 02147 } 02148 } 02149 02150 if (argc > 5 && !ast_strlen_zero(argv[5])) 02151 zone = argv[5]; 02152 02153 if (ast_get_time_t(argv[2], &unixtime, 0, NULL)) 02154 return RESULT_SHOWUSAGE; 02155 02156 res = ast_say_date_with_format(chan, unixtime, argv[3], ast_channel_language(chan), format, zone); 02157 if (res == 1) 02158 return RESULT_SUCCESS; 02159 02160 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02161 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 02162 }
| static int handle_saydigits | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2070 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.
02071 { 02072 int res, num; 02073 02074 if (argc != 4) 02075 return RESULT_SHOWUSAGE; 02076 if (sscanf(argv[2], "%30d", &num) != 1) 02077 return RESULT_SHOWUSAGE; 02078 02079 res = ast_say_digit_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl); 02080 if (res == 1) /* New command */ 02081 return RESULT_SUCCESS; 02082 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02083 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 02084 }
| 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 2055 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, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02056 { 02057 int res, num; 02058 02059 if (argc < 4 || argc > 5) 02060 return RESULT_SHOWUSAGE; 02061 if (sscanf(argv[2], "%30d", &num) != 1) 02062 return RESULT_SHOWUSAGE; 02063 res = ast_say_number_full(chan, num, argv[3], ast_channel_language(chan), argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl); 02064 if (res == 1) 02065 return RESULT_SUCCESS; 02066 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02067 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 02068 }
| static int handle_sayphonetic | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2164 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.
02165 { 02166 int res; 02167 02168 if (argc != 4) 02169 return RESULT_SHOWUSAGE; 02170 02171 res = ast_say_phonetic_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl); 02172 if (res == 1) /* New command */ 02173 return RESULT_SUCCESS; 02174 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02175 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 02176 }
| static int handle_saytime | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2115 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.
02116 { 02117 int res, num; 02118 02119 if (argc != 4) 02120 return RESULT_SHOWUSAGE; 02121 if (sscanf(argv[2], "%30d", &num) != 1) 02122 return RESULT_SHOWUSAGE; 02123 res = ast_say_time(chan, num, argv[3], ast_channel_language(chan)); 02124 if (res == 1) 02125 return RESULT_SUCCESS; 02126 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 02127 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 02128 }
| static int handle_sendimage | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1878 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.
01879 { 01880 int res; 01881 01882 if (argc != 3) { 01883 return RESULT_SHOWUSAGE; 01884 } 01885 01886 res = ast_send_image(chan, argv[2]); 01887 if (!ast_check_hangup(chan)) { 01888 res = 0; 01889 } 01890 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01891 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01892 }
| static int handle_sendtext | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1794 of file res_agi.c.
References ast_agi_send(), ast_sendtext(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01795 { 01796 int res; 01797 01798 if (argc != 3) 01799 return RESULT_SHOWUSAGE; 01800 01801 /* At the moment, the parser (perhaps broken) returns with 01802 the last argument PLUS the newline at the end of the input 01803 buffer. This probably needs to be fixed, but I wont do that 01804 because other stuff may break as a result. The right way 01805 would probably be to strip off the trailing newline before 01806 parsing, then here, add a newline at the end of the string 01807 before sending it to ast_sendtext --DUDE */ 01808 res = ast_sendtext(chan, argv[2]); 01809 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01810 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01811 }
| static int handle_setcallerid | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2516 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, and RESULT_SUCCESS.
02517 { 02518 char tmp[256]=""; 02519 char *l = NULL, *n = NULL; 02520 02521 if (argv[2]) { 02522 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02523 ast_callerid_parse(tmp, &n, &l); 02524 if (l) 02525 ast_shrink_phone_number(l); 02526 else 02527 l = ""; 02528 if (!n) 02529 n = ""; 02530 ast_set_callerid(chan, l, n, NULL); 02531 } 02532 02533 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02534 return RESULT_SUCCESS; 02535 }
| static int handle_setcontext | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2205 of file res_agi.c.
References ast_agi_send(), ast_copy_string(), ast_channel::context, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02206 { 02207 02208 if (argc != 3) 02209 return RESULT_SHOWUSAGE; 02210 ast_copy_string(chan->context, argv[2], sizeof(chan->context)); 02211 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02212 return RESULT_SUCCESS; 02213 }
| static int handle_setextension | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2215 of file res_agi.c.
References ast_agi_send(), ast_copy_string(), ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02216 { 02217 if (argc != 3) 02218 return RESULT_SHOWUSAGE; 02219 ast_copy_string(chan->exten, argv[2], sizeof(chan->exten)); 02220 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02221 return RESULT_SUCCESS; 02222 }
| static int handle_setmusic | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2747 of file res_agi.c.
References ast_agi_send(), ast_moh_start(), ast_moh_stop(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02748 { 02749 if (argc < 3) { 02750 return RESULT_SHOWUSAGE; 02751 } 02752 if (!strncasecmp(argv[2], "on", 2)) 02753 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL); 02754 else if (!strncasecmp(argv[2], "off", 3)) 02755 ast_moh_stop(chan); 02756 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02757 return RESULT_SUCCESS; 02758 }
| static int handle_setpriority | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2224 of file res_agi.c.
References ast_agi_send(), ast_explicit_goto(), ast_findlabel_extension(), ast_channel::caller, ast_channel::context, ast_channel::exten, agi_state::fd, ast_party_caller::id, ast_party_id::number, RESULT_SHOWUSAGE, RESULT_SUCCESS, S_COR, ast_party_number::str, and ast_party_number::valid.
02225 { 02226 int pri; 02227 02228 if (argc != 3) 02229 return RESULT_SHOWUSAGE; 02230 02231 if (sscanf(argv[2], "%30d", &pri) != 1) { 02232 pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], 02233 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 02234 if (pri < 1) 02235 return RESULT_SHOWUSAGE; 02236 } 02237 02238 ast_explicit_goto(chan, NULL, NULL, pri); 02239 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02240 return RESULT_SUCCESS; 02241 }
| static int handle_setvariable | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2559 of file res_agi.c.
References ast_agi_send(), agi_state::fd, pbx_builtin_setvar_helper(), and RESULT_SUCCESS.
02560 { 02561 if (argv[3]) 02562 pbx_builtin_setvar_helper(chan, argv[2], argv[3]); 02563 02564 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02565 return RESULT_SUCCESS; 02566 }
| static int handle_speechactivategrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2852 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_activate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02853 { 02854 if (argc != 4) 02855 return RESULT_SHOWUSAGE; 02856 02857 if (!agi->speech) { 02858 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02859 return RESULT_SUCCESS; 02860 } 02861 02862 if (ast_speech_grammar_activate(agi->speech, argv[3])) 02863 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02864 else 02865 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02866 02867 return RESULT_SUCCESS; 02868 }
| static int handle_speechcreate | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2760 of file res_agi.c.
References ast_agi_send(), ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_set(), AST_FORMAT_SLINEAR, ast_speech_new(), agi_state::fd, RESULT_FAILURE, RESULT_SUCCESS, and agi_state::speech.
02761 { 02762 struct ast_format_cap *cap; 02763 struct ast_format tmpfmt; 02764 02765 /* If a structure already exists, return an error */ 02766 if (agi->speech) { 02767 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02768 return RESULT_SUCCESS; 02769 } 02770 02771 if (!(cap = ast_format_cap_alloc_nolock())) { 02772 return RESULT_FAILURE; 02773 } 02774 ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); 02775 if ((agi->speech = ast_speech_new(argv[2], cap))) { 02776 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02777 } else { 02778 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02779 } 02780 cap = ast_format_cap_destroy(cap); 02781 02782 return RESULT_SUCCESS; 02783 }
| static int handle_speechdeactivategrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2870 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_deactivate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02871 { 02872 if (argc != 4) 02873 return RESULT_SHOWUSAGE; 02874 02875 if (!agi->speech) { 02876 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02877 return RESULT_SUCCESS; 02878 } 02879 02880 if (ast_speech_grammar_deactivate(agi->speech, argv[3])) 02881 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02882 else 02883 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02884 02885 return RESULT_SUCCESS; 02886 }
| static int handle_speechdestroy | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2803 of file res_agi.c.
References ast_agi_send(), ast_speech_destroy(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
02804 { 02805 if (agi->speech) { 02806 ast_speech_destroy(agi->speech); 02807 agi->speech = NULL; 02808 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02809 } else { 02810 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02811 } 02812 02813 return RESULT_SUCCESS; 02814 }
| static int handle_speechloadgrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2816 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_load(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02817 { 02818 if (argc != 5) 02819 return RESULT_SHOWUSAGE; 02820 02821 if (!agi->speech) { 02822 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02823 return RESULT_SUCCESS; 02824 } 02825 02826 if (ast_speech_grammar_load(agi->speech, argv[3], argv[4])) 02827 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02828 else 02829 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02830 02831 return RESULT_SUCCESS; 02832 }
| static int handle_speechrecognize | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2907 of file res_agi.c.
References ast_agi_send(), ast_build_string(), ast_channel_language(), ast_clear_flag, AST_CONTROL_HANGUP, ast_format_copy(), AST_FORMAT_SLINEAR, 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_by_id(), 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(), ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, ast_speech_result::grammar, ast_frame_subclass::integer, ast_speech::lock, ast_speech::processing_sound, prompt, ast_frame::ptr, ast_channel::readformat, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_speech::results, ast_channel::sched, ast_speech_result::score, agi_state::speech, speech_streamfile(), ast_speech::state, ast_channel::stream, ast_channel::streamid, ast_frame::subclass, ast_speech_result::text, and ast_channel::timingfunc.
02908 { 02909 struct ast_speech *speech = agi->speech; 02910 const char *prompt; 02911 char dtmf = 0, tmp[4096] = "", *buf = tmp; 02912 int timeout = 0, offset = 0, res = 0, i = 0; 02913 struct ast_format old_read_format; 02914 long current_offset = 0; 02915 const char *reason = NULL; 02916 struct ast_frame *fr = NULL; 02917 struct ast_speech_result *result = NULL; 02918 size_t left = sizeof(tmp); 02919 time_t start = 0, current; 02920 02921 if (argc < 4) 02922 return RESULT_SHOWUSAGE; 02923 02924 if (!speech) { 02925 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02926 return RESULT_SUCCESS; 02927 } 02928 02929 prompt = argv[2]; 02930 timeout = atoi(argv[3]); 02931 02932 /* If offset is specified then convert from text to integer */ 02933 if (argc == 5) 02934 offset = atoi(argv[4]); 02935 02936 /* We want frames coming in signed linear */ 02937 ast_format_copy(&old_read_format, &chan->readformat); 02938 if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) { 02939 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02940 return RESULT_SUCCESS; 02941 } 02942 02943 /* Setup speech structure */ 02944 if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) { 02945 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 02946 ast_speech_start(speech); 02947 } 02948 02949 /* Start playing prompt */ 02950 speech_streamfile(chan, prompt, ast_channel_language(chan), offset); 02951 02952 /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */ 02953 while (ast_strlen_zero(reason)) { 02954 /* Run scheduled items */ 02955 ast_sched_runq(chan->sched); 02956 02957 /* See maximum time of waiting */ 02958 if ((res = ast_sched_wait(chan->sched)) < 0) 02959 res = 1000; 02960 02961 /* Wait for frame */ 02962 if (ast_waitfor(chan, res) > 0) { 02963 if (!(fr = ast_read(chan))) { 02964 reason = "hangup"; 02965 break; 02966 } 02967 } 02968 02969 /* Perform timeout check */ 02970 if ((timeout > 0) && (start > 0)) { 02971 time(¤t); 02972 if ((current - start) >= timeout) { 02973 reason = "timeout"; 02974 if (fr) 02975 ast_frfree(fr); 02976 break; 02977 } 02978 } 02979 02980 /* Check the speech structure for any changes */ 02981 ast_mutex_lock(&speech->lock); 02982 02983 /* See if we need to quiet the audio stream playback */ 02984 if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) { 02985 current_offset = ast_tellstream(chan->stream); 02986 ast_stopstream(chan); 02987 ast_clear_flag(speech, AST_SPEECH_QUIET); 02988 } 02989 02990 /* Check each state */ 02991 switch (speech->state) { 02992 case AST_SPEECH_STATE_READY: 02993 /* If the stream is done, start timeout calculation */ 02994 if ((timeout > 0) && start == 0 && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) { 02995 ast_stopstream(chan); 02996 time(&start); 02997 } 02998 /* Write audio frame data into speech engine if possible */ 02999 if (fr && fr->frametype == AST_FRAME_VOICE) 03000 ast_speech_write(speech, fr->data.ptr, fr->datalen); 03001 break; 03002 case AST_SPEECH_STATE_WAIT: 03003 /* Cue waiting sound if not already playing */ 03004 if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) { 03005 ast_stopstream(chan); 03006 /* If a processing sound exists, or is not none - play it */ 03007 if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none")) 03008 speech_streamfile(chan, speech->processing_sound, ast_channel_language(chan), 0); 03009 } 03010 break; 03011 case AST_SPEECH_STATE_DONE: 03012 /* Get the results */ 03013 speech->results = ast_speech_results_get(speech); 03014 /* Change state to not ready */ 03015 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 03016 reason = "speech"; 03017 break; 03018 default: 03019 break; 03020 } 03021 ast_mutex_unlock(&speech->lock); 03022 03023 /* Check frame for DTMF or hangup */ 03024 if (fr) { 03025 if (fr->frametype == AST_FRAME_DTMF) { 03026 reason = "dtmf"; 03027 dtmf = fr->subclass.integer; 03028 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_HANGUP) { 03029 reason = "hangup"; 03030 } 03031 ast_frfree(fr); 03032 } 03033 } 03034 03035 if (!strcasecmp(reason, "speech")) { 03036 /* Build string containing speech results */ 03037 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) { 03038 /* Build result string */ 03039 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); 03040 /* Increment result count */ 03041 i++; 03042 } 03043 /* Print out */ 03044 ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp); 03045 } else if (!strcasecmp(reason, "dtmf")) { 03046 ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset); 03047 } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) { 03048 ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset); 03049 } else { 03050 ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset); 03051 } 03052 03053 return RESULT_SUCCESS; 03054 }
| static int handle_speechset | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2785 of file res_agi.c.
References ast_agi_send(), ast_speech_change(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02786 { 02787 /* Check for minimum arguments */ 02788 if (argc != 4) 02789 return RESULT_SHOWUSAGE; 02790 02791 /* Check to make sure speech structure exists */ 02792 if (!agi->speech) { 02793 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02794 return RESULT_SUCCESS; 02795 } 02796 02797 ast_speech_change(agi->speech, argv[2], argv[3]); 02798 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02799 02800 return RESULT_SUCCESS; 02801 }
| static int handle_speechunloadgrammar | ( | 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_speech_grammar_unload(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02835 { 02836 if (argc != 4) 02837 return RESULT_SHOWUSAGE; 02838 02839 if (!agi->speech) { 02840 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02841 return RESULT_SUCCESS; 02842 } 02843 02844 if (ast_speech_grammar_unload(agi->speech, argv[3])) 02845 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02846 else 02847 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02848 02849 return RESULT_SUCCESS; 02850 }
| static int handle_streamfile | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1930 of file res_agi.c.
References ast_agi_send(), ast_applystream(), ast_channel_language(), ast_debug, 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, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.
01931 { 01932 int res; 01933 struct ast_filestream *fs, *vfs; 01934 long sample_offset = 0, max_length; 01935 const char *edigits = ""; 01936 01937 if (argc < 4 || argc > 5) { 01938 return RESULT_SHOWUSAGE; 01939 } 01940 01941 if (argv[3]) { 01942 edigits = argv[3]; 01943 } 01944 01945 if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1)) { 01946 return RESULT_SHOWUSAGE; 01947 } 01948 01949 if (!(fs = ast_openstream(chan, argv[2], ast_channel_language(chan)))) { 01950 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset); 01951 return RESULT_SUCCESS; 01952 } 01953 01954 if ((vfs = ast_openvstream(chan, argv[2], ast_channel_language(chan)))) { 01955 ast_debug(1, "Ooh, found a video stream, too\n"); 01956 } 01957 01958 ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset); 01959 01960 ast_seekstream(fs, 0, SEEK_END); 01961 max_length = ast_tellstream(fs); 01962 ast_seekstream(fs, sample_offset, SEEK_SET); 01963 res = ast_applystream(chan, fs); 01964 if (vfs) { 01965 ast_applystream(chan, vfs); 01966 } 01967 ast_playstream(fs); 01968 if (vfs) { 01969 ast_playstream(vfs); 01970 } 01971 01972 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 01973 /* this is to check for if ast_waitstream closed the stream, we probably are at 01974 * the end of the stream, return that amount, else check for the amount */ 01975 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; 01976 ast_stopstream(chan); 01977 if (res == 1) { 01978 /* Stop this command, don't print a result line, as there is a new command */ 01979 return RESULT_SUCCESS; 01980 } 01981 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset); 01982 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01983 }
| static int handle_tddmode | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1850 of file res_agi.c.
References ast_agi_send(), ast_channel_setoption(), AST_OPTION_TDD, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01851 { 01852 int res, x; 01853 01854 if (argc != 3) 01855 return RESULT_SHOWUSAGE; 01856 01857 if (!strncasecmp(argv[2],"on",2)) { 01858 x = 1; 01859 } else { 01860 x = 0; 01861 } 01862 if (!strncasecmp(argv[2],"mate",4)) { 01863 x = 2; 01864 } 01865 if (!strncasecmp(argv[2],"tdd",3)) { 01866 x = 1; 01867 } 01868 res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0); 01869 if (res) { 01870 /* Set channel option failed */ 01871 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01872 } else { 01873 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01874 } 01875 return RESULT_SUCCESS; 01876 }
| static int handle_verbose | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 2625 of file res_agi.c.
References ast_agi_send(), ast_verb, ast_channel::data, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02626 { 02627 int level = 0; 02628 02629 if (argc < 2) 02630 return RESULT_SHOWUSAGE; 02631 02632 if (argv[2]) 02633 sscanf(argv[2], "%30d", &level); 02634 02635 ast_verb(level, "%s: %s\n", chan->data, argv[1]); 02636 02637 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02638 02639 return RESULT_SUCCESS; 02640 }
| static int handle_waitfordigit | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| const char *const | argv[] | |||
| ) | [static] |
Definition at line 1781 of file res_agi.c.
References ast_agi_send(), ast_waitfordigit_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01782 { 01783 int res, to; 01784 01785 if (argc != 4) 01786 return RESULT_SHOWUSAGE; 01787 if (sscanf(argv[3], "%30d", &to) != 1) 01788 return RESULT_SHOWUSAGE; 01789 res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl); 01790 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01791 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01792 }
| static char* help_workhorse | ( | int | fd, | |
| const char *const | match[] | |||
| ) | [static] |
Definition at line 3110 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().
03111 { 03112 char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN]; 03113 struct agi_command *e; 03114 03115 if (match) 03116 ast_join(matchstr, sizeof(matchstr), match); 03117 03118 ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description"); 03119 AST_RWLIST_RDLOCK(&agi_commands); 03120 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 03121 if (!e->cmda[0]) 03122 break; 03123 /* Hide commands that start with '_' */ 03124 if ((e->cmda[0])[0] == '_') 03125 continue; 03126 ast_join(fullcmd, sizeof(fullcmd), e->cmda); 03127 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr))) 03128 continue; 03129 ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, S_OR(e->summary, "Not available")); 03130 } 03131 AST_RWLIST_UNLOCK(&agi_commands); 03132 03133 return CLI_SUCCESS; 03134 }
| static enum agi_result launch_asyncagi | ( | struct ast_channel * | chan, | |
| char * | argv[], | |||
| int * | efd | |||
| ) | [static] |
Definition at line 1231 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_check_hangup(), ast_debug, 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, EVENT_FLAG_AGI, agi_state::fast, agi_state::fd, free_agi_cmd(), get_agi_cmd(), LOG_ERROR, LOG_WARNING, manager_event, setup_env(), and agi_state::speech.
Referenced by launch_script().
01232 { 01233 /* This buffer sizes might cause truncation if the AGI command writes more data 01234 than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command 01235 that writes a response larger than 1024 bytes?, I don't think so, most of 01236 them are just result=blah stuff. However probably if GET VARIABLE is called 01237 and the variable has large amount of data, that could be a problem. We could 01238 make this buffers dynamic, but let's leave that as a second step. 01239 01240 AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe 01241 number. Some characters of AGI buf will be url encoded to be sent to manager 01242 clients. An URL encoded character will take 3 bytes, but again, to cause 01243 truncation more than about 70% of the AGI buffer should be URL encoded for 01244 that to happen. Not likely at all. 01245 01246 On the other hand. I wonder if read() could eventually return less data than 01247 the amount already available in the pipe? If so, how to deal with that? 01248 So far, my tests on Linux have not had any problems. 01249 */ 01250 #define AGI_BUF_SIZE 1024 01251 #define AMI_BUF_SIZE 2048 01252 enum agi_result cmd_status; 01253 struct agi_cmd *cmd; 01254 int res; 01255 int fds[2]; 01256 int hungup; 01257 int timeout = 100; 01258 char agi_buffer[AGI_BUF_SIZE + 1]; 01259 char ami_buffer[AMI_BUF_SIZE]; 01260 enum agi_result returnstatus = AGI_RESULT_SUCCESS; 01261 AGI async_agi; 01262 01263 if (efd) { 01264 ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n"); 01265 return AGI_RESULT_FAILURE; 01266 } 01267 01268 /* add AsyncAGI datastore to the channel */ 01269 if (add_to_agi(chan)) { 01270 ast_log(LOG_ERROR, "Failed to start Async AGI on channel %s\n", ast_channel_name(chan)); 01271 return AGI_RESULT_FAILURE; 01272 } 01273 01274 /* this pipe allows us to create a "fake" AGI struct to use 01275 the AGI commands */ 01276 res = pipe(fds); 01277 if (res) { 01278 ast_log(LOG_ERROR, "Failed to create Async AGI pipe\n"); 01279 /* 01280 * Intentionally do not remove the datastore added with 01281 * add_to_agi() the from channel. It will be removed when the 01282 * channel is hung up anyway. 01283 */ 01284 return AGI_RESULT_FAILURE; 01285 } 01286 01287 /* handlers will get the pipe write fd and we read the AGI responses 01288 from the pipe read fd */ 01289 async_agi.fd = fds[1]; 01290 async_agi.ctrl = fds[1]; 01291 async_agi.audio = -1; /* no audio support */ 01292 async_agi.fast = 0; 01293 async_agi.speech = NULL; 01294 01295 /* notify possible manager users of a new channel ready to 01296 receive commands */ 01297 setup_env(chan, "async", fds[1], 0, 0, NULL); 01298 /* read the environment */ 01299 res = read(fds[0], agi_buffer, AGI_BUF_SIZE); 01300 if (!res) { 01301 ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s\n", 01302 ast_channel_name(chan)); 01303 returnstatus = AGI_RESULT_FAILURE; 01304 goto async_agi_abort; 01305 } 01306 agi_buffer[res] = '\0'; 01307 /* encode it and send it thru the manager so whoever is going to take 01308 care of AGI commands on this channel can decide which AGI commands 01309 to execute based on the setup info */ 01310 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http); 01311 manager_event(EVENT_FLAG_AGI, "AsyncAGI", 01312 "SubEvent: Start\r\n" 01313 "Channel: %s\r\n" 01314 "Env: %s\r\n", ast_channel_name(chan), ami_buffer); 01315 hungup = ast_check_hangup(chan); 01316 for (;;) { 01317 /* 01318 * Process as many commands as we can. Commands are added via 01319 * the manager or the cli threads. 01320 */ 01321 while (!hungup && (cmd = get_agi_cmd(chan))) { 01322 /* OK, we have a command, let's call the command handler. */ 01323 cmd_status = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0); 01324 01325 /* 01326 * The command handler must have written to our fake AGI struct 01327 * fd (the pipe), let's read the response. 01328 */ 01329 res = read(fds[0], agi_buffer, AGI_BUF_SIZE); 01330 if (!res) { 01331 ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s\n", 01332 ast_channel_name(chan)); 01333 free_agi_cmd(cmd); 01334 returnstatus = AGI_RESULT_FAILURE; 01335 goto async_agi_done; 01336 } 01337 /* 01338 * We have a response, let's send the response thru the manager. 01339 * Include the CommandID if it was specified when the command 01340 * was added. 01341 */ 01342 agi_buffer[res] = '\0'; 01343 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http); 01344 if (ast_strlen_zero(cmd->cmd_id)) { 01345 manager_event(EVENT_FLAG_AGI, "AsyncAGI", 01346 "SubEvent: Exec\r\n" 01347 "Channel: %s\r\n" 01348 "Result: %s\r\n", ast_channel_name(chan), ami_buffer); 01349 } else { 01350 manager_event(EVENT_FLAG_AGI, "AsyncAGI", 01351 "SubEvent: Exec\r\n" 01352 "Channel: %s\r\n" 01353 "CommandID: %s\r\n" 01354 "Result: %s\r\n", ast_channel_name(chan), cmd->cmd_id, ami_buffer); 01355 } 01356 free_agi_cmd(cmd); 01357 01358 /* 01359 * Check the command status to determine if we should continue 01360 * executing more commands. 01361 */ 01362 hungup = ast_check_hangup(chan); 01363 switch (cmd_status) { 01364 case AGI_RESULT_FAILURE: 01365 if (!hungup) { 01366 /* The failure was not because of a hangup. */ 01367 returnstatus = AGI_RESULT_FAILURE; 01368 goto async_agi_done; 01369 } 01370 break; 01371 case AGI_RESULT_SUCCESS_ASYNC: 01372 /* Only the "asyncagi break" command does this. */ 01373 returnstatus = AGI_RESULT_SUCCESS_ASYNC; 01374 goto async_agi_done; 01375 default: 01376 break; 01377 } 01378 } 01379 01380 if (!hungup) { 01381 /* Wait a bit for a frame to read or to poll for a new command. */ 01382 res = ast_waitfor(chan, timeout); 01383 if (res < 0) { 01384 ast_debug(1, "ast_waitfor returned <= 0 on chan %s\n", ast_channel_name(chan)); 01385 returnstatus = AGI_RESULT_FAILURE; 01386 break; 01387 } 01388 } else { 01389 /* 01390 * Read the channel control queue until it is dry so we can 01391 * quit. 01392 */ 01393 res = 1; 01394 } 01395 if (0 < res) { 01396 do { 01397 cmd_status = async_agi_read_frame(chan); 01398 if (cmd_status != AGI_RESULT_SUCCESS) { 01399 returnstatus = cmd_status; 01400 goto async_agi_done; 01401 } 01402 hungup = ast_check_hangup(chan); 01403 } while (hungup); 01404 } else { 01405 hungup = ast_check_hangup(chan); 01406 } 01407 } 01408 async_agi_done: 01409 01410 if (async_agi.speech) { 01411 ast_speech_destroy(async_agi.speech); 01412 } 01413 /* notify manager users this channel cannot be 01414 controlled anymore by Async AGI */ 01415 manager_event(EVENT_FLAG_AGI, "AsyncAGI", 01416 "SubEvent: End\r\n" 01417 "Channel: %s\r\n", ast_channel_name(chan)); 01418 01419 async_agi_abort: 01420 /* close the pipe */ 01421 close(fds[0]); 01422 close(fds[1]); 01423 01424 /* 01425 * Intentionally do not remove the datastore added with 01426 * add_to_agi() the from channel. There might be commands still 01427 * in the queue or in-flight to us and AsyncAGI may get called 01428 * again. The datastore destructor will be called on channel 01429 * destruction anyway. 01430 */ 01431 01432 if (returnstatus == AGI_RESULT_SUCCESS) { 01433 returnstatus = AGI_RESULT_SUCCESS_ASYNC; 01434 } 01435 return returnstatus; 01436 01437 #undef AGI_BUF_SIZE 01438 #undef AMI_BUF_SIZE 01439 }
| static enum agi_result launch_ha_netscript | ( | char * | agiurl, | |
| char * | argv[], | |||
| int * | fds | |||
| ) | [static] |
Definition at line 1545 of file res_agi.c.
References AGI_RESULT_FAILURE, AGI_RESULT_NOTFOUND, ast_log(), ast_srv_cleanup(), ast_srv_lookup(), ast_strdupa, context, launch_netscript(), LOG_WARNING, service, and SRV_PREFIX.
Referenced by launch_script().
01546 { 01547 char *host, *script; 01548 enum agi_result result; 01549 struct srv_context *context = NULL; 01550 int srv_ret; 01551 char service[256]; 01552 char resolved_uri[1024]; 01553 const char *srvhost; 01554 unsigned short srvport; 01555 01556 /* format of agiurl is "hagi://host.domain[:port][/script/name]" */ 01557 if (!(host = ast_strdupa(agiurl + 7))) { /* Remove hagi:// */ 01558 ast_log(LOG_WARNING, "An error occurred parsing the AGI URI: %s", agiurl); 01559 return AGI_RESULT_FAILURE; 01560 } 01561 01562 /* Strip off any script name */ 01563 if ((script = strchr(host, '/'))) { 01564 *script++ = '\0'; 01565 } else { 01566 script = ""; 01567 } 01568 01569 if (strchr(host, ':')) { 01570 ast_log(LOG_WARNING, "Specifying a port number disables SRV lookups: %s\n", agiurl); 01571 return launch_netscript(agiurl + 1, argv, fds); /* +1 to strip off leading h from hagi:// */ 01572 } 01573 01574 snprintf(service, sizeof(service), "%s%s", SRV_PREFIX, host); 01575 01576 while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) { 01577 snprintf(resolved_uri, sizeof(resolved_uri), "agi://%s:%d/%s", srvhost, srvport, script); 01578 result = launch_netscript(resolved_uri, argv, fds); 01579 if (result == AGI_RESULT_FAILURE || result == AGI_RESULT_NOTFOUND) { 01580 ast_log(LOG_WARNING, "AGI request failed for host '%s' (%s:%d)\n", host, srvhost, srvport); 01581 } else { 01582 /* The script launched so we must cleanup the context. */ 01583 ast_srv_cleanup(&context); 01584 return result; 01585 } 01586 } 01587 /* 01588 * The DNS SRV lookup failed or we ran out of servers to check. 01589 * ast_srv_lookup() has already cleaned up the context for us. 01590 */ 01591 if (srv_ret < 0) { 01592 ast_log(LOG_WARNING, "SRV lookup failed for %s\n", agiurl); 01593 } 01594 01595 return AGI_RESULT_FAILURE; 01596 }
| static enum agi_result launch_netscript | ( | char * | agiurl, | |
| char * | argv[], | |||
| int * | fds | |||
| ) | [static] |
Definition at line 1443 of file res_agi.c.
References AGI_PORT, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS_FAST, ast_agi_send(), ast_debug, ast_gethostbyname(), ast_log(), ast_poll, ast_strdupa, ast_strlen_zero(), errno, hp, LOG_WARNING, and MAX_AGI_CONNECT.
Referenced by launch_ha_netscript(), and launch_script().
01444 { 01445 int s, flags, res, port = AGI_PORT; 01446 struct pollfd pfds[1]; 01447 char *host, *c, *script; 01448 struct sockaddr_in addr_in; 01449 struct hostent *hp; 01450 struct ast_hostent ahp; 01451 01452 /* agiurl is "agi://host.domain[:port][/script/name]" */ 01453 host = ast_strdupa(agiurl + 6); /* Remove agi:// */ 01454 /* Strip off any script name */ 01455 if ((script = strchr(host, '/'))) { 01456 *script++ = '\0'; 01457 } else { 01458 script = ""; 01459 } 01460 01461 if ((c = strchr(host, ':'))) { 01462 *c++ = '\0'; 01463 port = atoi(c); 01464 } 01465 if (!(hp = ast_gethostbyname(host, &ahp))) { 01466 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host); 01467 return AGI_RESULT_FAILURE; 01468 } 01469 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 01470 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 01471 return AGI_RESULT_FAILURE; 01472 } 01473 if ((flags = fcntl(s, F_GETFL)) < 0) { 01474 ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno)); 01475 close(s); 01476 return AGI_RESULT_FAILURE; 01477 } 01478 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { 01479 ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno)); 01480 close(s); 01481 return AGI_RESULT_FAILURE; 01482 } 01483 memset(&addr_in, 0, sizeof(addr_in)); 01484 addr_in.sin_family = AF_INET; 01485 addr_in.sin_port = htons(port); 01486 memcpy(&addr_in.sin_addr, hp->h_addr, sizeof(addr_in.sin_addr)); 01487 if (connect(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) && (errno != EINPROGRESS)) { 01488 ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno)); 01489 close(s); 01490 return AGI_RESULT_FAILURE; 01491 } 01492 01493 pfds[0].fd = s; 01494 pfds[0].events = POLLOUT; 01495 while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) { 01496 if (errno != EINTR) { 01497 if (!res) { 01498 ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n", 01499 agiurl, MAX_AGI_CONNECT); 01500 } else 01501 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 01502 close(s); 01503 return AGI_RESULT_FAILURE; 01504 } 01505 } 01506 01507 if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) { 01508 if (errno != EINTR) { 01509 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 01510 close(s); 01511 return AGI_RESULT_FAILURE; 01512 } 01513 } 01514 01515 /* If we have a script parameter, relay it to the fastagi server */ 01516 /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */ 01517 if (!ast_strlen_zero(script)) 01518 ast_agi_send(s, NULL, "agi_network_script: %s\n", script); 01519 01520 ast_debug(4, "Wow, connected!\n"); 01521 fds[0] = s; 01522 fds[1] = s; 01523 return AGI_RESULT_SUCCESS_FAST; 01524 }
| static enum agi_result launch_script | ( | struct ast_channel * | chan, | |
| char * | script, | |||
| char * | argv[], | |||
| int * | fds, | |||
| int * | efd, | |||
| int * | opid | |||
| ) | [static] |
Definition at line 1598 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_log(), ast_safe_fork(), ast_set_priority(), ast_verb, errno, launch_asyncagi(), launch_ha_netscript(), launch_netscript(), LOG_WARNING, and setenv().
Referenced by agi_exec_full().
01599 { 01600 char tmp[256]; 01601 int pid, toast[2], fromast[2], audio[2], res; 01602 struct stat st; 01603 01604 if (!strncasecmp(script, "agi://", 6)) { 01605 return (efd == NULL) ? launch_netscript(script, argv, fds) : AGI_RESULT_FAILURE; 01606 } 01607 if (!strncasecmp(script, "hagi://", 7)) { 01608 return (efd == NULL) ? launch_ha_netscript(script, argv, fds) : AGI_RESULT_FAILURE; 01609 } 01610 if (!strncasecmp(script, "agi:async", sizeof("agi:async") - 1)) { 01611 return launch_asyncagi(chan, argv, efd); 01612 } 01613 01614 if (script[0] != '/') { 01615 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script); 01616 script = tmp; 01617 } 01618 01619 /* Before even trying let's see if the file actually exists */ 01620 if (stat(script, &st)) { 01621 ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script); 01622 return AGI_RESULT_NOTFOUND; 01623 } 01624 01625 if (pipe(toast)) { 01626 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno)); 01627 return AGI_RESULT_FAILURE; 01628 } 01629 if (pipe(fromast)) { 01630 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno)); 01631 close(toast[0]); 01632 close(toast[1]); 01633 return AGI_RESULT_FAILURE; 01634 } 01635 if (efd) { 01636 if (pipe(audio)) { 01637 ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno)); 01638 close(fromast[0]); 01639 close(fromast[1]); 01640 close(toast[0]); 01641 close(toast[1]); 01642 return AGI_RESULT_FAILURE; 01643 } 01644 res = fcntl(audio[1], F_GETFL); 01645 if (res > -1) 01646 res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK); 01647 if (res < 0) { 01648 ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno)); 01649 close(fromast[0]); 01650 close(fromast[1]); 01651 close(toast[0]); 01652 close(toast[1]); 01653 close(audio[0]); 01654 close(audio[1]); 01655 return AGI_RESULT_FAILURE; 01656 } 01657 } 01658 01659 if ((pid = ast_safe_fork(1)) < 0) { 01660 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); 01661 return AGI_RESULT_FAILURE; 01662 } 01663 if (!pid) { 01664 /* Pass paths to AGI via environmental variables */ 01665 setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1); 01666 setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1); 01667 setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1); 01668 setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1); 01669 setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1); 01670 setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1); 01671 setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1); 01672 setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1); 01673 setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1); 01674 setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1); 01675 setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1); 01676 01677 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */ 01678 ast_set_priority(0); 01679 01680 /* Redirect stdin and out, provide enhanced audio channel if desired */ 01681 dup2(fromast[0], STDIN_FILENO); 01682 dup2(toast[1], STDOUT_FILENO); 01683 if (efd) 01684 dup2(audio[0], STDERR_FILENO + 1); 01685 else 01686 close(STDERR_FILENO + 1); 01687 01688 /* Close everything but stdin/out/error */ 01689 ast_close_fds_above_n(STDERR_FILENO + 1); 01690 01691 /* Execute script */ 01692 /* XXX argv should be deprecated in favor of passing agi_argX paramaters */ 01693 execv(script, argv); 01694 /* Can't use ast_log since FD's are closed */ 01695 ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno)); 01696 /* Special case to set status of AGI to failure */ 01697 fprintf(stdout, "failure\n"); 01698 fflush(stdout); 01699 _exit(1); 01700 } 01701 ast_verb(3, "Launched AGI Script %s\n", script); 01702 fds[0] = toast[0]; 01703 fds[1] = fromast[1]; 01704 if (efd) 01705 *efd = audio[1]; 01706 /* close what we're not using in the parent */ 01707 close(toast[1]); 01708 close(fromast[0]); 01709 01710 if (efd) 01711 close(audio[0]); 01712 01713 *opid = pid; 01714 return AGI_RESULT_SUCCESS; 01715 }
| static int load_module | ( | void | ) | [static] |
Definition at line 4008 of file res_agi.c.
References action_add_agi_cmd(), agi_exec(), ARRAY_LEN, ast_agi_register_multiple(), ast_cli_register_multiple(), ast_manager_register_xml, ast_register_application_xml, AST_TEST_REGISTER, cli_agi, commands, deadagi_exec(), eagi_exec(), and EVENT_FLAG_AGI.
04009 { 04010 ast_cli_register_multiple(cli_agi, ARRAY_LEN(cli_agi)); 04011 /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as 04012 no other commands have been registered yet 04013 */ 04014 (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 04015 ast_register_application_xml(deadapp, deadagi_exec); 04016 ast_register_application_xml(eapp, eagi_exec); 04017 ast_manager_register_xml("AGI", EVENT_FLAG_AGI, action_add_agi_cmd); 04018 AST_TEST_REGISTER(test_agi_null_docs); 04019 return ast_register_application_xml(app, agi_exec); 04020 }
| static int parse_args | ( | char * | s, | |
| int * | max, | |||
| const char * | argv[] | |||
| ) | [static] |
Definition at line 3305 of file res_agi.c.
References ast_log(), LOG_WARNING, and MAX_ARGS.
03306 { 03307 int x = 0, quoted = 0, escaped = 0, whitespace = 1; 03308 char *cur; 03309 03310 cur = s; 03311 while(*s) { 03312 switch(*s) { 03313 case '"': 03314 /* If it's escaped, put a literal quote */ 03315 if (escaped) 03316 goto normal; 03317 else 03318 quoted = !quoted; 03319 if (quoted && whitespace) { 03320 /* If we're starting a quote, coming off white space start a new word, too */ 03321 argv[x++] = cur; 03322 whitespace=0; 03323 } 03324 escaped = 0; 03325 break; 03326 case ' ': 03327 case '\t': 03328 if (!quoted && !escaped) { 03329 /* If we're not quoted, mark this as whitespace, and 03330 end the previous argument */ 03331 whitespace = 1; 03332 *(cur++) = '\0'; 03333 } else 03334 /* Otherwise, just treat it as anything else */ 03335 goto normal; 03336 break; 03337 case '\\': 03338 /* If we're escaped, print a literal, otherwise enable escaping */ 03339 if (escaped) { 03340 goto normal; 03341 } else { 03342 escaped=1; 03343 } 03344 break; 03345 default: 03346 normal: 03347 if (whitespace) { 03348 if (x >= MAX_ARGS -1) { 03349 ast_log(LOG_WARNING, "Too many arguments, truncating\n"); 03350 break; 03351 } 03352 /* Coming off of whitespace, start the next argument */ 03353 argv[x++] = cur; 03354 whitespace=0; 03355 } 03356 *(cur++) = *s; 03357 escaped=0; 03358 } 03359 s++; 03360 } 03361 /* Null terminate */ 03362 *(cur++) = '\0'; 03363 argv[x] = NULL; 03364 *max = x; 03365 return 0; 03366 }
| 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] |
Definition at line 3464 of file res_agi.c.
References AGI_BUF_LEN, agi_handle_command(), AGI_NANDFS_RETRY, AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS, ast_agi_send(), 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_strlen_zero(), ast_verb, ast_verbose, ast_waitfor_nandfds(), agi_state::audio, agi_state::ctrl, ast_frame::data, ast_frame::datalen, errno, f, agi_state::fast, agi_state::fd, ast_frame::frametype, len(), LOG_WARNING, pbx_builtin_getvar_helper(), ast_frame::ptr, setup_env(), and agi_state::speech.
Referenced by agi_exec_full().
03465 { 03466 struct ast_channel *c; 03467 int outfd; 03468 int ms; 03469 int needhup = 0; 03470 enum agi_result returnstatus = AGI_RESULT_SUCCESS; 03471 struct ast_frame *f; 03472 char buf[AGI_BUF_LEN]; 03473 char *res = NULL; 03474 FILE *readf; 03475 /* how many times we'll retry if ast_waitfor_nandfs will return without either 03476 channel or file descriptor in case select is interrupted by a system call (EINTR) */ 03477 int retry = AGI_NANDFS_RETRY; 03478 int send_sighup; 03479 const char *sighup_str; 03480 03481 ast_channel_lock(chan); 03482 sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP"); 03483 send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str); 03484 ast_channel_unlock(chan); 03485 03486 if (!(readf = fdopen(agi->ctrl, "r"))) { 03487 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n"); 03488 if (send_sighup && pid > -1) 03489 kill(pid, SIGHUP); 03490 close(agi->ctrl); 03491 return AGI_RESULT_FAILURE; 03492 } 03493 03494 setlinebuf(readf); 03495 setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv); 03496 for (;;) { 03497 if (needhup) { 03498 needhup = 0; 03499 dead = 1; 03500 if (send_sighup) { 03501 if (pid > -1) { 03502 kill(pid, SIGHUP); 03503 } else if (agi->fast) { 03504 ast_agi_send(agi->fd, chan, "HANGUP\n"); 03505 } 03506 } 03507 } 03508 ms = -1; 03509 if (dead) { 03510 c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms); 03511 } else if (!ast_check_hangup(chan)) { 03512 c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms); 03513 } else { 03514 /* 03515 * Read the channel control queue until it is dry so we can 03516 * switch to dead mode. 03517 */ 03518 c = chan; 03519 } 03520 if (c) { 03521 retry = AGI_NANDFS_RETRY; 03522 /* Idle the channel until we get a command */ 03523 f = ast_read(c); 03524 if (!f) { 03525 ast_debug(1, "%s hungup\n", ast_channel_name(chan)); 03526 needhup = 1; 03527 if (!returnstatus) { 03528 returnstatus = AGI_RESULT_HANGUP; 03529 } 03530 } else { 03531 /* If it's voice, write it to the audio pipe */ 03532 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) { 03533 /* Write, ignoring errors */ 03534 if (write(agi->audio, f->data.ptr, f->datalen) < 0) { 03535 } 03536 } 03537 ast_frfree(f); 03538 } 03539 } else if (outfd > -1) { 03540 size_t len = sizeof(buf); 03541 size_t buflen = 0; 03542 enum agi_result cmd_status; 03543 03544 retry = AGI_NANDFS_RETRY; 03545 buf[0] = '\0'; 03546 03547 while (len > 1) { 03548 res = fgets(buf + buflen, len, readf); 03549 if (feof(readf)) 03550 break; 03551 if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN))) 03552 break; 03553 if (res != NULL && !agi->fast) 03554 break; 03555 buflen = strlen(buf); 03556 if (buflen && buf[buflen - 1] == '\n') 03557 break; 03558 len = sizeof(buf) - buflen; 03559 if (agidebug) 03560 ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno)); 03561 } 03562 03563 if (!buf[0]) { 03564 /* Program terminated */ 03565 ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", ast_channel_name(chan), request, returnstatus); 03566 if (pid > 0) 03567 waitpid(pid, status, 0); 03568 /* No need to kill the pid anymore, since they closed us */ 03569 pid = -1; 03570 break; 03571 } 03572 03573 /* Special case for inability to execute child process */ 03574 if (*buf && strncasecmp(buf, "failure", 7) == 0) { 03575 returnstatus = AGI_RESULT_FAILURE; 03576 break; 03577 } 03578 03579 /* get rid of trailing newline, if any */ 03580 buflen = strlen(buf); 03581 if (buflen && buf[buflen - 1] == '\n') { 03582 buf[buflen - 1] = '\0'; 03583 } 03584 03585 if (agidebug) 03586 ast_verbose("<%s>AGI Rx << %s\n", ast_channel_name(chan), buf); 03587 cmd_status = agi_handle_command(chan, agi, buf, dead); 03588 switch (cmd_status) { 03589 case AGI_RESULT_FAILURE: 03590 if (dead || !ast_check_hangup(chan)) { 03591 /* The failure was not because of a hangup. */ 03592 returnstatus = AGI_RESULT_FAILURE; 03593 } 03594 break; 03595 default: 03596 break; 03597 } 03598 } else { 03599 if (--retry <= 0) { 03600 ast_log(LOG_WARNING, "No channel, no fd?\n"); 03601 returnstatus = AGI_RESULT_FAILURE; 03602 break; 03603 } 03604 } 03605 } 03606 if (agi->speech) { 03607 ast_speech_destroy(agi->speech); 03608 } 03609 /* Notify process */ 03610 if (send_sighup) { 03611 if (pid > -1) { 03612 if (kill(pid, SIGHUP)) { 03613 ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno)); 03614 } else { /* Give the process a chance to die */ 03615 usleep(1); 03616 } 03617 waitpid(pid, status, WNOHANG); 03618 } else if (agi->fast) { 03619 ast_agi_send(agi->fd, chan, "HANGUP\n"); 03620 } 03621 } 03622 fclose(readf); 03623 return returnstatus; 03624 }
| static void setup_env | ( | struct ast_channel * | chan, | |
| char * | request, | |||
| int | fd, | |||
| int | enhanced, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1717 of file res_agi.c.
References ast_party_caller::ani2, ast_agi_send(), ast_channel_accountcode(), ast_channel_language(), ast_channel_name(), ast_channel_uniqueid(), ast_get_version(), ast_party_id_presentation(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, ast_party_redirecting::from, ast_party_caller::id, ast_party_id::name, ast_party_dialed::number, ast_party_id::number, ast_party_number::plan, ast_channel::priority, ast_channel::redirecting, S_COR, S_OR, ast_party_dialed::str, ast_party_name::str, ast_party_number::str, ast_channel::tech, ast_party_dialed::transit_network_select, ast_channel_tech::type, ast_party_name::valid, and ast_party_number::valid.
Referenced by launch_asyncagi(), and run_agi().
01718 { 01719 int count; 01720 01721 /* Print initial environment, with agi_request always being the first 01722 thing */ 01723 ast_agi_send(fd, chan, "agi_request: %s\n", request); 01724 ast_agi_send(fd, chan, "agi_channel: %s\n", ast_channel_name(chan)); 01725 ast_agi_send(fd, chan, "agi_language: %s\n", ast_channel_language(chan)); 01726 ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type); 01727 ast_agi_send(fd, chan, "agi_uniqueid: %s\n", ast_channel_uniqueid(chan)); 01728 ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version()); 01729 01730 /* ANI/DNIS */ 01731 ast_agi_send(fd, chan, "agi_callerid: %s\n", 01732 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "unknown")); 01733 ast_agi_send(fd, chan, "agi_calleridname: %s\n", 01734 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "unknown")); 01735 ast_agi_send(fd, chan, "agi_callingpres: %d\n", 01736 ast_party_id_presentation(&chan->caller.id)); 01737 ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->caller.ani2); 01738 ast_agi_send(fd, chan, "agi_callington: %d\n", chan->caller.id.number.plan); 01739 ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->dialed.transit_network_select); 01740 ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->dialed.number.str, "unknown")); 01741 ast_agi_send(fd, chan, "agi_rdnis: %s\n", 01742 S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "unknown")); 01743 01744 /* Context information */ 01745 ast_agi_send(fd, chan, "agi_context: %s\n", chan->context); 01746 ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten); 01747 ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority); 01748 ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0"); 01749 01750 /* User information */ 01751 ast_agi_send(fd, chan, "agi_accountcode: %s\n", ast_channel_accountcode(chan) ? ast_channel_accountcode(chan) : ""); 01752 ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self()); 01753 01754 /* Send any parameters to the fastagi server that have been passed via the agi application */ 01755 /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */ 01756 for(count = 1; count < argc; count++) 01757 ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]); 01758 01759 /* End with empty return */ 01760 ast_agi_send(fd, chan, "\n"); 01761 }
| static int speech_streamfile | ( | struct ast_channel * | chan, | |
| const char * | filename, | |||
| const char * | preflang, | |||
| int | offset | |||
| ) | [static] |
Definition at line 2888 of file res_agi.c.
References ast_applystream(), ast_openstream(), ast_playstream(), and ast_seekstream().
02889 { 02890 struct ast_filestream *fs = NULL; 02891 02892 if (!(fs = ast_openstream(chan, filename, preflang))) 02893 return -1; 02894 02895 if (offset) 02896 ast_seekstream(fs, offset, SEEK_SET); 02897 02898 if (ast_applystream(chan, fs)) 02899 return -1; 02900 02901 if (ast_playstream(fs)) 02902 return -1; 02903 02904 return 0; 02905 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 3994 of file res_agi.c.
References ARRAY_LEN, ast_agi_unregister_multiple(), ast_cli_unregister_multiple(), ast_manager_unregister(), AST_TEST_UNREGISTER, ast_unregister_application(), cli_agi, and commands.
03995 { 03996 ast_cli_unregister_multiple(cli_agi, ARRAY_LEN(cli_agi)); 03997 /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as 03998 we know that these commands were registered by this module and are still registered 03999 */ 04000 (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 04001 ast_unregister_application(eapp); 04002 ast_unregister_application(deadapp); 04003 ast_manager_unregister("AGI"); 04004 AST_TEST_UNREGISTER(test_agi_null_docs); 04005 return ast_unregister_application(app); 04006 }
| static void write_html_escaped | ( | FILE * | htmlfile, | |
| char * | str | |||
| ) | [static] |
Convert string to use HTML escaped characters.
Definition at line 3732 of file res_agi.c.
Referenced by write_htmldump().
03733 { 03734 char *cur = str; 03735 03736 while(*cur) { 03737 switch (*cur) { 03738 case '<': 03739 fprintf(htmlfile, "%s", "<"); 03740 break; 03741 case '>': 03742 fprintf(htmlfile, "%s", ">"); 03743 break; 03744 case '&': 03745 fprintf(htmlfile, "%s", "&"); 03746 break; 03747 case '"': 03748 fprintf(htmlfile, "%s", """); 03749 break; 03750 default: 03751 fprintf(htmlfile, "%c", *cur); 03752 break; 03753 } 03754 cur++; 03755 } 03756 03757 return; 03758 }
| static int write_htmldump | ( | const char * | filename | ) | [static] |
Definition at line 3760 of file res_agi.c.
References ast_free, ast_join(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, agi_command::cmda, agi_command::list, MAX_CMD_LEN, strsep(), agi_command::summary, agi_command::usage, and write_html_escaped().
Referenced by handle_cli_agi_dump_html().
03761 { 03762 struct agi_command *command; 03763 char fullcmd[MAX_CMD_LEN]; 03764 FILE *htmlfile; 03765 03766 if (!(htmlfile = fopen(filename, "wt"))) 03767 return -1; 03768 03769 fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n"); 03770 fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n"); 03771 fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n"); 03772 03773 AST_RWLIST_RDLOCK(&agi_commands); 03774 AST_RWLIST_TRAVERSE(&agi_commands, command, list) { 03775 #ifdef AST_XML_DOCS 03776 char *stringptmp; 03777 #endif 03778 char *tempstr, *stringp; 03779 03780 if (!command->cmda[0]) /* end ? */ 03781 break; 03782 /* Hide commands that start with '_' */ 03783 if ((command->cmda[0])[0] == '_') 03784 continue; 03785 ast_join(fullcmd, sizeof(fullcmd), command->cmda); 03786 03787 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n"); 03788 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary); 03789 #ifdef AST_XML_DOCS 03790 stringptmp = ast_xmldoc_printable(command->usage, 0); 03791 stringp = ast_strdup(stringptmp); 03792 #else 03793 stringp = ast_strdup(command->usage); 03794 #endif 03795 tempstr = strsep(&stringp, "\n"); 03796 03797 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">"); 03798 write_html_escaped(htmlfile, tempstr); 03799 fprintf(htmlfile, "</TD></TR>\n"); 03800 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n"); 03801 03802 while ((tempstr = strsep(&stringp, "\n")) != NULL) { 03803 write_html_escaped(htmlfile, tempstr); 03804 fprintf(htmlfile, "<BR>\n"); 03805 } 03806 fprintf(htmlfile, "</TD></TR>\n"); 03807 fprintf(htmlfile, "</TABLE></TD></TR>\n\n"); 03808 ast_free(stringp); 03809 #ifdef AST_XML_DOCS 03810 ast_free(stringptmp); 03811 #endif 03812 } 03813 AST_RWLIST_UNLOCK(&agi_commands); 03814 fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n"); 03815 fclose(htmlfile); 03816 return 0; 03817 }
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, } [static] |
struct ast_threadstorage agi_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_agi_buf , .custom_init = NULL , } [static] |
struct ast_datastore_info agi_commands_datastore_info [static] |
Initial value:
{
.type = "AsyncAGI",
.destroy = agi_destroy_commands_cb
}
Definition at line 997 of file res_agi.c.
Referenced by add_agi_cmd(), add_to_agi(), and get_agi_cmd().
struct ast_module_info* ast_module_info = &__mod_info [static] |
struct ast_cli_entry cli_agi[] [static] |
struct agi_command commands[] [static] |
AGI commands list.
Definition at line 3059 of file res_agi.c.
Referenced by aji_dinfo_handler(), dundi_showframe(), load_module(), and unload_module().
1.5.6