AGI - the Asterisk Gateway Interface. More...
#include "asterisk.h"#include <math.h>#include <signal.h>#include <sys/time.h>#include <sys/wait.h>#include <sys/stat.h>#include <pthread.h>#include "asterisk/paths.h"#include "asterisk/network.h"#include "asterisk/file.h"#include "asterisk/channel.h"#include "asterisk/pbx.h"#include "asterisk/module.h"#include "asterisk/astdb.h"#include "asterisk/callerid.h"#include "asterisk/cli.h"#include "asterisk/image.h"#include "asterisk/say.h"#include "asterisk/app.h"#include "asterisk/dsp.h"#include "asterisk/musiconhold.h"#include "asterisk/utils.h"#include "asterisk/lock.h"#include "asterisk/strings.h"#include "asterisk/agi.h"#include "asterisk/manager.h"#include "asterisk/ast_version.h"#include "asterisk/speech.h"#include "asterisk/features.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 | MAX_AGI_CONNECT 2000 |
| #define | MAX_ARGS 128 |
| #define | TONE_BLOCK_SIZE 200 |
Enumerations | |
| enum | agi_result { AGI_RESULT_FAILURE = -1, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_FAST, AGI_RESULT_SUCCESS_ASYNC, AGI_RESULT_NOTFOUND, AGI_RESULT_HANGUP } |
Functions | |
| static void | __init_agi_buf (void) |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | action_add_agi_cmd (struct mansession *s, const struct message *m) |
| Add a new command to execute by the Async AGI application. | |
| 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, void *data) |
| static int | agi_exec_full (struct ast_channel *chan, void *data, int enhanced, int dead) |
| static int | agi_handle_command (struct ast_channel *chan, AGI *agi, char *buf, int dead) |
| int | ast_agi_register (struct ast_module *mod, agi_command *cmd) |
| int | 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_agi_send (int fd, struct ast_channel *chan, char *fmt,...) |
| Sends a string of text to an application connected via AGI. | |
| int | ast_agi_unregister (struct ast_module *mod, agi_command *cmd) |
| int | 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 int | deadagi_exec (struct ast_channel *chan, void *data) |
| static int | eagi_exec (struct ast_channel *chan, void *data) |
| static agi_command * | find_command (char *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, char *argv[]) |
| static int | handle_asyncagi_break (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_autohangup (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_channelstatus (struct ast_channel *chan, AGI *agi, int argc, char **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_dumphtml_deprecated (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, char *argv[]) |
| static int | handle_dbdel (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_dbdeltree (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_dbget (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_dbput (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_exec (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_getdata (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_getoption (struct ast_channel *chan, AGI *agi, int argc, char *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, char **argv) |
| static int | handle_getvariablefull (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_hangup (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_noop (struct ast_channel *chan, AGI *agi, int arg, char *argv[]) |
| static int | handle_recordfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_recvchar (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_recvtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_sayalpha (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_saydate (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_saydatetime (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_saydigits (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_saynumber (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| Say number in various language syntaxes. | |
| static int | handle_sayphonetic (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_saytime (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_sendimage (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_sendtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_setcallerid (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_setcontext (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_setextension (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_setmusic (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_setpriority (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_setvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_speechactivategrammar (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_speechcreate (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_speechdeactivategrammar (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_speechdestroy (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_speechloadgrammar (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_speechrecognize (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_speechset (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_speechunloadgrammar (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_streamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_tddmode (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_verbose (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static int | handle_waitfordigit (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static char * | help_workhorse (int fd, char *match[]) |
| static enum agi_result | launch_asyncagi (struct ast_channel *chan, char *argv[], int *efd) |
| static enum agi_result | launch_netscript (char *agiurl, char *argv[], int *fds, int *efd, int *opid) |
| 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, 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 (char *filename) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } |
| 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 ast_cli_entry | cli_agi_dumphtml_deprecated = AST_CLI_DEFINE(handle_cli_agi_dumphtml_deprecated, "Dumps a list of AGI commands in HTML format") |
| static struct agi_command | commands [] |
| AGI commands list. | |
| static char * | deadapp = "DeadAGI" |
| static char * | deadsynopsis = "Executes AGI on a hungup channel" |
| static char * | descrip |
| static char * | eapp = "EAGI" |
| static char * | esynopsis = "Executes an EAGI compliant application" |
| static const char | mandescr_asyncagi [] |
| static char * | synopsis = "Executes an AGI compliant application" |
| static char | usage_answer [] |
| static char | usage_asyncagi_break [] |
| static char | usage_autohangup [] |
| static char | usage_channelstatus [] |
| static char | usage_controlstreamfile [] |
| static char | usage_dbdel [] |
| static char | usage_dbdeltree [] |
| static char | usage_dbget [] |
| static char | usage_dbput [] |
| static char | usage_exec [] |
| static char | usage_getdata [] |
| static char | usage_getoption [] |
| static char | usage_getvariable [] |
| static char | usage_getvariablefull [] |
| static char | usage_hangup [] |
| static char | usage_noop [] |
| static char | usage_recordfile [] |
| static char | usage_recvchar [] |
| static char | usage_recvtext [] |
| static char | usage_sayalpha [] |
| static char | usage_saydate [] |
| static char | usage_saydatetime [] |
| static char | usage_saydigits [] |
| static char | usage_saynumber [] |
| static char | usage_sayphonetic [] |
| static char | usage_saytime [] |
| static char | usage_sendimage [] |
| static char | usage_sendtext [] |
| static char | usage_setcallerid [] |
| static char | usage_setcontext [] |
| static char | usage_setextension [] |
| static char | usage_setmusic [] |
| static char | usage_setpriority [] |
| static char | usage_setvariable [] |
| static char | usage_speechactivategrammar [] |
| static char | usage_speechcreate [] |
| static char | usage_speechdeactivategrammar [] |
| static char | usage_speechdestroy [] |
| static char | usage_speechloadgrammar [] |
| static char | usage_speechrecognize [] |
| static char | usage_speechset [] |
| static char | usage_speechunloadgrammar [] |
| static char | usage_streamfile [] |
| static char | usage_tddmode [] |
| static char | usage_verbose [] |
| static char | usage_waitfordigit [] |
AGI - the Asterisk Gateway Interface.
Definition in file res_agi.c.
| #define AGI_BUF_INITSIZE 256 |
Definition at line 116 of file res_agi.c.
Referenced by ast_agi_send().
| #define AGI_BUF_LEN 2048 |
Definition at line 63 of file res_agi.c.
Referenced by agi_exec_full(), and run_agi().
| #define AGI_BUF_SIZE 1024 |
Referenced by launch_asyncagi().
| #define AGI_PORT 4573 |
Definition at line 102 of file res_agi.c.
Referenced by launch_netscript().
| #define AMI_BUF_SIZE 2048 |
Referenced by launch_asyncagi().
| #define MAX_AGI_CONNECT 2000 |
Definition at line 100 of file res_agi.c.
Referenced by launch_netscript().
| 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 104 of file res_agi.c.
00104 { 00105 AGI_RESULT_FAILURE = -1, 00106 AGI_RESULT_SUCCESS, 00107 AGI_RESULT_SUCCESS_FAST, 00108 AGI_RESULT_SUCCESS_ASYNC, 00109 AGI_RESULT_NOTFOUND, 00110 AGI_RESULT_HANGUP, 00111 };
| 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 330 of file res_agi.c.
References add_agi_cmd(), ast_channel_unlock, ast_get_channel_by_name_locked(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), buf, and chan.
Referenced by load_module().
00331 { 00332 const char *channel = astman_get_header(m, "Channel"); 00333 const char *cmdbuff = astman_get_header(m, "Command"); 00334 const char *cmdid = astman_get_header(m, "CommandID"); 00335 struct ast_channel *chan; 00336 char buf[256]; 00337 if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) { 00338 astman_send_error(s, m, "Both, Channel and Command are *required*"); 00339 return 0; 00340 } 00341 chan = ast_get_channel_by_name_locked(channel); 00342 if (!chan) { 00343 snprintf(buf, sizeof(buf), "Channel %s does not exists or cannot get its lock", channel); 00344 astman_send_error(s, m, buf); 00345 return 0; 00346 } 00347 if (add_agi_cmd(chan, cmdbuff, cmdid)) { 00348 snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", chan->name); 00349 astman_send_error(s, m, buf); 00350 ast_channel_unlock(chan); 00351 return 0; 00352 } 00353 astman_send_ack(s, m, "Added AGI command to queue"); 00354 ast_channel_unlock(chan); 00355 return 0; 00356 }
| static int add_agi_cmd | ( | struct ast_channel * | chan, | |
| const char * | cmd_buff, | |||
| const char * | cmd_id | |||
| ) | [static] |
Definition at line 210 of file res_agi.c.
References agi_commands_datastore_info, ast_calloc, ast_channel_datastore_find(), 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().
00211 { 00212 struct ast_datastore *store; 00213 struct agi_cmd *cmd; 00214 AST_LIST_HEAD(, agi_cmd) *agi_commands; 00215 00216 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 00217 if (!store) { 00218 ast_log(LOG_WARNING, "Channel %s is not at Async AGI.\n", chan->name); 00219 return -1; 00220 } 00221 agi_commands = store->data; 00222 cmd = ast_calloc(1, sizeof(*cmd)); 00223 if (!cmd) { 00224 return -1; 00225 } 00226 cmd->cmd_buffer = ast_strdup(cmd_buff); 00227 if (!cmd->cmd_buffer) { 00228 ast_free(cmd); 00229 return -1; 00230 } 00231 cmd->cmd_id = ast_strdup(cmd_id); 00232 if (!cmd->cmd_id) { 00233 ast_free(cmd->cmd_buffer); 00234 ast_free(cmd); 00235 return -1; 00236 } 00237 AST_LIST_LOCK(agi_commands); 00238 AST_LIST_INSERT_TAIL(agi_commands, cmd, entry); 00239 AST_LIST_UNLOCK(agi_commands); 00240 return 0; 00241 }
| static int add_to_agi | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 243 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().
00244 { 00245 struct ast_datastore *datastore; 00246 AST_LIST_HEAD(, agi_cmd) *agi_cmds_list; 00247 00248 /* check if already on AGI */ 00249 ast_channel_lock(chan); 00250 datastore = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 00251 ast_channel_unlock(chan); 00252 if (datastore) { 00253 /* we already have an AGI datastore, let's just 00254 return success */ 00255 return 0; 00256 } 00257 00258 /* the channel has never been on Async AGI, 00259 let's allocate it's datastore */ 00260 datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI"); 00261 if (!datastore) { 00262 return -1; 00263 } 00264 agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list)); 00265 if (!agi_cmds_list) { 00266 ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n"); 00267 ast_datastore_free(datastore); 00268 return -1; 00269 } 00270 datastore->data = agi_cmds_list; 00271 AST_LIST_HEAD_INIT(agi_cmds_list); 00272 ast_channel_lock(chan); 00273 ast_channel_datastore_add(chan, datastore); 00274 ast_channel_unlock(chan); 00275 return 0; 00276 }
| static void agi_destroy_commands_cb | ( | void * | data | ) | [static] |
Definition at line 162 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().
00163 { 00164 struct agi_cmd *cmd; 00165 AST_LIST_HEAD(, agi_cmd) *chan_cmds = data; 00166 AST_LIST_LOCK(chan_cmds); 00167 while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) { 00168 free_agi_cmd(cmd); 00169 } 00170 AST_LIST_UNLOCK(chan_cmds); 00171 AST_LIST_HEAD_DESTROY(chan_cmds); 00172 ast_free(chan_cmds); 00173 }
| static int agi_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3030 of file res_agi.c.
References agi_exec_full(), and ast_check_hangup().
Referenced by deadagi_exec(), and load_module().
03031 { 03032 if (!ast_check_hangup(chan)) 03033 return agi_exec_full(chan, data, 0, 0); 03034 else 03035 return agi_exec_full(chan, data, 0, 1); 03036 }
| static int agi_exec_full | ( | struct ast_channel * | chan, | |
| void * | data, | |||
| int | enhanced, | |||
| int | dead | |||
| ) | [static] |
Definition at line 2963 of file res_agi.c.
References ast_channel::_state, AGI_BUF_LEN, AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_NOTFOUND, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, AGI_RESULT_SUCCESS_FAST, ast_answer(), AST_APP_ARG, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_log(), ast_safe_fork_cleanup(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strlen_zero(), buf, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), run_agi(), and status.
Referenced by agi_exec(), and eagi_exec().
02964 { 02965 enum agi_result res; 02966 char buf[AGI_BUF_LEN] = "", *tmp = buf; 02967 int fds[2], efd = -1, pid; 02968 AST_DECLARE_APP_ARGS(args, 02969 AST_APP_ARG(arg)[MAX_ARGS]; 02970 ); 02971 AGI agi; 02972 02973 if (ast_strlen_zero(data)) { 02974 ast_log(LOG_WARNING, "AGI requires an argument (script)\n"); 02975 return -1; 02976 } 02977 if (dead) 02978 ast_debug(3, "Hungup channel detected, running agi in dead mode.\n"); 02979 ast_copy_string(buf, data, sizeof(buf)); 02980 memset(&agi, 0, sizeof(agi)); 02981 AST_STANDARD_APP_ARGS(args, tmp); 02982 args.argv[args.argc] = NULL; 02983 #if 0 02984 /* Answer if need be */ 02985 if (chan->_state != AST_STATE_UP) { 02986 if (ast_answer(chan)) 02987 return -1; 02988 } 02989 #endif 02990 res = launch_script(chan, args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid); 02991 /* Async AGI do not require run_agi(), so just proceed if normal AGI 02992 or Fast AGI are setup with success. */ 02993 if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) { 02994 int status = 0; 02995 agi.fd = fds[1]; 02996 agi.ctrl = fds[0]; 02997 agi.audio = efd; 02998 agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0; 02999 res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv); 03000 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */ 03001 if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status) 03002 res = AGI_RESULT_FAILURE; 03003 if (fds[1] != fds[0]) 03004 close(fds[1]); 03005 if (efd > -1) 03006 close(efd); 03007 } 03008 ast_safe_fork_cleanup(); 03009 03010 switch (res) { 03011 case AGI_RESULT_SUCCESS: 03012 case AGI_RESULT_SUCCESS_FAST: 03013 case AGI_RESULT_SUCCESS_ASYNC: 03014 pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS"); 03015 break; 03016 case AGI_RESULT_FAILURE: 03017 pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE"); 03018 break; 03019 case AGI_RESULT_NOTFOUND: 03020 pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND"); 03021 break; 03022 case AGI_RESULT_HANGUP: 03023 pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP"); 03024 return -1; 03025 } 03026 03027 return 0; 03028 }
| static int agi_handle_command | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| char * | buf, | |||
| int | dead | |||
| ) | [static] |
Definition at line 2584 of file res_agi.c.
References ast_agi_send(), ast_cdr_setapp(), ast_check_hangup(), ast_module_ref(), ast_module_unref(), ast_random(), ast_strdupa, 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().
02585 { 02586 char *argv[MAX_ARGS]; 02587 int argc = MAX_ARGS, res; 02588 agi_command *c; 02589 const char *ami_res = "Unknown Result"; 02590 char *ami_cmd = ast_strdupa(buf); 02591 int command_id = ast_random(), resultcode = 200; 02592 02593 manager_event(EVENT_FLAG_AGI, "AGIExec", 02594 "SubEvent: Start\r\n" 02595 "Channel: %s\r\n" 02596 "CommandId: %d\r\n" 02597 "Command: %s\r\n", chan->name, command_id, ami_cmd); 02598 parse_args(buf, &argc, argv); 02599 if ((c = find_command(argv, 0)) && (!dead || (dead && c->dead))) { 02600 /* if this command wasnt registered by res_agi, be sure to usecount 02601 the module we are using */ 02602 if (c->mod != ast_module_info->self) 02603 ast_module_ref(c->mod); 02604 /* If the AGI command being executed is an actual application (using agi exec) 02605 the app field will be updated in pbx_exec via handle_exec */ 02606 if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC")) 02607 ast_cdr_setapp(chan->cdr, "AGI", buf); 02608 02609 res = c->handler(chan, agi, argc, argv); 02610 if (c->mod != ast_module_info->self) 02611 ast_module_unref(c->mod); 02612 switch (res) { 02613 case RESULT_SHOWUSAGE: ami_res = "Usage"; resultcode = 520; break; 02614 case RESULT_FAILURE: ami_res = "Failure"; resultcode = -1; break; 02615 case RESULT_SUCCESS: ami_res = "Success"; resultcode = 200; break; 02616 } 02617 manager_event(EVENT_FLAG_AGI, "AGIExec", 02618 "SubEvent: End\r\n" 02619 "Channel: %s\r\n" 02620 "CommandId: %d\r\n" 02621 "Command: %s\r\n" 02622 "ResultCode: %d\r\n" 02623 "Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res); 02624 switch(res) { 02625 case RESULT_SHOWUSAGE: 02626 ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n"); 02627 ast_agi_send(agi->fd, chan, "%s", c->usage); 02628 ast_agi_send(agi->fd, chan, "520 End of proper usage.\n"); 02629 break; 02630 case RESULT_FAILURE: 02631 /* They've already given the failure. We've been hung up on so handle this 02632 appropriately */ 02633 return -1; 02634 } 02635 } else if ((c = find_command(argv, 0))) { 02636 ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n"); 02637 manager_event(EVENT_FLAG_AGI, "AGIExec", 02638 "SubEvent: End\r\n" 02639 "Channel: %s\r\n" 02640 "CommandId: %d\r\n" 02641 "Command: %s\r\n" 02642 "ResultCode: 511\r\n" 02643 "Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd); 02644 } else { 02645 ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n"); 02646 manager_event(EVENT_FLAG_AGI, "AGIExec", 02647 "SubEvent: End\r\n" 02648 "Channel: %s\r\n" 02649 "CommandId: %d\r\n" 02650 "Command: %s\r\n" 02651 "ResultCode: 510\r\n" 02652 "Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd); 02653 } 02654 return 0; 02655 }
| int ast_agi_register | ( | struct ast_module * | mod, | |
| agi_command * | cmd | |||
| ) |
Definition at line 2389 of file res_agi.c.
References ast_join(), AST_LIST_INSERT_TAIL, ast_log(), ast_module_ref(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, agi_command::cmda, find_command(), LOG_WARNING, and agi_command::mod.
Referenced by ast_agi_register_multiple(), and load_module().
02390 { 02391 char fullcmd[80]; 02392 02393 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 02394 02395 if (!find_command(cmd->cmda,1)) { 02396 cmd->mod = mod; 02397 AST_RWLIST_WRLOCK(&agi_commands); 02398 AST_LIST_INSERT_TAIL(&agi_commands, cmd, list); 02399 AST_RWLIST_UNLOCK(&agi_commands); 02400 if (mod != ast_module_info->self) 02401 ast_module_ref(ast_module_info->self); 02402 ast_verb(2, "AGI Command '%s' registered\n",fullcmd); 02403 return 1; 02404 } else { 02405 ast_log(LOG_WARNING, "Command already registered!\n"); 02406 return 0; 02407 } 02408 }
| int 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 commands | |
| len | Length of the array (use the ARRAY_LEN macro to determine this easily) |
Definition at line 2437 of file res_agi.c.
References ast_agi_register(), and ast_agi_unregister().
Referenced by load_module().
02438 { 02439 unsigned int i, x = 0; 02440 02441 for (i = 0; i < len; i++) { 02442 if (ast_agi_register(mod, cmd + i) == 1) { 02443 x++; 02444 continue; 02445 } 02446 02447 /* registration failed, unregister everything 02448 that had been registered up to that point 02449 */ 02450 for (; x > 0; x--) { 02451 /* we are intentionally ignoring the 02452 result of ast_agi_unregister() here, 02453 but it should be safe to do so since 02454 we just registered these commands and 02455 the only possible way for unregistration 02456 to fail is if the command is not 02457 registered 02458 */ 02459 (void) ast_agi_unregister(mod, cmd + x - 1); 02460 } 02461 return -1; 02462 } 02463 02464 return 0; 02465 }
| int 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 118 of file res_agi.c.
References agi_buf, AGI_BUF_INITSIZE, ast_carefulwrite(), ast_log(), ast_str_set_va(), ast_str_thread_get(), ast_verbose, buf, LOG_ERROR, ast_str::str, and ast_str::used.
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(), and setup_env().
00119 { 00120 int res = 0; 00121 va_list ap; 00122 struct ast_str *buf; 00123 00124 if (!(buf = ast_str_thread_get(&agi_buf, AGI_BUF_INITSIZE))) 00125 return -1; 00126 00127 va_start(ap, fmt); 00128 res = ast_str_set_va(&buf, 0, fmt, ap); 00129 va_end(ap); 00130 00131 if (res == -1) { 00132 ast_log(LOG_ERROR, "Out of memory\n"); 00133 return -1; 00134 } 00135 00136 if (agidebug) { 00137 if (chan) { 00138 ast_verbose("<%s>AGI Tx >> %s", chan->name, buf->str); 00139 } else { 00140 ast_verbose("AGI Tx >> %s", buf->str); 00141 } 00142 } 00143 00144 return ast_carefulwrite(fd, buf->str, buf->used, 100); 00145 }
| int ast_agi_unregister | ( | struct ast_module * | mod, | |
| agi_command * | cmd | |||
| ) |
Definition at line 2410 of file res_agi.c.
References 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, agi_command::cmda, and LOG_WARNING.
Referenced by ast_agi_register_multiple(), ast_agi_unregister_multiple(), and unload_module().
02411 { 02412 struct agi_command *e; 02413 int unregistered = 0; 02414 char fullcmd[80]; 02415 02416 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 02417 02418 AST_RWLIST_WRLOCK(&agi_commands); 02419 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) { 02420 if (cmd == e) { 02421 AST_RWLIST_REMOVE_CURRENT(list); 02422 if (mod != ast_module_info->self) 02423 ast_module_unref(ast_module_info->self); 02424 unregistered=1; 02425 break; 02426 } 02427 } 02428 AST_RWLIST_TRAVERSE_SAFE_END; 02429 AST_RWLIST_UNLOCK(&agi_commands); 02430 if (unregistered) 02431 ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd); 02432 else 02433 ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd); 02434 return unregistered; 02435 }
| int 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 commands | |
| len | Length of the array (use the ARRAY_LEN macro to determine this easily) |
Definition at line 2467 of file res_agi.c.
References ast_agi_unregister().
Referenced by unload_module().
02468 { 02469 unsigned int i; 02470 int res = 0; 02471 02472 for (i = 0; i < len; i++) { 02473 /* remember whether any of the unregistration 02474 attempts failed... there is no recourse if 02475 any of them do 02476 */ 02477 res |= ast_agi_unregister(mod, cmd + i); 02478 } 02479 02480 return res; 02481 }
| static int deadagi_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3060 of file res_agi.c.
References agi_exec(), ast_log(), and LOG_WARNING.
Referenced by load_module().
03061 { 03062 ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n"); 03063 return agi_exec(chan, data); 03064 }
| static int eagi_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3038 of file res_agi.c.
References agi_exec_full(), ast_check_hangup(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), ast_set_read_format(), LOG_ERROR, LOG_WARNING, and ast_channel::readformat.
Referenced by load_module().
03039 { 03040 int readformat, res; 03041 03042 if (ast_check_hangup(chan)) { 03043 ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n"); 03044 return 0; 03045 } 03046 readformat = chan->readformat; 03047 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 03048 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name); 03049 return -1; 03050 } 03051 res = agi_exec_full(chan, data, 1, 0); 03052 if (!res) { 03053 if (ast_set_read_format(chan, readformat)) { 03054 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat)); 03055 } 03056 } 03057 return res; 03058 }
| static agi_command * find_command | ( | char * | cmds[], | |
| int | exact | |||
| ) | [static] |
Definition at line 2483 of file res_agi.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, and match().
Referenced by agi_handle_command(), ast_agi_register(), and handle_cli_agi_show().
02484 { 02485 int y, match; 02486 struct agi_command *e; 02487 02488 AST_RWLIST_RDLOCK(&agi_commands); 02489 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 02490 if (!e->cmda[0]) 02491 break; 02492 /* start optimistic */ 02493 match = 1; 02494 for (y = 0; match && cmds[y]; y++) { 02495 /* If there are no more words in the command (and we're looking for 02496 an exact match) or there is a difference between the two words, 02497 then this is not a match */ 02498 if (!e->cmda[y] && !exact) 02499 break; 02500 /* don't segfault if the next part of a command doesn't exist */ 02501 if (!e->cmda[y]) { 02502 AST_RWLIST_UNLOCK(&agi_commands); 02503 return NULL; 02504 } 02505 if (strcasecmp(e->cmda[y], cmds[y])) 02506 match = 0; 02507 } 02508 /* If more words are needed to complete the command then this is not 02509 a candidate (unless we're looking for a really inexact answer */ 02510 if ((exact > -1) && e->cmda[y]) 02511 match = 0; 02512 if (match) { 02513 AST_RWLIST_UNLOCK(&agi_commands); 02514 return e; 02515 } 02516 } 02517 AST_RWLIST_UNLOCK(&agi_commands); 02518 return NULL; 02519 }
| static void free_agi_cmd | ( | struct agi_cmd * | cmd | ) | [static] |
Definition at line 154 of file res_agi.c.
References ast_free.
Referenced by agi_destroy_commands_cb(), and launch_asyncagi().
00155 { 00156 ast_free(cmd->cmd_buffer); 00157 ast_free(cmd->cmd_id); 00158 ast_free(cmd); 00159 }
| static struct agi_cmd* get_agi_cmd | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 189 of file res_agi.c.
References agi_commands_datastore_info, ast_channel_datastore_find(), ast_channel_lock, 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().
00190 { 00191 struct ast_datastore *store; 00192 struct agi_cmd *cmd; 00193 AST_LIST_HEAD(, agi_cmd) *agi_commands; 00194 00195 ast_channel_lock(chan); 00196 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 00197 ast_channel_unlock(chan); 00198 if (!store) { 00199 ast_log(LOG_ERROR, "Hu? datastore disappeared at Async AGI on Channel %s!\n", chan->name); 00200 return NULL; 00201 } 00202 agi_commands = store->data; 00203 AST_LIST_LOCK(agi_commands); 00204 cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry); 00205 AST_LIST_UNLOCK(agi_commands); 00206 return cmd; 00207 }
| static int handle_answer | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 765 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.
00766 { 00767 int res = 0; 00768 00769 /* Answer the channel */ 00770 if (chan->_state != AST_STATE_UP) 00771 res = ast_answer(chan); 00772 00773 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00774 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00775 }
| static int handle_asyncagi_break | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 777 of file res_agi.c.
References ast_agi_send(), agi_state::fd, and RESULT_FAILURE.
00778 { 00779 ast_agi_send(agi->fd, chan, "200 result=0\n"); 00780 return RESULT_FAILURE; 00781 }
| static int handle_autohangup | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1413 of file res_agi.c.
References ast_agi_send(), ast_channel_setwhentohangup_tv(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01414 { 01415 double timeout; 01416 struct timeval whentohangup = { 0, 0 }; 01417 01418 if (argc != 3) 01419 return RESULT_SHOWUSAGE; 01420 if (sscanf(argv[2], "%30lf", &timeout) != 1) 01421 return RESULT_SHOWUSAGE; 01422 if (timeout < 0) 01423 timeout = 0; 01424 if (timeout) { 01425 whentohangup.tv_sec = timeout; 01426 whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0; 01427 } 01428 ast_channel_setwhentohangup_tv(chan, whentohangup); 01429 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01430 return RESULT_SUCCESS; 01431 }
| static int handle_channelstatus | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1528 of file res_agi.c.
References ast_channel::_state, ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01529 { 01530 struct ast_channel *c; 01531 if (argc == 2) { 01532 /* no argument: supply info on the current channel */ 01533 ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state); 01534 return RESULT_SUCCESS; 01535 } else if (argc == 3) { 01536 /* one argument: look for info on the specified channel */ 01537 c = ast_get_channel_by_name_locked(argv[2]); 01538 if (c) { 01539 ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state); 01540 ast_channel_unlock(c); 01541 return RESULT_SUCCESS; 01542 } 01543 /* if we get this far no channel name matched the argument given */ 01544 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01545 return RESULT_SUCCESS; 01546 } else { 01547 return RESULT_SHOWUSAGE; 01548 } 01549 }
| 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 287 of file res_agi.c.
References add_agi_cmd(), ast_cli_args::argc, ast_cli_args::argv, ast_channel_unlock, ast_complete_channels(), ast_get_channel_by_name_locked(), ast_log(), chan, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::line, LOG_DEBUG, LOG_WARNING, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
00288 { 00289 struct ast_channel *chan; 00290 switch (cmd) { 00291 case CLI_INIT: 00292 e->command = "agi exec"; 00293 e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n" 00294 " Add AGI command to the execute queue of the specified channel in Async AGI\n"; 00295 return NULL; 00296 case CLI_GENERATE: 00297 if (a->pos == 2) 00298 return ast_complete_channels(a->line, a->word, a->pos, a->n, 2); 00299 return NULL; 00300 } 00301 00302 if (a->argc < 4) 00303 return CLI_SHOWUSAGE; 00304 chan = ast_get_channel_by_name_locked(a->argv[2]); 00305 if (!chan) { 00306 ast_log(LOG_WARNING, "Channel %s does not exists or cannot lock it\n", a->argv[2]); 00307 return CLI_FAILURE; 00308 } 00309 if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) { 00310 ast_log(LOG_WARNING, "failed to add AGI command to queue of channel %s\n", chan->name); 00311 ast_channel_unlock(chan); 00312 return CLI_FAILURE; 00313 } 00314 ast_log(LOG_DEBUG, "Added AGI command to channel %s queue\n", chan->name); 00315 ast_channel_unlock(chan); 00316 return CLI_SUCCESS; 00317 }
| static char* handle_cli_agi_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1693 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.
01694 { 01695 switch (cmd) { 01696 case CLI_INIT: 01697 e->command = "agi set debug [on|off]"; 01698 e->usage = 01699 "Usage: agi set debug [on|off]\n" 01700 " Enables/disables dumping of AGI transactions for\n" 01701 " debugging purposes.\n"; 01702 return NULL; 01703 01704 case CLI_GENERATE: 01705 return NULL; 01706 } 01707 01708 if (a->argc != e->args) 01709 return CLI_SHOWUSAGE; 01710 01711 if (strncasecmp(a->argv[3], "off", 3) == 0) { 01712 agidebug = 0; 01713 } else if (strncasecmp(a->argv[3], "on", 2) == 0) { 01714 agidebug = 1; 01715 } else { 01716 return CLI_SHOWUSAGE; 01717 } 01718 ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis"); 01719 return CLI_SUCCESS; 01720 }
| static char* handle_cli_agi_dump_html | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2939 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().
02940 { 02941 switch (cmd) { 02942 case CLI_INIT: 02943 e->command = "agi dump html"; 02944 e->usage = 02945 "Usage: agi dump html <filename>\n" 02946 " Dumps the AGI command list in HTML format to the given\n" 02947 " file.\n"; 02948 return NULL; 02949 case CLI_GENERATE: 02950 return NULL; 02951 } 02952 if (a->argc != e->args + 1) 02953 return CLI_SHOWUSAGE; 02954 02955 if (write_htmldump(a->argv[e->args]) < 0) { 02956 ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]); 02957 return CLI_SHOWUSAGE; 02958 } 02959 ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]); 02960 return CLI_SUCCESS; 02961 }
| static char* handle_cli_agi_dumphtml_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2915 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().
02916 { 02917 switch (cmd) { 02918 case CLI_INIT: 02919 e->command = "agi dumphtml"; 02920 e->usage = 02921 "Usage: agi dumphtml <filename>\n" 02922 " Dumps the AGI command list in HTML format to the given\n" 02923 " file.\n"; 02924 return NULL; 02925 case CLI_GENERATE: 02926 return NULL; 02927 } 02928 if (a->argc < e->args + 1) 02929 return CLI_SHOWUSAGE; 02930 02931 if (write_htmldump(a->argv[2]) < 0) { 02932 ast_cli(a->fd, "Could not create file '%s'\n", a->argv[2]); 02933 return CLI_SHOWUSAGE; 02934 } 02935 ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[2]); 02936 return CLI_SUCCESS; 02937 }
| static char* handle_cli_agi_show | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2799 of file res_agi.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_join(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, agi_command::dead, ast_cli_args::fd, find_command(), help_workhorse(), agi_command::usage, and ast_cli_entry::usage.
02800 { 02801 struct agi_command *command; 02802 char fullcmd[80]; 02803 02804 switch (cmd) { 02805 case CLI_INIT: 02806 e->command = "agi show"; 02807 e->usage = 02808 "Usage: agi show [topic]\n" 02809 " When called with a topic as an argument, displays usage\n" 02810 " information on the given command. If called without a\n" 02811 " topic, it provides a list of AGI commands.\n"; 02812 case CLI_GENERATE: 02813 return NULL; 02814 } 02815 if (a->argc < e->args) 02816 return CLI_SHOWUSAGE; 02817 if (a->argc > e->args) { 02818 command = find_command(a->argv + e->args, 1); 02819 if (command) { 02820 ast_cli(a->fd, "%s", command->usage); 02821 ast_cli(a->fd, " Runs Dead : %s\n", command->dead ? "Yes" : "No"); 02822 } else { 02823 if (find_command(a->argv + e->args, -1)) { 02824 return help_workhorse(a->fd, a->argv + e->args); 02825 } else { 02826 ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args); 02827 ast_cli(a->fd, "No such command '%s'.\n", fullcmd); 02828 } 02829 } 02830 } else { 02831 return help_workhorse(a->fd, NULL); 02832 } 02833 return CLI_SUCCESS; 02834 }
| static int handle_controlstreamfile | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 895 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, and stop.
00896 { 00897 int res = 0, skipms = 3000; 00898 char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */ 00899 00900 if (argc < 5 || argc > 9) { 00901 return RESULT_SHOWUSAGE; 00902 } 00903 00904 if (!ast_strlen_zero(argv[4])) { 00905 stop = argv[4]; 00906 } 00907 00908 if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) { 00909 return RESULT_SHOWUSAGE; 00910 } 00911 00912 if (argc > 6 && !ast_strlen_zero(argv[6])) { 00913 fwd = argv[6]; 00914 } 00915 00916 if (argc > 7 && !ast_strlen_zero(argv[7])) { 00917 rev = argv[7]; 00918 } 00919 00920 if (argc > 8 && !ast_strlen_zero(argv[8])) { 00921 suspend = argv[8]; 00922 } 00923 00924 res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL); 00925 00926 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00927 00928 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00929 }
| static int handle_dbdel | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1667 of file res_agi.c.
References ast_agi_send(), ast_db_del(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01668 { 01669 int res; 01670 01671 if (argc != 4) 01672 return RESULT_SHOWUSAGE; 01673 res = ast_db_del(argv[2], argv[3]); 01674 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01675 return RESULT_SUCCESS; 01676 }
| static int handle_dbdeltree | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1678 of file res_agi.c.
References ast_agi_send(), ast_db_deltree(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01679 { 01680 int res; 01681 01682 if ((argc < 3) || (argc > 4)) 01683 return RESULT_SHOWUSAGE; 01684 if (argc == 4) 01685 res = ast_db_deltree(argv[2], argv[3]); 01686 else 01687 res = ast_db_deltree(argv[2], NULL); 01688 01689 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01690 return RESULT_SUCCESS; 01691 }
| static int handle_dbget | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1623 of file res_agi.c.
References ast_agi_send(), ast_db_get(), ast_free, ast_str_create(), ast_str_make_space(), buf, agi_state::fd, ast_str::len, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_str::str, and ast_str::used.
01624 { 01625 int res; 01626 struct ast_str *buf; 01627 01628 if (argc != 4) 01629 return RESULT_SHOWUSAGE; 01630 01631 if (!(buf = ast_str_create(16))) { 01632 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01633 return RESULT_SUCCESS; 01634 } 01635 01636 do { 01637 res = ast_db_get(argv[2], argv[3], buf->str, buf->len); 01638 buf->used = strlen(buf->str); 01639 if (buf->used < buf->len - 1) { 01640 break; 01641 } 01642 if (ast_str_make_space(&buf, buf->len * 2)) { 01643 break; 01644 } 01645 } while (1); 01646 01647 if (res) 01648 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01649 else 01650 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf->str); 01651 01652 ast_free(buf); 01653 return RESULT_SUCCESS; 01654 }
| static int handle_dbput | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1656 of file res_agi.c.
References ast_agi_send(), ast_db_put(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01657 { 01658 int res; 01659 01660 if (argc != 5) 01661 return RESULT_SHOWUSAGE; 01662 res = ast_db_put(argv[2], argv[3], argv[4]); 01663 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01664 return RESULT_SUCCESS; 01665 }
| static int handle_exec | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1460 of file res_agi.c.
References ast_agi_send(), ast_clear_flag, ast_compat_res_agi, AST_FLAG_DISABLE_WORKAROUNDS, ast_log(), ast_masq_park_call(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_verb, agi_state::fd, LOG_WARNING, PARK_APP_NAME, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.
01461 { 01462 int res, workaround; 01463 struct ast_app *app_to_exec; 01464 01465 if (argc < 2) 01466 return RESULT_SHOWUSAGE; 01467 01468 ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : ""); 01469 01470 if ((app_to_exec = pbx_findapp(argv[1]))) { 01471 if(!strcasecmp(argv[1], PARK_APP_NAME)) { 01472 ast_masq_park_call(chan, NULL, 0, NULL); 01473 } 01474 if (!(workaround = ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS))) { 01475 ast_set_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS); 01476 } 01477 if (ast_compat_res_agi && argc >= 3 && !ast_strlen_zero(argv[2])) { 01478 char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr, *vptr; 01479 for (cptr = compat, vptr = argv[2]; *vptr; vptr++) { 01480 if (*vptr == ',') { 01481 *cptr++ = '\\'; 01482 *cptr++ = ','; 01483 } else if (*vptr == '|') { 01484 *cptr++ = ','; 01485 } else { 01486 *cptr++ = *vptr; 01487 } 01488 } 01489 *cptr = '\0'; 01490 res = pbx_exec(chan, app_to_exec, compat); 01491 } else { 01492 res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]); 01493 } 01494 if (!workaround) { 01495 ast_clear_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS); 01496 } 01497 } else { 01498 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]); 01499 res = -2; 01500 } 01501 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01502 01503 /* Even though this is wrong, users are depending upon this result. */ 01504 return res; 01505 }
| static int handle_getdata | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1173 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.
01174 { 01175 int res, max, timeout; 01176 char data[1024]; 01177 01178 if (argc < 3) 01179 return RESULT_SHOWUSAGE; 01180 if (argc >= 4) 01181 timeout = atoi(argv[3]); 01182 else 01183 timeout = 0; 01184 if (argc >= 5) 01185 max = atoi(argv[4]); 01186 else 01187 max = 1024; 01188 res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl); 01189 if (res == 2) /* New command */ 01190 return RESULT_SUCCESS; 01191 else if (res == 1) 01192 ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data); 01193 else if (res < 0 ) 01194 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01195 else 01196 ast_agi_send(agi->fd, chan, "200 result=%s\n", data); 01197 return RESULT_SUCCESS; 01198 }
| static int handle_getoption | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
get option - really similar to the handle_streamfile, but with a timeout
Definition at line 981 of file res_agi.c.
References ast_agi_send(), ast_applystream(), 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.
00982 { 00983 int res, vres; 00984 struct ast_filestream *fs, *vfs; 00985 long sample_offset = 0, max_length; 00986 int timeout = 0; 00987 char *edigits = ""; 00988 00989 if ( argc < 4 || argc > 5 ) 00990 return RESULT_SHOWUSAGE; 00991 00992 if ( argv[3] ) 00993 edigits = argv[3]; 00994 00995 if ( argc == 5 ) 00996 timeout = atoi(argv[4]); 00997 else if (chan->pbx->dtimeoutms) { 00998 /* by default dtimeout is set to 5sec */ 00999 timeout = chan->pbx->dtimeoutms; /* in msec */ 01000 } 01001 01002 if (!(fs = ast_openstream(chan, argv[2], chan->language))) { 01003 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset); 01004 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]); 01005 return RESULT_SUCCESS; 01006 } 01007 01008 if ((vfs = ast_openvstream(chan, argv[2], chan->language))) 01009 ast_debug(1, "Ooh, found a video stream, too\n"); 01010 01011 ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout); 01012 01013 ast_seekstream(fs, 0, SEEK_END); 01014 max_length = ast_tellstream(fs); 01015 ast_seekstream(fs, sample_offset, SEEK_SET); 01016 res = ast_applystream(chan, fs); 01017 if (vfs) 01018 vres = ast_applystream(chan, vfs); 01019 ast_playstream(fs); 01020 if (vfs) 01021 ast_playstream(vfs); 01022 01023 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 01024 /* this is to check for if ast_waitstream closed the stream, we probably are at 01025 * the end of the stream, return that amount, else check for the amount */ 01026 sample_offset = (chan->stream)?ast_tellstream(fs):max_length; 01027 ast_stopstream(chan); 01028 if (res == 1) { 01029 /* Stop this command, don't print a result line, as there is a new command */ 01030 return RESULT_SUCCESS; 01031 } 01032 01033 /* If the user didnt press a key, wait for digitTimeout*/ 01034 if (res == 0 ) { 01035 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl); 01036 /* Make sure the new result is in the escape digits of the GET OPTION */ 01037 if ( !strchr(edigits,res) ) 01038 res=0; 01039 } 01040 01041 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset); 01042 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01043 }
| static int handle_getvariable | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1560 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.
01561 { 01562 char *ret; 01563 char tempstr[1024]; 01564 01565 if (argc != 3) 01566 return RESULT_SHOWUSAGE; 01567 01568 /* check if we want to execute an ast_custom_function */ 01569 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) { 01570 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr; 01571 } else { 01572 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL); 01573 } 01574 01575 if (ret) 01576 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret); 01577 else 01578 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01579 01580 return RESULT_SUCCESS; 01581 }
| static int handle_getvariablefull | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1583 of file res_agi.c.
References ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, pbx_substitute_variables_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01584 { 01585 char tmp[4096]; 01586 struct ast_channel *chan2=NULL; 01587 01588 if ((argc != 4) && (argc != 5)) 01589 return RESULT_SHOWUSAGE; 01590 if (argc == 5) { 01591 chan2 = ast_get_channel_by_name_locked(argv[4]); 01592 } else { 01593 chan2 = chan; 01594 } 01595 if (chan2) { 01596 pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1); 01597 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp); 01598 } else { 01599 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01600 } 01601 if (chan2 && (chan2 != chan)) 01602 ast_channel_unlock(chan2); 01603 return RESULT_SUCCESS; 01604 }
| static int handle_hangup | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1433 of file res_agi.c.
References ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01434 { 01435 struct ast_channel *c; 01436 01437 if (argc == 1) { 01438 /* no argument: hangup the current channel */ 01439 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT); 01440 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01441 return RESULT_SUCCESS; 01442 } else if (argc == 2) { 01443 /* one argument: look for info on the specified channel */ 01444 c = ast_get_channel_by_name_locked(argv[1]); 01445 if (c) { 01446 /* we have a matching channel */ 01447 ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT); 01448 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01449 ast_channel_unlock(c); 01450 return RESULT_SUCCESS; 01451 } 01452 /* if we get this far no channel name matched the argument given */ 01453 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01454 return RESULT_SUCCESS; 01455 } else { 01456 return RESULT_SHOWUSAGE; 01457 } 01458 }
| static int handle_noop | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | arg, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1722 of file res_agi.c.
References ast_agi_send(), agi_state::fd, and RESULT_SUCCESS.
01723 { 01724 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01725 return RESULT_SUCCESS; 01726 }
| static int handle_recordfile | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1236 of file res_agi.c.
References ast_agi_send(), ast_applystream(), 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_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_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, LOG_WARNING, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, ast_frame::subclass, THRESHOLD_SILENCE, and ast_dsp::totalsilence.
01237 { 01238 struct ast_filestream *fs; 01239 struct ast_frame *f; 01240 struct timeval start; 01241 long sample_offset = 0; 01242 int res = 0; 01243 int ms; 01244 01245 struct ast_dsp *sildet=NULL; /* silence detector dsp */ 01246 int totalsilence = 0; 01247 int dspsilence = 0; 01248 int silence = 0; /* amount of silence to allow */ 01249 int gotsilence = 0; /* did we timeout for silence? */ 01250 char *silencestr = NULL; 01251 int rfmt = 0; 01252 01253 /* XXX EAGI FIXME XXX */ 01254 01255 if (argc < 6) 01256 return RESULT_SHOWUSAGE; 01257 if (sscanf(argv[5], "%30d", &ms) != 1) 01258 return RESULT_SHOWUSAGE; 01259 01260 if (argc > 6) 01261 silencestr = strchr(argv[6],'s'); 01262 if ((argc > 7) && (!silencestr)) 01263 silencestr = strchr(argv[7],'s'); 01264 if ((argc > 8) && (!silencestr)) 01265 silencestr = strchr(argv[8],'s'); 01266 01267 if (silencestr) { 01268 if (strlen(silencestr) > 2) { 01269 if ((silencestr[0] == 's') && (silencestr[1] == '=')) { 01270 silencestr++; 01271 silencestr++; 01272 if (silencestr) 01273 silence = atoi(silencestr); 01274 if (silence > 0) 01275 silence *= 1000; 01276 } 01277 } 01278 } 01279 01280 if (silence > 0) { 01281 rfmt = chan->readformat; 01282 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 01283 if (res < 0) { 01284 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 01285 return -1; 01286 } 01287 sildet = ast_dsp_new(); 01288 if (!sildet) { 01289 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 01290 return -1; 01291 } 01292 ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE)); 01293 } 01294 01295 /* backward compatibility, if no offset given, arg[6] would have been 01296 * caught below and taken to be a beep, else if it is a digit then it is a 01297 * offset */ 01298 if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '='))) 01299 res = ast_streamfile(chan, "beep", chan->language); 01300 01301 if ((argc > 7) && (!strchr(argv[7], '='))) 01302 res = ast_streamfile(chan, "beep", chan->language); 01303 01304 if (!res) 01305 res = ast_waitstream(chan, argv[4]); 01306 if (res) { 01307 ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset); 01308 } else { 01309 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE); 01310 if (!fs) { 01311 res = -1; 01312 ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res); 01313 if (sildet) 01314 ast_dsp_free(sildet); 01315 return RESULT_FAILURE; 01316 } 01317 01318 /* Request a video update */ 01319 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 01320 01321 chan->stream = fs; 01322 ast_applystream(chan,fs); 01323 /* really should have checks */ 01324 ast_seekstream(fs, sample_offset, SEEK_SET); 01325 ast_truncstream(fs); 01326 01327 start = ast_tvnow(); 01328 while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) { 01329 res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start)); 01330 if (res < 0) { 01331 ast_closestream(fs); 01332 ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset); 01333 if (sildet) 01334 ast_dsp_free(sildet); 01335 return RESULT_FAILURE; 01336 } 01337 f = ast_read(chan); 01338 if (!f) { 01339 ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset); 01340 ast_closestream(fs); 01341 if (sildet) 01342 ast_dsp_free(sildet); 01343 return RESULT_FAILURE; 01344 } 01345 switch(f->frametype) { 01346 case AST_FRAME_DTMF: 01347 if (strchr(argv[4], f->subclass)) { 01348 /* This is an interrupting chracter, so rewind to chop off any small 01349 amount of DTMF that may have been recorded 01350 */ 01351 ast_stream_rewind(fs, 200); 01352 ast_truncstream(fs); 01353 sample_offset = ast_tellstream(fs); 01354 ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset); 01355 ast_closestream(fs); 01356 ast_frfree(f); 01357 if (sildet) 01358 ast_dsp_free(sildet); 01359 return RESULT_SUCCESS; 01360 } 01361 break; 01362 case AST_FRAME_VOICE: 01363 ast_writestream(fs, f); 01364 /* this is a safe place to check progress since we know that fs 01365 * is valid after a write, and it will then have our current 01366 * location */ 01367 sample_offset = ast_tellstream(fs); 01368 if (silence > 0) { 01369 dspsilence = 0; 01370 ast_dsp_silence(sildet, f, &dspsilence); 01371 if (dspsilence) { 01372 totalsilence = dspsilence; 01373 } else { 01374 totalsilence = 0; 01375 } 01376 if (totalsilence > silence) { 01377 /* Ended happily with silence */ 01378 gotsilence = 1; 01379 break; 01380 } 01381 } 01382 break; 01383 case AST_FRAME_VIDEO: 01384 ast_writestream(fs, f); 01385 default: 01386 /* Ignore all other frames */ 01387 break; 01388 } 01389 ast_frfree(f); 01390 if (gotsilence) 01391 break; 01392 } 01393 01394 if (gotsilence) { 01395 ast_stream_rewind(fs, silence-1000); 01396 ast_truncstream(fs); 01397 sample_offset = ast_tellstream(fs); 01398 } 01399 ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset); 01400 ast_closestream(fs); 01401 } 01402 01403 if (silence > 0) { 01404 res = ast_set_read_format(chan, rfmt); 01405 if (res) 01406 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 01407 ast_dsp_free(sildet); 01408 } 01409 01410 return RESULT_SUCCESS; 01411 }
| static int handle_recvchar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 815 of file res_agi.c.
References ast_agi_send(), ast_recvchar(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00816 { 00817 int res; 00818 00819 if (argc != 3) 00820 return RESULT_SHOWUSAGE; 00821 00822 res = ast_recvchar(chan,atoi(argv[2])); 00823 if (res == 0) { 00824 ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res); 00825 return RESULT_SUCCESS; 00826 } 00827 if (res > 0) { 00828 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00829 return RESULT_SUCCESS; 00830 } 00831 ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res); 00832 return RESULT_FAILURE; 00833 }
| static int handle_recvtext | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 835 of file res_agi.c.
References ast_agi_send(), ast_free, ast_recvtext(), buf, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00836 { 00837 char *buf; 00838 00839 if (argc != 3) 00840 return RESULT_SHOWUSAGE; 00841 00842 buf = ast_recvtext(chan, atoi(argv[2])); 00843 if (buf) { 00844 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf); 00845 ast_free(buf); 00846 } else { 00847 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 00848 } 00849 return RESULT_SUCCESS; 00850 }
| static int handle_sayalpha | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1081 of file res_agi.c.
References ast_agi_send(), ast_say_character_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01082 { 01083 int res; 01084 01085 if (argc != 4) 01086 return RESULT_SHOWUSAGE; 01087 01088 res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01089 if (res == 1) /* New command */ 01090 return RESULT_SUCCESS; 01091 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01092 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01093 }
| static int handle_saydate | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1095 of file res_agi.c.
References ast_agi_send(), ast_say_date, agi_state::fd, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01096 { 01097 int res, num; 01098 01099 if (argc != 4) 01100 return RESULT_SHOWUSAGE; 01101 if (sscanf(argv[2], "%30d", &num) != 1) 01102 return RESULT_SHOWUSAGE; 01103 res = ast_say_date(chan, num, argv[3], chan->language); 01104 if (res == 1) 01105 return RESULT_SUCCESS; 01106 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01107 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01108 }
| static int handle_saydatetime | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1125 of file res_agi.c.
References ast_agi_send(), ast_get_time_t(), ast_say_date_with_format, ast_strlen_zero(), agi_state::fd, format, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01126 { 01127 int res = 0; 01128 time_t unixtime; 01129 char *format, *zone = NULL; 01130 01131 if (argc < 4) 01132 return RESULT_SHOWUSAGE; 01133 01134 if (argc > 4) { 01135 format = argv[4]; 01136 } else { 01137 /* XXX this doesn't belong here, but in the 'say' module */ 01138 if (!strcasecmp(chan->language, "de")) { 01139 format = "A dBY HMS"; 01140 } else { 01141 format = "ABdY 'digits/at' IMp"; 01142 } 01143 } 01144 01145 if (argc > 5 && !ast_strlen_zero(argv[5])) 01146 zone = argv[5]; 01147 01148 if (ast_get_time_t(argv[2], &unixtime, 0, NULL)) 01149 return RESULT_SHOWUSAGE; 01150 01151 res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone); 01152 if (res == 1) 01153 return RESULT_SUCCESS; 01154 01155 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01156 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01157 }
| static int handle_saydigits | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1065 of file res_agi.c.
References ast_agi_send(), ast_say_digit_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01066 { 01067 int res, num; 01068 01069 if (argc != 4) 01070 return RESULT_SHOWUSAGE; 01071 if (sscanf(argv[2], "%30d", &num) != 1) 01072 return RESULT_SHOWUSAGE; 01073 01074 res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01075 if (res == 1) /* New command */ 01076 return RESULT_SUCCESS; 01077 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01078 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01079 }
| static int handle_saynumber | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Say number in various language syntaxes.
Definition at line 1050 of file res_agi.c.
References ast_agi_send(), ast_say_number_full, agi_state::audio, agi_state::ctrl, agi_state::fd, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01051 { 01052 int res, num; 01053 01054 if (argc < 4 || argc > 5) 01055 return RESULT_SHOWUSAGE; 01056 if (sscanf(argv[2], "%30d", &num) != 1) 01057 return RESULT_SHOWUSAGE; 01058 res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl); 01059 if (res == 1) 01060 return RESULT_SUCCESS; 01061 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01062 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01063 }
| static int handle_sayphonetic | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1159 of file res_agi.c.
References ast_agi_send(), ast_say_phonetic_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01160 { 01161 int res; 01162 01163 if (argc != 4) 01164 return RESULT_SHOWUSAGE; 01165 01166 res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01167 if (res == 1) /* New command */ 01168 return RESULT_SUCCESS; 01169 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01170 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01171 }
| static int handle_saytime | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1110 of file res_agi.c.
References ast_agi_send(), ast_say_time, agi_state::fd, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01111 { 01112 int res, num; 01113 01114 if (argc != 4) 01115 return RESULT_SHOWUSAGE; 01116 if (sscanf(argv[2], "%30d", &num) != 1) 01117 return RESULT_SHOWUSAGE; 01118 res = ast_say_time(chan, num, argv[3], chan->language); 01119 if (res == 1) 01120 return RESULT_SUCCESS; 01121 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01122 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01123 }
| static int handle_sendimage | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 879 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.
00880 { 00881 int res; 00882 00883 if (argc != 3) { 00884 return RESULT_SHOWUSAGE; 00885 } 00886 00887 res = ast_send_image(chan, argv[2]); 00888 if (!ast_check_hangup(chan)) { 00889 res = 0; 00890 } 00891 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00892 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00893 }
| static int handle_sendtext | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 796 of file res_agi.c.
References ast_agi_send(), ast_sendtext(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00797 { 00798 int res; 00799 00800 if (argc != 3) 00801 return RESULT_SHOWUSAGE; 00802 00803 /* At the moment, the parser (perhaps broken) returns with 00804 the last argument PLUS the newline at the end of the input 00805 buffer. This probably needs to be fixed, but I wont do that 00806 because other stuff may break as a result. The right way 00807 would probably be to strip off the trailing newline before 00808 parsing, then here, add a newline at the end of the string 00809 before sending it to ast_sendtext --DUDE */ 00810 res = ast_sendtext(chan, argv[2]); 00811 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00812 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00813 }
| static int handle_setcallerid | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1507 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.
01508 { 01509 char tmp[256]=""; 01510 char *l = NULL, *n = NULL; 01511 01512 if (argv[2]) { 01513 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01514 ast_callerid_parse(tmp, &n, &l); 01515 if (l) 01516 ast_shrink_phone_number(l); 01517 else 01518 l = ""; 01519 if (!n) 01520 n = ""; 01521 ast_set_callerid(chan, l, n, NULL); 01522 } 01523 01524 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01525 return RESULT_SUCCESS; 01526 }
| static int handle_setcontext | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1200 of file res_agi.c.
References ast_agi_send(), ast_copy_string(), ast_channel::context, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01201 { 01202 01203 if (argc != 3) 01204 return RESULT_SHOWUSAGE; 01205 ast_copy_string(chan->context, argv[2], sizeof(chan->context)); 01206 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01207 return RESULT_SUCCESS; 01208 }
| static int handle_setextension | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1210 of file res_agi.c.
References ast_agi_send(), ast_copy_string(), ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01211 { 01212 if (argc != 3) 01213 return RESULT_SHOWUSAGE; 01214 ast_copy_string(chan->exten, argv[2], sizeof(chan->exten)); 01215 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01216 return RESULT_SUCCESS; 01217 }
| static int handle_setmusic | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1728 of file res_agi.c.
References ast_agi_send(), ast_moh_start(), ast_moh_stop(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01729 { 01730 if (argc < 3) { 01731 return RESULT_SHOWUSAGE; 01732 } 01733 if (!strncasecmp(argv[2], "on", 2)) 01734 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL); 01735 else if (!strncasecmp(argv[2], "off", 3)) 01736 ast_moh_stop(chan); 01737 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01738 return RESULT_SUCCESS; 01739 }
| static int handle_setpriority | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1219 of file res_agi.c.
References ast_agi_send(), ast_explicit_goto(), ast_findlabel_extension(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01220 { 01221 int pri; 01222 01223 if (argc != 3) 01224 return RESULT_SHOWUSAGE; 01225 01226 if (sscanf(argv[2], "%30d", &pri) != 1) { 01227 if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1) 01228 return RESULT_SHOWUSAGE; 01229 } 01230 01231 ast_explicit_goto(chan, NULL, NULL, pri); 01232 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01233 return RESULT_SUCCESS; 01234 }
| static int handle_setvariable | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1551 of file res_agi.c.
References ast_agi_send(), agi_state::fd, pbx_builtin_setvar_helper(), and RESULT_SUCCESS.
01552 { 01553 if (argv[3]) 01554 pbx_builtin_setvar_helper(chan, argv[2], argv[3]); 01555 01556 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01557 return RESULT_SUCCESS; 01558 }
| static int handle_speechactivategrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1824 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_activate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01825 { 01826 if (argc != 4) 01827 return RESULT_SHOWUSAGE; 01828 01829 if (!agi->speech) { 01830 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01831 return RESULT_SUCCESS; 01832 } 01833 01834 if (ast_speech_grammar_activate(agi->speech, argv[3])) 01835 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01836 else 01837 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01838 01839 return RESULT_SUCCESS; 01840 }
| static int handle_speechcreate | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1741 of file res_agi.c.
References ast_agi_send(), AST_FORMAT_SLINEAR, ast_speech_new(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
01742 { 01743 /* If a structure already exists, return an error */ 01744 if (agi->speech) { 01745 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01746 return RESULT_SUCCESS; 01747 } 01748 01749 if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR))) 01750 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01751 else 01752 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01753 01754 return RESULT_SUCCESS; 01755 }
| static int handle_speechdeactivategrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1842 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_deactivate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01843 { 01844 if (argc != 4) 01845 return RESULT_SHOWUSAGE; 01846 01847 if (!agi->speech) { 01848 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01849 return RESULT_SUCCESS; 01850 } 01851 01852 if (ast_speech_grammar_deactivate(agi->speech, argv[3])) 01853 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01854 else 01855 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01856 01857 return RESULT_SUCCESS; 01858 }
| static int handle_speechdestroy | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1775 of file res_agi.c.
References ast_agi_send(), ast_speech_destroy(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
01776 { 01777 if (agi->speech) { 01778 ast_speech_destroy(agi->speech); 01779 agi->speech = NULL; 01780 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01781 } else { 01782 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01783 } 01784 01785 return RESULT_SUCCESS; 01786 }
| static int handle_speechloadgrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1788 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_load(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01789 { 01790 if (argc != 5) 01791 return RESULT_SHOWUSAGE; 01792 01793 if (!agi->speech) { 01794 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01795 return RESULT_SUCCESS; 01796 } 01797 01798 if (ast_speech_grammar_load(agi->speech, argv[3], argv[4])) 01799 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01800 else 01801 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01802 01803 return RESULT_SUCCESS; 01804 }
| static int handle_speechrecognize | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1879 of file res_agi.c.
References ast_agi_send(), ast_build_string(), ast_clear_flag, AST_CONTROL_HANGUP, 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(), ast_speech_change_state(), AST_SPEECH_QUIET, ast_speech_results_get(), ast_speech_start(), AST_SPEECH_STATE_DONE, AST_SPEECH_STATE_NOT_READY, AST_SPEECH_STATE_READY, AST_SPEECH_STATE_WAIT, ast_speech_write(), ast_stopstream(), ast_strlen_zero(), ast_tellstream(), ast_test_flag, ast_waitfor(), buf, ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, ast_speech_result::grammar, ast_speech_result::list, 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.
01880 { 01881 struct ast_speech *speech = agi->speech; 01882 char *prompt, dtmf = 0, tmp[4096] = "", *buf = tmp; 01883 int timeout = 0, offset = 0, old_read_format = 0, res = 0, i = 0; 01884 long current_offset = 0; 01885 const char *reason = NULL; 01886 struct ast_frame *fr = NULL; 01887 struct ast_speech_result *result = NULL; 01888 size_t left = sizeof(tmp); 01889 time_t start = 0, current; 01890 01891 if (argc < 4) 01892 return RESULT_SHOWUSAGE; 01893 01894 if (!speech) { 01895 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01896 return RESULT_SUCCESS; 01897 } 01898 01899 prompt = argv[2]; 01900 timeout = atoi(argv[3]); 01901 01902 /* If offset is specified then convert from text to integer */ 01903 if (argc == 5) 01904 offset = atoi(argv[4]); 01905 01906 /* We want frames coming in signed linear */ 01907 old_read_format = chan->readformat; 01908 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 01909 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01910 return RESULT_SUCCESS; 01911 } 01912 01913 /* Setup speech structure */ 01914 if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) { 01915 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 01916 ast_speech_start(speech); 01917 } 01918 01919 /* Start playing prompt */ 01920 speech_streamfile(chan, prompt, chan->language, offset); 01921 01922 /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */ 01923 while (ast_strlen_zero(reason)) { 01924 /* Run scheduled items */ 01925 ast_sched_runq(chan->sched); 01926 01927 /* See maximum time of waiting */ 01928 if ((res = ast_sched_wait(chan->sched)) < 0) 01929 res = 1000; 01930 01931 /* Wait for frame */ 01932 if (ast_waitfor(chan, res) > 0) { 01933 if (!(fr = ast_read(chan))) { 01934 reason = "hangup"; 01935 break; 01936 } 01937 } 01938 01939 /* Perform timeout check */ 01940 if ((timeout > 0) && (start > 0)) { 01941 time(¤t); 01942 if ((current - start) >= timeout) { 01943 reason = "timeout"; 01944 if (fr) 01945 ast_frfree(fr); 01946 break; 01947 } 01948 } 01949 01950 /* Check the speech structure for any changes */ 01951 ast_mutex_lock(&speech->lock); 01952 01953 /* See if we need to quiet the audio stream playback */ 01954 if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) { 01955 current_offset = ast_tellstream(chan->stream); 01956 ast_stopstream(chan); 01957 ast_clear_flag(speech, AST_SPEECH_QUIET); 01958 } 01959 01960 /* Check each state */ 01961 switch (speech->state) { 01962 case AST_SPEECH_STATE_READY: 01963 /* If the stream is done, start timeout calculation */ 01964 if ((timeout > 0) && start == 0 && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) { 01965 ast_stopstream(chan); 01966 time(&start); 01967 } 01968 /* Write audio frame data into speech engine if possible */ 01969 if (fr && fr->frametype == AST_FRAME_VOICE) 01970 ast_speech_write(speech, fr->data.ptr, fr->datalen); 01971 break; 01972 case AST_SPEECH_STATE_WAIT: 01973 /* Cue waiting sound if not already playing */ 01974 if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) { 01975 ast_stopstream(chan); 01976 /* If a processing sound exists, or is not none - play it */ 01977 if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none")) 01978 speech_streamfile(chan, speech->processing_sound, chan->language, 0); 01979 } 01980 break; 01981 case AST_SPEECH_STATE_DONE: 01982 /* Get the results */ 01983 speech->results = ast_speech_results_get(speech); 01984 /* Change state to not ready */ 01985 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 01986 reason = "speech"; 01987 break; 01988 default: 01989 break; 01990 } 01991 ast_mutex_unlock(&speech->lock); 01992 01993 /* Check frame for DTMF or hangup */ 01994 if (fr) { 01995 if (fr->frametype == AST_FRAME_DTMF) { 01996 reason = "dtmf"; 01997 dtmf = fr->subclass; 01998 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_HANGUP) { 01999 reason = "hangup"; 02000 } 02001 ast_frfree(fr); 02002 } 02003 } 02004 02005 if (!strcasecmp(reason, "speech")) { 02006 /* Build string containing speech results */ 02007 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) { 02008 /* Build result string */ 02009 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); 02010 /* Increment result count */ 02011 i++; 02012 } 02013 /* Print out */ 02014 ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp); 02015 } else if (!strcasecmp(reason, "dtmf")) { 02016 ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset); 02017 } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) { 02018 ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset); 02019 } else { 02020 ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset); 02021 } 02022 02023 return RESULT_SUCCESS; 02024 }
| static int handle_speechset | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1757 of file res_agi.c.
References ast_agi_send(), ast_speech_change(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01758 { 01759 /* Check for minimum arguments */ 01760 if (argc != 3) 01761 return RESULT_SHOWUSAGE; 01762 01763 /* Check to make sure speech structure exists */ 01764 if (!agi->speech) { 01765 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01766 return RESULT_SUCCESS; 01767 } 01768 01769 ast_speech_change(agi->speech, argv[2], argv[3]); 01770 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01771 01772 return RESULT_SUCCESS; 01773 }
| static int handle_speechunloadgrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1806 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_unload(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01807 { 01808 if (argc != 4) 01809 return RESULT_SHOWUSAGE; 01810 01811 if (!agi->speech) { 01812 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01813 return RESULT_SUCCESS; 01814 } 01815 01816 if (ast_speech_grammar_unload(agi->speech, argv[3])) 01817 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01818 else 01819 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01820 01821 return RESULT_SUCCESS; 01822 }
| static int handle_streamfile | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 931 of file res_agi.c.
References ast_agi_send(), ast_applystream(), 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.
00932 { 00933 int res, vres; 00934 struct ast_filestream *fs, *vfs; 00935 long sample_offset = 0, max_length; 00936 char *edigits = ""; 00937 00938 if (argc < 4 || argc > 5) 00939 return RESULT_SHOWUSAGE; 00940 00941 if (argv[3]) 00942 edigits = argv[3]; 00943 00944 if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1)) 00945 return RESULT_SHOWUSAGE; 00946 00947 if (!(fs = ast_openstream(chan, argv[2], chan->language))) { 00948 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset); 00949 return RESULT_SUCCESS; 00950 } 00951 00952 if ((vfs = ast_openvstream(chan, argv[2], chan->language))) 00953 ast_debug(1, "Ooh, found a video stream, too\n"); 00954 00955 ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset); 00956 00957 ast_seekstream(fs, 0, SEEK_END); 00958 max_length = ast_tellstream(fs); 00959 ast_seekstream(fs, sample_offset, SEEK_SET); 00960 res = ast_applystream(chan, fs); 00961 if (vfs) 00962 vres = ast_applystream(chan, vfs); 00963 ast_playstream(fs); 00964 if (vfs) 00965 ast_playstream(vfs); 00966 00967 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 00968 /* this is to check for if ast_waitstream closed the stream, we probably are at 00969 * the end of the stream, return that amount, else check for the amount */ 00970 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; 00971 ast_stopstream(chan); 00972 if (res == 1) { 00973 /* Stop this command, don't print a result line, as there is a new command */ 00974 return RESULT_SUCCESS; 00975 } 00976 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset); 00977 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00978 }
| static int handle_tddmode | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 852 of file res_agi.c.
References ast_agi_send(), ast_channel_setoption(), AST_OPTION_TDD, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00853 { 00854 int res, x; 00855 00856 if (argc != 3) 00857 return RESULT_SHOWUSAGE; 00858 00859 if (!strncasecmp(argv[2],"on",2)) { 00860 x = 1; 00861 } else { 00862 x = 0; 00863 } 00864 if (!strncasecmp(argv[2],"mate",4)) { 00865 x = 2; 00866 } 00867 if (!strncasecmp(argv[2],"tdd",3)) { 00868 x = 1; 00869 } 00870 res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0); 00871 if (res != RESULT_SUCCESS) { 00872 ast_agi_send(agi->fd, chan, "200 result=0\n"); 00873 } else { 00874 ast_agi_send(agi->fd, chan, "200 result=1\n"); 00875 } 00876 return RESULT_SUCCESS; 00877 }
| static int handle_verbose | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1606 of file res_agi.c.
References ast_agi_send(), ast_verb, ast_channel::data, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01607 { 01608 int level = 0; 01609 01610 if (argc < 2) 01611 return RESULT_SHOWUSAGE; 01612 01613 if (argv[2]) 01614 sscanf(argv[2], "%30d", &level); 01615 01616 ast_verb(level, "%s: %s\n", chan->data, argv[1]); 01617 01618 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01619 01620 return RESULT_SUCCESS; 01621 }
| static int handle_waitfordigit | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 783 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.
00784 { 00785 int res, to; 00786 00787 if (argc != 4) 00788 return RESULT_SHOWUSAGE; 00789 if (sscanf(argv[3], "%30d", &to) != 1) 00790 return RESULT_SHOWUSAGE; 00791 res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl); 00792 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00793 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00794 }
| static char* help_workhorse | ( | int | fd, | |
| char * | match[] | |||
| ) | [static] |
Definition at line 2363 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, and agi_command::summary.
Referenced by handle_cli_agi_show().
02364 { 02365 char fullcmd[80], matchstr[80]; 02366 struct agi_command *e; 02367 02368 if (match) 02369 ast_join(matchstr, sizeof(matchstr), match); 02370 02371 ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description"); 02372 AST_RWLIST_RDLOCK(&agi_commands); 02373 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 02374 if (!e->cmda[0]) 02375 break; 02376 /* Hide commands that start with '_' */ 02377 if ((e->cmda[0])[0] == '_') 02378 continue; 02379 ast_join(fullcmd, sizeof(fullcmd), e->cmda); 02380 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr))) 02381 continue; 02382 ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, e->summary); 02383 } 02384 AST_RWLIST_UNLOCK(&agi_commands); 02385 02386 return CLI_SUCCESS; 02387 }
| static enum agi_result launch_asyncagi | ( | struct ast_channel * | chan, | |
| char * | argv[], | |||
| int * | efd | |||
| ) | [static] |
Definition at line 360 of file res_agi.c.
References add_to_agi(), AGI_BUF_SIZE, agi_handle_command(), AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS_ASYNC, AMI_BUF_SIZE, ast_check_hangup(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_frfree, ast_log(), ast_read(), ast_speech_destroy(), ast_strlen_zero(), ast_uri_encode(), ast_waitfor(), agi_state::audio, agi_cmd::cmd_buffer, agi_cmd::cmd_id, agi_state::ctrl, EVENT_FLAG_AGI, f, agi_state::fast, agi_state::fd, ast_frame::frametype, free_agi_cmd(), get_agi_cmd(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, manager_event, quit, setup_env(), agi_state::speech, and ast_frame::subclass.
Referenced by launch_script().
00361 { 00362 /* This buffer sizes might cause truncation if the AGI command writes more data 00363 than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command 00364 that writes a response larger than 1024 bytes?, I don't think so, most of 00365 them are just result=blah stuff. However probably if GET VARIABLE is called 00366 and the variable has large amount of data, that could be a problem. We could 00367 make this buffers dynamic, but let's leave that as a second step. 00368 00369 AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe 00370 number. Some characters of AGI buf will be url encoded to be sent to manager 00371 clients. An URL encoded character will take 3 bytes, but again, to cause 00372 truncation more than about 70% of the AGI buffer should be URL encoded for 00373 that to happen. Not likely at all. 00374 00375 On the other hand. I wonder if read() could eventually return less data than 00376 the amount already available in the pipe? If so, how to deal with that? 00377 So far, my tests on Linux have not had any problems. 00378 */ 00379 #define AGI_BUF_SIZE 1024 00380 #define AMI_BUF_SIZE 2048 00381 struct ast_frame *f; 00382 struct agi_cmd *cmd; 00383 int res, fds[2]; 00384 int timeout = 100; 00385 char agi_buffer[AGI_BUF_SIZE + 1]; 00386 char ami_buffer[AMI_BUF_SIZE]; 00387 enum agi_result returnstatus = AGI_RESULT_SUCCESS_ASYNC; 00388 AGI async_agi; 00389 00390 if (efd) { 00391 ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n"); 00392 return AGI_RESULT_FAILURE; 00393 } 00394 00395 /* add AsyncAGI datastore to the channel */ 00396 if (add_to_agi(chan)) { 00397 ast_log(LOG_ERROR, "failed to start Async AGI on channel %s\n", chan->name); 00398 return AGI_RESULT_FAILURE; 00399 } 00400 00401 /* this pipe allows us to create a "fake" AGI struct to use 00402 the AGI commands */ 00403 res = pipe(fds); 00404 if (res) { 00405 ast_log(LOG_ERROR, "failed to create Async AGI pipe\n"); 00406 /* intentionally do not remove datastore, added with 00407 add_to_agi(), from channel. It will be removed when 00408 the channel is hung up anyways */ 00409 return AGI_RESULT_FAILURE; 00410 } 00411 00412 /* handlers will get the pipe write fd and we read the AGI responses 00413 from the pipe read fd */ 00414 async_agi.fd = fds[1]; 00415 async_agi.ctrl = fds[1]; 00416 async_agi.audio = -1; /* no audio support */ 00417 async_agi.fast = 0; 00418 00419 /* notify possible manager users of a new channel ready to 00420 receive commands */ 00421 setup_env(chan, "async", fds[1], 0, 0, NULL); 00422 /* read the environment */ 00423 res = read(fds[0], agi_buffer, AGI_BUF_SIZE); 00424 if (!res) { 00425 ast_log(LOG_ERROR, "failed to read from Async AGI pipe on channel %s\n", chan->name); 00426 returnstatus = AGI_RESULT_FAILURE; 00427 goto quit; 00428 } 00429 agi_buffer[res] = '\0'; 00430 /* encode it and send it thru the manager so whoever is going to take 00431 care of AGI commands on this channel can decide which AGI commands 00432 to execute based on the setup info */ 00433 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1); 00434 manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Start\r\nChannel: %s\r\nEnv: %s\r\n", chan->name, ami_buffer); 00435 while (1) { 00436 /* bail out if we need to hangup */ 00437 if (ast_check_hangup(chan)) { 00438 ast_log(LOG_DEBUG, "ast_check_hangup returned true on chan %s\n", chan->name); 00439 break; 00440 } 00441 /* retrieve a command 00442 (commands are added via the manager or the cli threads) */ 00443 cmd = get_agi_cmd(chan); 00444 if (cmd) { 00445 /* OK, we have a command, let's call the 00446 command handler. */ 00447 res = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0); 00448 if (res < 0) { 00449 free_agi_cmd(cmd); 00450 break; 00451 } 00452 /* the command handler must have written to our fake 00453 AGI struct fd (the pipe), let's read the response */ 00454 res = read(fds[0], agi_buffer, AGI_BUF_SIZE); 00455 if (!res) { 00456 returnstatus = AGI_RESULT_FAILURE; 00457 ast_log(LOG_ERROR, "failed to read from AsyncAGI pipe on channel %s\n", chan->name); 00458 free_agi_cmd(cmd); 00459 break; 00460 } 00461 /* we have a response, let's send the response thru the 00462 manager. Include the CommandID if it was specified 00463 when the command was added */ 00464 agi_buffer[res] = '\0'; 00465 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1); 00466 if (ast_strlen_zero(cmd->cmd_id)) 00467 manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Exec\r\nChannel: %s\r\nResult: %s\r\n", chan->name, ami_buffer); 00468 else 00469 manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Exec\r\nChannel: %s\r\nCommandID: %s\r\nResult: %s\r\n", chan->name, cmd->cmd_id, ami_buffer); 00470 free_agi_cmd(cmd); 00471 } else { 00472 /* no command so far, wait a bit for a frame to read */ 00473 res = ast_waitfor(chan, timeout); 00474 if (res < 0) { 00475 ast_log(LOG_DEBUG, "ast_waitfor returned <= 0 on chan %s\n", chan->name); 00476 break; 00477 } 00478 if (res == 0) 00479 continue; 00480 f = ast_read(chan); 00481 if (!f) { 00482 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 00483 returnstatus = AGI_RESULT_HANGUP; 00484 break; 00485 } 00486 /* is there any other frame we should care about 00487 besides AST_CONTROL_HANGUP? */ 00488 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 00489 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 00490 ast_frfree(f); 00491 break; 00492 } 00493 ast_frfree(f); 00494 } 00495 } 00496 00497 if (async_agi.speech) { 00498 ast_speech_destroy(async_agi.speech); 00499 } 00500 quit: 00501 /* notify manager users this channel cannot be 00502 controlled anymore by Async AGI */ 00503 manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: End\r\nChannel: %s\r\n", chan->name); 00504 00505 /* close the pipe */ 00506 close(fds[0]); 00507 close(fds[1]); 00508 00509 /* intentionally don't get rid of the datastore. So commands can be 00510 still in the queue in case AsyncAGI gets called again. 00511 Datastore destructor will be called on channel destroy anyway */ 00512 00513 return returnstatus; 00514 00515 #undef AGI_BUF_SIZE 00516 #undef AMI_BUF_SIZE 00517 }
| static enum agi_result launch_netscript | ( | char * | agiurl, | |
| char * | argv[], | |||
| int * | fds, | |||
| int * | efd, | |||
| int * | opid | |||
| ) | [static] |
Definition at line 521 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, MAX_AGI_CONNECT, and s.
Referenced by launch_script().
00522 { 00523 int s, flags, res, port = AGI_PORT; 00524 struct pollfd pfds[1]; 00525 char *host, *c, *script = ""; 00526 struct sockaddr_in addr_in; 00527 struct hostent *hp; 00528 struct ast_hostent ahp; 00529 00530 /* agiusl is "agi://host.domain[:port][/script/name]" */ 00531 host = ast_strdupa(agiurl + 6); /* Remove agi:// */ 00532 /* Strip off any script name */ 00533 if ((c = strchr(host, '/'))) { 00534 *c = '\0'; 00535 c++; 00536 script = c; 00537 } 00538 if ((c = strchr(host, ':'))) { 00539 *c = '\0'; 00540 c++; 00541 port = atoi(c); 00542 } 00543 if (efd) { 00544 ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n"); 00545 return -1; 00546 } 00547 if (!(hp = ast_gethostbyname(host, &ahp))) { 00548 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host); 00549 return -1; 00550 } 00551 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00552 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 00553 return -1; 00554 } 00555 if ((flags = fcntl(s, F_GETFL)) < 0) { 00556 ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno)); 00557 close(s); 00558 return -1; 00559 } 00560 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { 00561 ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno)); 00562 close(s); 00563 return -1; 00564 } 00565 memset(&addr_in, 0, sizeof(addr_in)); 00566 addr_in.sin_family = AF_INET; 00567 addr_in.sin_port = htons(port); 00568 memcpy(&addr_in.sin_addr, hp->h_addr, sizeof(addr_in.sin_addr)); 00569 if (connect(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) && (errno != EINPROGRESS)) { 00570 ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno)); 00571 close(s); 00572 return AGI_RESULT_FAILURE; 00573 } 00574 00575 pfds[0].fd = s; 00576 pfds[0].events = POLLOUT; 00577 while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) { 00578 if (errno != EINTR) { 00579 if (!res) { 00580 ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n", 00581 agiurl, MAX_AGI_CONNECT); 00582 } else 00583 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 00584 close(s); 00585 return AGI_RESULT_FAILURE; 00586 } 00587 } 00588 00589 if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) { 00590 if (errno != EINTR) { 00591 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 00592 close(s); 00593 return AGI_RESULT_FAILURE; 00594 } 00595 } 00596 00597 /* If we have a script parameter, relay it to the fastagi server */ 00598 /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */ 00599 if (!ast_strlen_zero(script)) 00600 ast_agi_send(s, NULL, "agi_network_script: %s\n", script); 00601 00602 ast_debug(4, "Wow, connected!\n"); 00603 fds[0] = s; 00604 fds[1] = s; 00605 *opid = -1; 00606 return AGI_RESULT_SUCCESS_FAST; 00607 }
| static enum agi_result launch_script | ( | struct ast_channel * | chan, | |
| char * | script, | |||
| char * | argv[], | |||
| int * | fds, | |||
| int * | efd, | |||
| int * | opid | |||
| ) | [static] |
Definition at line 609 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_netscript(), LOG_WARNING, and setenv().
Referenced by agi_exec_full().
00610 { 00611 char tmp[256]; 00612 int pid, toast[2], fromast[2], audio[2], res; 00613 struct stat st; 00614 00615 if (!strncasecmp(script, "agi://", 6)) 00616 return launch_netscript(script, argv, fds, efd, opid); 00617 if (!strncasecmp(script, "agi:async", sizeof("agi:async")-1)) 00618 return launch_asyncagi(chan, argv, efd); 00619 00620 if (script[0] != '/') { 00621 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script); 00622 script = tmp; 00623 } 00624 00625 /* Before even trying let's see if the file actually exists */ 00626 if (stat(script, &st)) { 00627 ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script); 00628 return AGI_RESULT_NOTFOUND; 00629 } 00630 00631 if (pipe(toast)) { 00632 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno)); 00633 return AGI_RESULT_FAILURE; 00634 } 00635 if (pipe(fromast)) { 00636 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno)); 00637 close(toast[0]); 00638 close(toast[1]); 00639 return AGI_RESULT_FAILURE; 00640 } 00641 if (efd) { 00642 if (pipe(audio)) { 00643 ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno)); 00644 close(fromast[0]); 00645 close(fromast[1]); 00646 close(toast[0]); 00647 close(toast[1]); 00648 return AGI_RESULT_FAILURE; 00649 } 00650 res = fcntl(audio[1], F_GETFL); 00651 if (res > -1) 00652 res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK); 00653 if (res < 0) { 00654 ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno)); 00655 close(fromast[0]); 00656 close(fromast[1]); 00657 close(toast[0]); 00658 close(toast[1]); 00659 close(audio[0]); 00660 close(audio[1]); 00661 return AGI_RESULT_FAILURE; 00662 } 00663 } 00664 00665 if ((pid = ast_safe_fork(1)) < 0) { 00666 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); 00667 return AGI_RESULT_FAILURE; 00668 } 00669 if (!pid) { 00670 /* Pass paths to AGI via environmental variables */ 00671 setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1); 00672 setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1); 00673 setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1); 00674 setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1); 00675 setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1); 00676 setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1); 00677 setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1); 00678 setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1); 00679 setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1); 00680 setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1); 00681 setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1); 00682 00683 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */ 00684 ast_set_priority(0); 00685 00686 /* Redirect stdin and out, provide enhanced audio channel if desired */ 00687 dup2(fromast[0], STDIN_FILENO); 00688 dup2(toast[1], STDOUT_FILENO); 00689 if (efd) 00690 dup2(audio[0], STDERR_FILENO + 1); 00691 else 00692 close(STDERR_FILENO + 1); 00693 00694 /* Close everything but stdin/out/error */ 00695 ast_close_fds_above_n(STDERR_FILENO + 1); 00696 00697 /* Execute script */ 00698 /* XXX argv should be deprecated in favor of passing agi_argX paramaters */ 00699 execv(script, argv); 00700 /* Can't use ast_log since FD's are closed */ 00701 ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno)); 00702 /* Special case to set status of AGI to failure */ 00703 fprintf(stdout, "failure\n"); 00704 fflush(stdout); 00705 _exit(1); 00706 } 00707 ast_verb(3, "Launched AGI Script %s\n", script); 00708 fds[0] = toast[0]; 00709 fds[1] = fromast[1]; 00710 if (efd) 00711 *efd = audio[1]; 00712 /* close what we're not using in the parent */ 00713 close(toast[1]); 00714 close(fromast[0]); 00715 00716 if (efd) 00717 close(audio[0]); 00718 00719 *opid = pid; 00720 return AGI_RESULT_SUCCESS; 00721 }
| static int load_module | ( | void | ) | [static] |
Definition at line 3088 of file res_agi.c.
References action_add_agi_cmd(), agi_exec(), ARRAY_LEN, ast_agi_register_multiple(), ast_cli_register_multiple(), ast_manager_register2(), ast_register_application, cli_agi, commands, deadagi_exec(), eagi_exec(), EVENT_FLAG_AGI, and mandescr_asyncagi.
03089 { 03090 ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry)); 03091 /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as 03092 no other commands have been registered yet 03093 */ 03094 (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 03095 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip); 03096 ast_register_application(eapp, eagi_exec, esynopsis, descrip); 03097 ast_manager_register2("AGI", EVENT_FLAG_AGI, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi); 03098 return ast_register_application(app, agi_exec, synopsis, descrip); 03099 }
| static int parse_args | ( | char * | s, | |
| int * | max, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 2521 of file res_agi.c.
References ast_log(), LOG_WARNING, and MAX_ARGS.
Referenced by agi_handle_command().
02522 { 02523 int x = 0, quoted = 0, escaped = 0, whitespace = 1; 02524 char *cur; 02525 02526 cur = s; 02527 while(*s) { 02528 switch(*s) { 02529 case '"': 02530 /* If it's escaped, put a literal quote */ 02531 if (escaped) 02532 goto normal; 02533 else 02534 quoted = !quoted; 02535 if (quoted && whitespace) { 02536 /* If we're starting a quote, coming off white space start a new word, too */ 02537 argv[x++] = cur; 02538 whitespace=0; 02539 } 02540 escaped = 0; 02541 break; 02542 case ' ': 02543 case '\t': 02544 if (!quoted && !escaped) { 02545 /* If we're not quoted, mark this as whitespace, and 02546 end the previous argument */ 02547 whitespace = 1; 02548 *(cur++) = '\0'; 02549 } else 02550 /* Otherwise, just treat it as anything else */ 02551 goto normal; 02552 break; 02553 case '\\': 02554 /* If we're escaped, print a literal, otherwise enable escaping */ 02555 if (escaped) { 02556 goto normal; 02557 } else { 02558 escaped=1; 02559 } 02560 break; 02561 default: 02562 normal: 02563 if (whitespace) { 02564 if (x >= MAX_ARGS -1) { 02565 ast_log(LOG_WARNING, "Too many arguments, truncating\n"); 02566 break; 02567 } 02568 /* Coming off of whitespace, start the next argument */ 02569 argv[x++] = cur; 02570 whitespace=0; 02571 } 02572 *(cur++) = *s; 02573 escaped=0; 02574 } 02575 s++; 02576 } 02577 /* Null terminate */ 02578 *(cur++) = '\0'; 02579 argv[x] = NULL; 02580 *max = x; 02581 return 0; 02582 }
| 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 2656 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_channel_lock, ast_channel_unlock, 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, buf, 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().
02657 { 02658 struct ast_channel *c; 02659 int outfd, ms, needhup = 0; 02660 enum agi_result returnstatus = AGI_RESULT_SUCCESS; 02661 struct ast_frame *f; 02662 char buf[AGI_BUF_LEN]; 02663 char *res = NULL; 02664 FILE *readf; 02665 /* how many times we'll retry if ast_waitfor_nandfs will return without either 02666 channel or file descriptor in case select is interrupted by a system call (EINTR) */ 02667 int retry = AGI_NANDFS_RETRY; 02668 int send_sighup; 02669 const char *sighup_str; 02670 02671 ast_channel_lock(chan); 02672 sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP"); 02673 send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str); 02674 ast_channel_unlock(chan); 02675 02676 if (!(readf = fdopen(agi->ctrl, "r"))) { 02677 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n"); 02678 if (send_sighup && pid > -1) 02679 kill(pid, SIGHUP); 02680 close(agi->ctrl); 02681 return AGI_RESULT_FAILURE; 02682 } 02683 02684 setlinebuf(readf); 02685 setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv); 02686 for (;;) { 02687 if (needhup) { 02688 needhup = 0; 02689 dead = 1; 02690 if (send_sighup) { 02691 if (pid > -1) { 02692 kill(pid, SIGHUP); 02693 } else if (agi->fast) { 02694 send(agi->ctrl, "HANGUP\n", 7, MSG_OOB); 02695 } 02696 } 02697 } 02698 ms = -1; 02699 c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms); 02700 if (c) { 02701 retry = AGI_NANDFS_RETRY; 02702 /* Idle the channel until we get a command */ 02703 f = ast_read(c); 02704 if (!f) { 02705 ast_debug(1, "%s hungup\n", chan->name); 02706 returnstatus = AGI_RESULT_HANGUP; 02707 needhup = 1; 02708 continue; 02709 } else { 02710 /* If it's voice, write it to the audio pipe */ 02711 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) { 02712 /* Write, ignoring errors */ 02713 if (write(agi->audio, f->data.ptr, f->datalen) < 0) { 02714 } 02715 } 02716 ast_frfree(f); 02717 } 02718 } else if (outfd > -1) { 02719 size_t len = sizeof(buf); 02720 size_t buflen = 0; 02721 02722 retry = AGI_NANDFS_RETRY; 02723 buf[0] = '\0'; 02724 02725 while (buflen < (len - 1)) { 02726 res = fgets(buf + buflen, len, readf); 02727 if (feof(readf)) 02728 break; 02729 if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN))) 02730 break; 02731 if (res != NULL && !agi->fast) 02732 break; 02733 buflen = strlen(buf); 02734 if (buflen && buf[buflen - 1] == '\n') 02735 break; 02736 len -= buflen; 02737 if (agidebug) 02738 ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno)); 02739 } 02740 02741 if (!buf[0]) { 02742 /* Program terminated */ 02743 if (returnstatus) { 02744 returnstatus = -1; 02745 } 02746 ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", chan->name, request, returnstatus); 02747 if (pid > 0) 02748 waitpid(pid, status, 0); 02749 /* No need to kill the pid anymore, since they closed us */ 02750 pid = -1; 02751 break; 02752 } 02753 02754 /* Special case for inability to execute child process */ 02755 if (*buf && strncasecmp(buf, "failure", 7) == 0) { 02756 returnstatus = AGI_RESULT_FAILURE; 02757 break; 02758 } 02759 02760 /* get rid of trailing newline, if any */ 02761 if (*buf && buf[strlen(buf) - 1] == '\n') 02762 buf[strlen(buf) - 1] = 0; 02763 if (agidebug) 02764 ast_verbose("<%s>AGI Rx << %s\n", chan->name, buf); 02765 returnstatus |= agi_handle_command(chan, agi, buf, dead); 02766 /* If the handle_command returns -1, we need to stop */ 02767 if (returnstatus < 0) { 02768 needhup = 1; 02769 continue; 02770 } 02771 } else { 02772 if (--retry <= 0) { 02773 ast_log(LOG_WARNING, "No channel, no fd?\n"); 02774 returnstatus = AGI_RESULT_FAILURE; 02775 break; 02776 } 02777 } 02778 } 02779 if (agi->speech) { 02780 ast_speech_destroy(agi->speech); 02781 } 02782 /* Notify process */ 02783 if (send_sighup) { 02784 if (pid > -1) { 02785 if (kill(pid, SIGHUP)) { 02786 ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno)); 02787 } else { /* Give the process a chance to die */ 02788 usleep(1); 02789 } 02790 waitpid(pid, status, WNOHANG); 02791 } else if (agi->fast) { 02792 send(agi->ctrl, "HANGUP\n", 7, MSG_OOB); 02793 } 02794 } 02795 fclose(readf); 02796 return returnstatus; 02797 }
| static void setup_env | ( | struct ast_channel * | chan, | |
| char * | request, | |||
| int | fd, | |||
| int | enhanced, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 723 of file res_agi.c.
References ast_agi_send(), ast_get_version(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, ast_channel::priority, S_OR, ast_channel::tech, and ast_channel_tech::type.
Referenced by launch_asyncagi(), and run_agi().
00724 { 00725 int count; 00726 00727 /* Print initial environment, with agi_request always being the first 00728 thing */ 00729 ast_agi_send(fd, chan, "agi_request: %s\n", request); 00730 ast_agi_send(fd, chan, "agi_channel: %s\n", chan->name); 00731 ast_agi_send(fd, chan, "agi_language: %s\n", chan->language); 00732 ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type); 00733 ast_agi_send(fd, chan, "agi_uniqueid: %s\n", chan->uniqueid); 00734 ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version()); 00735 00736 /* ANI/DNIS */ 00737 ast_agi_send(fd, chan, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown")); 00738 ast_agi_send(fd, chan, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown")); 00739 ast_agi_send(fd, chan, "agi_callingpres: %d\n", chan->cid.cid_pres); 00740 ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->cid.cid_ani2); 00741 ast_agi_send(fd, chan, "agi_callington: %d\n", chan->cid.cid_ton); 00742 ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->cid.cid_tns); 00743 ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown")); 00744 ast_agi_send(fd, chan, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown")); 00745 00746 /* Context information */ 00747 ast_agi_send(fd, chan, "agi_context: %s\n", chan->context); 00748 ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten); 00749 ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority); 00750 ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0"); 00751 00752 /* User information */ 00753 ast_agi_send(fd, chan, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : ""); 00754 ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self()); 00755 00756 /* Send any parameters to the fastagi server that have been passed via the agi application */ 00757 /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */ 00758 for(count = 1; count < argc; count++) 00759 ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]); 00760 00761 /* End with empty return */ 00762 ast_agi_send(fd, chan, "\n"); 00763 }
| static int speech_streamfile | ( | struct ast_channel * | chan, | |
| const char * | filename, | |||
| const char * | preflang, | |||
| int | offset | |||
| ) | [static] |
Definition at line 1860 of file res_agi.c.
References ast_applystream(), ast_openstream(), ast_playstream(), and ast_seekstream().
Referenced by handle_speechrecognize().
01861 { 01862 struct ast_filestream *fs = NULL; 01863 01864 if (!(fs = ast_openstream(chan, filename, preflang))) 01865 return -1; 01866 01867 if (offset) 01868 ast_seekstream(fs, offset, SEEK_SET); 01869 01870 if (ast_applystream(chan, fs)) 01871 return -1; 01872 01873 if (ast_playstream(fs)) 01874 return -1; 01875 01876 return 0; 01877 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 3075 of file res_agi.c.
References ARRAY_LEN, ast_agi_unregister_multiple(), ast_cli_unregister_multiple(), ast_manager_unregister(), ast_unregister_application(), cli_agi, and commands.
03076 { 03077 ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry)); 03078 /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as 03079 we know that these commands were registered by this module and are still registered 03080 */ 03081 (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 03082 ast_unregister_application(eapp); 03083 ast_unregister_application(deadapp); 03084 ast_manager_unregister("AGI"); 03085 return ast_unregister_application(app); 03086 }
| static void write_html_escaped | ( | FILE * | htmlfile, | |
| char * | str | |||
| ) | [static] |
Convert string to use HTML escaped characters.
Definition at line 2839 of file res_agi.c.
Referenced by write_htmldump().
02840 { 02841 char *cur = str; 02842 02843 while(*cur) { 02844 switch (*cur) { 02845 case '<': 02846 fprintf(htmlfile, "%s", "<"); 02847 break; 02848 case '>': 02849 fprintf(htmlfile, "%s", ">"); 02850 break; 02851 case '&': 02852 fprintf(htmlfile, "%s", "&"); 02853 break; 02854 case '"': 02855 fprintf(htmlfile, "%s", """); 02856 break; 02857 default: 02858 fprintf(htmlfile, "%c", *cur); 02859 break; 02860 } 02861 cur++; 02862 } 02863 02864 return; 02865 }
| static int write_htmldump | ( | char * | filename | ) | [static] |
Definition at line 2867 of file res_agi.c.
References ast_join(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, strsep(), agi_command::summary, agi_command::usage, and write_html_escaped().
Referenced by handle_cli_agi_dump_html(), and handle_cli_agi_dumphtml_deprecated().
02868 { 02869 struct agi_command *command; 02870 char fullcmd[80]; 02871 FILE *htmlfile; 02872 02873 if (!(htmlfile = fopen(filename, "wt"))) 02874 return -1; 02875 02876 fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n"); 02877 fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n"); 02878 fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n"); 02879 02880 AST_RWLIST_RDLOCK(&agi_commands); 02881 AST_RWLIST_TRAVERSE(&agi_commands, command, list) { 02882 char *stringp, *tempstr; 02883 02884 if (!command->cmda[0]) /* end ? */ 02885 break; 02886 /* Hide commands that start with '_' */ 02887 if ((command->cmda[0])[0] == '_') 02888 continue; 02889 ast_join(fullcmd, sizeof(fullcmd), command->cmda); 02890 02891 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n"); 02892 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary); 02893 02894 stringp = command->usage; 02895 tempstr = strsep(&stringp, "\n"); 02896 02897 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">"); 02898 write_html_escaped(htmlfile, tempstr); 02899 fprintf(htmlfile, "</TD></TR>\n"); 02900 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n"); 02901 02902 while ((tempstr = strsep(&stringp, "\n")) != NULL) { 02903 write_html_escaped(htmlfile, tempstr); 02904 fprintf(htmlfile, "<BR>\n"); 02905 } 02906 fprintf(htmlfile, "</TD></TR>\n"); 02907 fprintf(htmlfile, "</TABLE></TD></TR>\n\n"); 02908 } 02909 AST_RWLIST_UNLOCK(&agi_commands); 02910 fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n"); 02911 fclose(htmlfile); 02912 return 0; 02913 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
struct ast_threadstorage agi_buf = { .once = { PTHREAD_ONCE_INIT } , .key_init = __init_agi_buf , .custom_init = NULL , } [static] |
Definition at line 115 of file res_agi.c.
Referenced by ast_agi_send().
struct ast_datastore_info agi_commands_datastore_info [static] |
{
.type = "AsyncAGI",
.destroy = agi_destroy_commands_cb
}
Definition at line 176 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] |
Definition at line 3068 of file res_agi.c.
Referenced by load_module(), and unload_module().
struct ast_cli_entry cli_agi_dumphtml_deprecated = AST_CLI_DEFINE(handle_cli_agi_dumphtml_deprecated, "Dumps a list of AGI commands in HTML format") [static] |
struct agi_command commands[] [static] |
AGI commands list.
Definition at line 2312 of file res_agi.c.
Referenced by aji_dinfo_handler(), dundi_showframe(), load_module(), and unload_module().
char* deadsynopsis = "Executes AGI on a hungup channel" [static] |
char* esynopsis = "Executes an EAGI compliant application" [static] |
const char mandescr_asyncagi[] [static] |
Definition at line 181 of file res_agi.c.
Referenced by load_module().
char usage_answer[] [static] |
char usage_asyncagi_break[] [static] |
char usage_autohangup[] [static] |
" Usage: SET AUTOHANGUP <time>\n" " Cause the channel to automatically hangup at <time> seconds in the\n" " future. Of course it can be hungup before then as well. Setting to 0 will\n" " cause the autohangup feature to be disabled on this channel.\n"
char usage_channelstatus[] [static] |
char usage_controlstreamfile[] [static] |
char usage_dbdel[] [static] |
char usage_dbdeltree[] [static] |
char usage_dbget[] [static] |
char usage_dbput[] [static] |
char usage_exec[] [static] |
char usage_getdata[] [static] |
char usage_getoption[] [static] |
char usage_getvariable[] [static] |
char usage_getvariablefull[] [static] |
char usage_hangup[] [static] |
char usage_noop[] [static] |
char usage_recordfile[] [static] |
char usage_recvchar[] [static] |
char usage_recvtext[] [static] |
" Usage: RECEIVE TEXT <timeout>\n" " Receives a string of text on a channel. Specify timeout to be the\n" " maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n" " do not support the reception of text. Returns -1 for failure or 1 for success, and the string in parentheses.\n"
char usage_sayalpha[] [static] |
char usage_saydate[] [static] |
char usage_saydatetime[] [static] |
char usage_saydigits[] [static] |
char usage_saynumber[] [static] |
char usage_sayphonetic[] [static] |
char usage_saytime[] [static] |
char usage_sendimage[] [static] |
char usage_sendtext[] [static] |
char usage_setcallerid[] [static] |
char usage_setcontext[] [static] |
char usage_setextension[] [static] |
char usage_setmusic[] [static] |
char usage_setpriority[] [static] |
char usage_setvariable[] [static] |
char usage_speechactivategrammar[] [static] |
char usage_speechcreate[] [static] |
char usage_speechdeactivategrammar[] [static] |
char usage_speechdestroy[] [static] |
char usage_speechloadgrammar[] [static] |
char usage_speechrecognize[] [static] |
char usage_speechset[] [static] |
char usage_speechunloadgrammar[] [static] |
char usage_streamfile[] [static] |
char usage_tddmode[] [static] |
char usage_verbose[] [static] |
char usage_waitfordigit[] [static] |
1.6.1