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 3021 of file res_agi.c.
References agi_exec_full(), and ast_check_hangup().
Referenced by deadagi_exec(), and load_module().
03022 { 03023 if (!ast_check_hangup(chan)) 03024 return agi_exec_full(chan, data, 0, 0); 03025 else 03026 return agi_exec_full(chan, data, 0, 1); 03027 }
| static int agi_exec_full | ( | struct ast_channel * | chan, | |
| void * | data, | |||
| int | enhanced, | |||
| int | dead | |||
| ) | [static] |
Definition at line 2954 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().
02955 { 02956 enum agi_result res; 02957 char buf[AGI_BUF_LEN] = "", *tmp = buf; 02958 int fds[2], efd = -1, pid; 02959 AST_DECLARE_APP_ARGS(args, 02960 AST_APP_ARG(arg)[MAX_ARGS]; 02961 ); 02962 AGI agi; 02963 02964 if (ast_strlen_zero(data)) { 02965 ast_log(LOG_WARNING, "AGI requires an argument (script)\n"); 02966 return -1; 02967 } 02968 if (dead) 02969 ast_debug(3, "Hungup channel detected, running agi in dead mode.\n"); 02970 ast_copy_string(buf, data, sizeof(buf)); 02971 memset(&agi, 0, sizeof(agi)); 02972 AST_STANDARD_APP_ARGS(args, tmp); 02973 args.argv[args.argc] = NULL; 02974 #if 0 02975 /* Answer if need be */ 02976 if (chan->_state != AST_STATE_UP) { 02977 if (ast_answer(chan)) 02978 return -1; 02979 } 02980 #endif 02981 res = launch_script(chan, args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid); 02982 /* Async AGI do not require run_agi(), so just proceed if normal AGI 02983 or Fast AGI are setup with success. */ 02984 if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) { 02985 int status = 0; 02986 agi.fd = fds[1]; 02987 agi.ctrl = fds[0]; 02988 agi.audio = efd; 02989 agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0; 02990 res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv); 02991 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */ 02992 if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status) 02993 res = AGI_RESULT_FAILURE; 02994 if (fds[1] != fds[0]) 02995 close(fds[1]); 02996 if (efd > -1) 02997 close(efd); 02998 } 02999 ast_safe_fork_cleanup(); 03000 03001 switch (res) { 03002 case AGI_RESULT_SUCCESS: 03003 case AGI_RESULT_SUCCESS_FAST: 03004 case AGI_RESULT_SUCCESS_ASYNC: 03005 pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS"); 03006 break; 03007 case AGI_RESULT_FAILURE: 03008 pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE"); 03009 break; 03010 case AGI_RESULT_NOTFOUND: 03011 pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND"); 03012 break; 03013 case AGI_RESULT_HANGUP: 03014 pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP"); 03015 return -1; 03016 } 03017 03018 return 0; 03019 }
| static int agi_handle_command | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| char * | buf, | |||
| int | dead | |||
| ) | [static] |
Definition at line 2575 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().
02576 { 02577 char *argv[MAX_ARGS]; 02578 int argc = MAX_ARGS, res; 02579 agi_command *c; 02580 const char *ami_res = "Unknown Result"; 02581 char *ami_cmd = ast_strdupa(buf); 02582 int command_id = ast_random(), resultcode = 200; 02583 02584 manager_event(EVENT_FLAG_AGI, "AGIExec", 02585 "SubEvent: Start\r\n" 02586 "Channel: %s\r\n" 02587 "CommandId: %d\r\n" 02588 "Command: %s\r\n", chan->name, command_id, ami_cmd); 02589 parse_args(buf, &argc, argv); 02590 if ((c = find_command(argv, 0)) && (!dead || (dead && c->dead))) { 02591 /* if this command wasnt registered by res_agi, be sure to usecount 02592 the module we are using */ 02593 if (c->mod != ast_module_info->self) 02594 ast_module_ref(c->mod); 02595 /* If the AGI command being executed is an actual application (using agi exec) 02596 the app field will be updated in pbx_exec via handle_exec */ 02597 if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC")) 02598 ast_cdr_setapp(chan->cdr, "AGI", buf); 02599 02600 res = c->handler(chan, agi, argc, argv); 02601 if (c->mod != ast_module_info->self) 02602 ast_module_unref(c->mod); 02603 switch (res) { 02604 case RESULT_SHOWUSAGE: ami_res = "Usage"; resultcode = 520; break; 02605 case RESULT_FAILURE: ami_res = "Failure"; resultcode = -1; break; 02606 case RESULT_SUCCESS: ami_res = "Success"; resultcode = 200; break; 02607 } 02608 manager_event(EVENT_FLAG_AGI, "AGIExec", 02609 "SubEvent: End\r\n" 02610 "Channel: %s\r\n" 02611 "CommandId: %d\r\n" 02612 "Command: %s\r\n" 02613 "ResultCode: %d\r\n" 02614 "Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res); 02615 switch(res) { 02616 case RESULT_SHOWUSAGE: 02617 ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n"); 02618 ast_agi_send(agi->fd, chan, "%s", c->usage); 02619 ast_agi_send(agi->fd, chan, "520 End of proper usage.\n"); 02620 break; 02621 case RESULT_FAILURE: 02622 /* They've already given the failure. We've been hung up on so handle this 02623 appropriately */ 02624 return -1; 02625 } 02626 } else if ((c = find_command(argv, 0))) { 02627 ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n"); 02628 manager_event(EVENT_FLAG_AGI, "AGIExec", 02629 "SubEvent: End\r\n" 02630 "Channel: %s\r\n" 02631 "CommandId: %d\r\n" 02632 "Command: %s\r\n" 02633 "ResultCode: 511\r\n" 02634 "Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd); 02635 } else { 02636 ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\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: 510\r\n" 02643 "Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd); 02644 } 02645 return 0; 02646 }
| int ast_agi_register | ( | struct ast_module * | mod, | |
| agi_command * | cmd | |||
| ) |
Definition at line 2380 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().
02381 { 02382 char fullcmd[80]; 02383 02384 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 02385 02386 if (!find_command(cmd->cmda,1)) { 02387 cmd->mod = mod; 02388 AST_RWLIST_WRLOCK(&agi_commands); 02389 AST_LIST_INSERT_TAIL(&agi_commands, cmd, list); 02390 AST_RWLIST_UNLOCK(&agi_commands); 02391 if (mod != ast_module_info->self) 02392 ast_module_ref(ast_module_info->self); 02393 ast_verb(2, "AGI Command '%s' registered\n",fullcmd); 02394 return 1; 02395 } else { 02396 ast_log(LOG_WARNING, "Command already registered!\n"); 02397 return 0; 02398 } 02399 }
| 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 2428 of file res_agi.c.
References ast_agi_register(), and ast_agi_unregister().
Referenced by load_module().
02429 { 02430 unsigned int i, x = 0; 02431 02432 for (i = 0; i < len; i++) { 02433 if (ast_agi_register(mod, cmd + i) == 1) { 02434 x++; 02435 continue; 02436 } 02437 02438 /* registration failed, unregister everything 02439 that had been registered up to that point 02440 */ 02441 for (; x > 0; x--) { 02442 /* we are intentionally ignoring the 02443 result of ast_agi_unregister() here, 02444 but it should be safe to do so since 02445 we just registered these commands and 02446 the only possible way for unregistration 02447 to fail is if the command is not 02448 registered 02449 */ 02450 (void) ast_agi_unregister(mod, cmd + x - 1); 02451 } 02452 return -1; 02453 } 02454 02455 return 0; 02456 }
| 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 2401 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().
02402 { 02403 struct agi_command *e; 02404 int unregistered = 0; 02405 char fullcmd[80]; 02406 02407 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 02408 02409 AST_RWLIST_WRLOCK(&agi_commands); 02410 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) { 02411 if (cmd == e) { 02412 AST_RWLIST_REMOVE_CURRENT(list); 02413 if (mod != ast_module_info->self) 02414 ast_module_unref(ast_module_info->self); 02415 unregistered=1; 02416 break; 02417 } 02418 } 02419 AST_RWLIST_TRAVERSE_SAFE_END; 02420 AST_RWLIST_UNLOCK(&agi_commands); 02421 if (unregistered) 02422 ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd); 02423 else 02424 ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd); 02425 return unregistered; 02426 }
| 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 2458 of file res_agi.c.
References ast_agi_unregister().
Referenced by unload_module().
02459 { 02460 unsigned int i; 02461 int res = 0; 02462 02463 for (i = 0; i < len; i++) { 02464 /* remember whether any of the unregistration 02465 attempts failed... there is no recourse if 02466 any of them do 02467 */ 02468 res |= ast_agi_unregister(mod, cmd + i); 02469 } 02470 02471 return res; 02472 }
| static int deadagi_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3051 of file res_agi.c.
References agi_exec(), ast_log(), and LOG_WARNING.
Referenced by load_module().
03052 { 03053 ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n"); 03054 return agi_exec(chan, data); 03055 }
| static int eagi_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3029 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().
03030 { 03031 int readformat, res; 03032 03033 if (ast_check_hangup(chan)) { 03034 ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n"); 03035 return 0; 03036 } 03037 readformat = chan->readformat; 03038 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 03039 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name); 03040 return -1; 03041 } 03042 res = agi_exec_full(chan, data, 1, 0); 03043 if (!res) { 03044 if (ast_set_read_format(chan, readformat)) { 03045 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat)); 03046 } 03047 } 03048 return res; 03049 }
| static agi_command * find_command | ( | char * | cmds[], | |
| int | exact | |||
| ) | [static] |
Definition at line 2474 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().
02475 { 02476 int y, match; 02477 struct agi_command *e; 02478 02479 AST_RWLIST_RDLOCK(&agi_commands); 02480 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 02481 if (!e->cmda[0]) 02482 break; 02483 /* start optimistic */ 02484 match = 1; 02485 for (y = 0; match && cmds[y]; y++) { 02486 /* If there are no more words in the command (and we're looking for 02487 an exact match) or there is a difference between the two words, 02488 then this is not a match */ 02489 if (!e->cmda[y] && !exact) 02490 break; 02491 /* don't segfault if the next part of a command doesn't exist */ 02492 if (!e->cmda[y]) { 02493 AST_RWLIST_UNLOCK(&agi_commands); 02494 return NULL; 02495 } 02496 if (strcasecmp(e->cmda[y], cmds[y])) 02497 match = 0; 02498 } 02499 /* If more words are needed to complete the command then this is not 02500 a candidate (unless we're looking for a really inexact answer */ 02501 if ((exact > -1) && e->cmda[y]) 02502 match = 0; 02503 if (match) { 02504 AST_RWLIST_UNLOCK(&agi_commands); 02505 return e; 02506 } 02507 } 02508 AST_RWLIST_UNLOCK(&agi_commands); 02509 return NULL; 02510 }
| 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 1522 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.
01523 { 01524 struct ast_channel *c; 01525 if (argc == 2) { 01526 /* no argument: supply info on the current channel */ 01527 ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state); 01528 return RESULT_SUCCESS; 01529 } else if (argc == 3) { 01530 /* one argument: look for info on the specified channel */ 01531 c = ast_get_channel_by_name_locked(argv[2]); 01532 if (c) { 01533 ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state); 01534 ast_channel_unlock(c); 01535 return RESULT_SUCCESS; 01536 } 01537 /* if we get this far no channel name matched the argument given */ 01538 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01539 return RESULT_SUCCESS; 01540 } else { 01541 return RESULT_SHOWUSAGE; 01542 } 01543 }
| 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 1687 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.
01688 { 01689 switch (cmd) { 01690 case CLI_INIT: 01691 e->command = "agi set debug [on|off]"; 01692 e->usage = 01693 "Usage: agi set debug [on|off]\n" 01694 " Enables/disables dumping of AGI transactions for\n" 01695 " debugging purposes.\n"; 01696 return NULL; 01697 01698 case CLI_GENERATE: 01699 return NULL; 01700 } 01701 01702 if (a->argc != e->args) 01703 return CLI_SHOWUSAGE; 01704 01705 if (strncasecmp(a->argv[3], "off", 3) == 0) { 01706 agidebug = 0; 01707 } else if (strncasecmp(a->argv[3], "on", 2) == 0) { 01708 agidebug = 1; 01709 } else { 01710 return CLI_SHOWUSAGE; 01711 } 01712 ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis"); 01713 return CLI_SUCCESS; 01714 }
| static char* handle_cli_agi_dump_html | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2930 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().
02931 { 02932 switch (cmd) { 02933 case CLI_INIT: 02934 e->command = "agi dump html"; 02935 e->usage = 02936 "Usage: agi dump html <filename>\n" 02937 " Dumps the AGI command list in HTML format to the given\n" 02938 " file.\n"; 02939 return NULL; 02940 case CLI_GENERATE: 02941 return NULL; 02942 } 02943 if (a->argc != e->args + 1) 02944 return CLI_SHOWUSAGE; 02945 02946 if (write_htmldump(a->argv[e->args]) < 0) { 02947 ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]); 02948 return CLI_SHOWUSAGE; 02949 } 02950 ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]); 02951 return CLI_SUCCESS; 02952 }
| static char* handle_cli_agi_dumphtml_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2906 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().
02907 { 02908 switch (cmd) { 02909 case CLI_INIT: 02910 e->command = "agi dumphtml"; 02911 e->usage = 02912 "Usage: agi dumphtml <filename>\n" 02913 " Dumps the AGI command list in HTML format to the given\n" 02914 " file.\n"; 02915 return NULL; 02916 case CLI_GENERATE: 02917 return NULL; 02918 } 02919 if (a->argc < e->args + 1) 02920 return CLI_SHOWUSAGE; 02921 02922 if (write_htmldump(a->argv[2]) < 0) { 02923 ast_cli(a->fd, "Could not create file '%s'\n", a->argv[2]); 02924 return CLI_SHOWUSAGE; 02925 } 02926 ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[2]); 02927 return CLI_SUCCESS; 02928 }
| static char* handle_cli_agi_show | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2790 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.
02791 { 02792 struct agi_command *command; 02793 char fullcmd[80]; 02794 02795 switch (cmd) { 02796 case CLI_INIT: 02797 e->command = "agi show"; 02798 e->usage = 02799 "Usage: agi show [topic]\n" 02800 " When called with a topic as an argument, displays usage\n" 02801 " information on the given command. If called without a\n" 02802 " topic, it provides a list of AGI commands.\n"; 02803 case CLI_GENERATE: 02804 return NULL; 02805 } 02806 if (a->argc < e->args) 02807 return CLI_SHOWUSAGE; 02808 if (a->argc > e->args) { 02809 command = find_command(a->argv + e->args, 1); 02810 if (command) { 02811 ast_cli(a->fd, "%s", command->usage); 02812 ast_cli(a->fd, " Runs Dead : %s\n", command->dead ? "Yes" : "No"); 02813 } else { 02814 if (find_command(a->argv + e->args, -1)) { 02815 return help_workhorse(a->fd, a->argv + e->args); 02816 } else { 02817 ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args); 02818 ast_cli(a->fd, "No such command '%s'.\n", fullcmd); 02819 } 02820 } 02821 } else { 02822 return help_workhorse(a->fd, NULL); 02823 } 02824 return CLI_SUCCESS; 02825 }
| 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 1661 of file res_agi.c.
References ast_agi_send(), ast_db_del(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01662 { 01663 int res; 01664 01665 if (argc != 4) 01666 return RESULT_SHOWUSAGE; 01667 res = ast_db_del(argv[2], argv[3]); 01668 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01669 return RESULT_SUCCESS; 01670 }
| static int handle_dbdeltree | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1672 of file res_agi.c.
References ast_agi_send(), ast_db_deltree(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01673 { 01674 int res; 01675 01676 if ((argc < 3) || (argc > 4)) 01677 return RESULT_SHOWUSAGE; 01678 if (argc == 4) 01679 res = ast_db_deltree(argv[2], argv[3]); 01680 else 01681 res = ast_db_deltree(argv[2], NULL); 01682 01683 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01684 return RESULT_SUCCESS; 01685 }
| static int handle_dbget | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1617 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.
01618 { 01619 int res; 01620 struct ast_str *buf; 01621 01622 if (argc != 4) 01623 return RESULT_SHOWUSAGE; 01624 01625 if (!(buf = ast_str_create(16))) { 01626 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01627 return RESULT_SUCCESS; 01628 } 01629 01630 do { 01631 res = ast_db_get(argv[2], argv[3], buf->str, buf->len); 01632 buf->used = strlen(buf->str); 01633 if (buf->used < buf->len - 1) { 01634 break; 01635 } 01636 if (ast_str_make_space(&buf, buf->len * 2)) { 01637 break; 01638 } 01639 } while (1); 01640 01641 if (res) 01642 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01643 else 01644 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf->str); 01645 01646 ast_free(buf); 01647 return RESULT_SUCCESS; 01648 }
| static int handle_dbput | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1650 of file res_agi.c.
References ast_agi_send(), ast_db_put(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01651 { 01652 int res; 01653 01654 if (argc != 5) 01655 return RESULT_SHOWUSAGE; 01656 res = ast_db_put(argv[2], argv[3], argv[4]); 01657 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01658 return RESULT_SUCCESS; 01659 }
| 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_compat_res_agi, ast_log(), ast_masq_park_call(), ast_strlen_zero(), ast_verb, agi_state::fd, LOG_WARNING, PARK_APP_NAME, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.
01461 { 01462 int res; 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], 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 (ast_compat_res_agi && !ast_strlen_zero(argv[2])) { 01475 char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr, *vptr; 01476 for (cptr = compat, vptr = argv[2]; *vptr; vptr++) { 01477 if (*vptr == ',') { 01478 *cptr++ = '\\'; 01479 *cptr++ = ','; 01480 } else if (*vptr == '|') { 01481 *cptr++ = ','; 01482 } else { 01483 *cptr++ = *vptr; 01484 } 01485 } 01486 *cptr = '\0'; 01487 res = pbx_exec(chan, app_to_exec, compat); 01488 } else { 01489 res = pbx_exec(chan, app_to_exec, argv[2]); 01490 } 01491 } else { 01492 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]); 01493 res = -2; 01494 } 01495 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01496 01497 /* Even though this is wrong, users are depending upon this result. */ 01498 return res; 01499 }
| 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 1554 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.
01555 { 01556 char *ret; 01557 char tempstr[1024]; 01558 01559 if (argc != 3) 01560 return RESULT_SHOWUSAGE; 01561 01562 /* check if we want to execute an ast_custom_function */ 01563 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) { 01564 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr; 01565 } else { 01566 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL); 01567 } 01568 01569 if (ret) 01570 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret); 01571 else 01572 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01573 01574 return RESULT_SUCCESS; 01575 }
| static int handle_getvariablefull | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1577 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.
01578 { 01579 char tmp[4096]; 01580 struct ast_channel *chan2=NULL; 01581 01582 if ((argc != 4) && (argc != 5)) 01583 return RESULT_SHOWUSAGE; 01584 if (argc == 5) { 01585 chan2 = ast_get_channel_by_name_locked(argv[4]); 01586 } else { 01587 chan2 = chan; 01588 } 01589 if (chan2) { 01590 pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1); 01591 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp); 01592 } else { 01593 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01594 } 01595 if (chan2 && (chan2 != chan)) 01596 ast_channel_unlock(chan2); 01597 return RESULT_SUCCESS; 01598 }
| 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 1716 of file res_agi.c.
References ast_agi_send(), agi_state::fd, and RESULT_SUCCESS.
01717 { 01718 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01719 return RESULT_SUCCESS; 01720 }
| 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 1501 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.
01502 { 01503 char tmp[256]=""; 01504 char *l = NULL, *n = NULL; 01505 01506 if (argv[2]) { 01507 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01508 ast_callerid_parse(tmp, &n, &l); 01509 if (l) 01510 ast_shrink_phone_number(l); 01511 else 01512 l = ""; 01513 if (!n) 01514 n = ""; 01515 ast_set_callerid(chan, l, n, NULL); 01516 } 01517 01518 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01519 return RESULT_SUCCESS; 01520 }
| 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 1722 of file res_agi.c.
References ast_agi_send(), ast_moh_start(), ast_moh_stop(), agi_state::fd, and RESULT_SUCCESS.
01723 { 01724 if (!strncasecmp(argv[2], "on", 2)) 01725 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL); 01726 else if (!strncasecmp(argv[2], "off", 3)) 01727 ast_moh_stop(chan); 01728 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01729 return RESULT_SUCCESS; 01730 }
| 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 1545 of file res_agi.c.
References ast_agi_send(), agi_state::fd, pbx_builtin_setvar_helper(), and RESULT_SUCCESS.
01546 { 01547 if (argv[3]) 01548 pbx_builtin_setvar_helper(chan, argv[2], argv[3]); 01549 01550 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01551 return RESULT_SUCCESS; 01552 }
| static int handle_speechactivategrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1815 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_activate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01816 { 01817 if (argc != 4) 01818 return RESULT_SHOWUSAGE; 01819 01820 if (!agi->speech) { 01821 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01822 return RESULT_SUCCESS; 01823 } 01824 01825 if (ast_speech_grammar_activate(agi->speech, argv[3])) 01826 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01827 else 01828 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01829 01830 return RESULT_SUCCESS; 01831 }
| static int handle_speechcreate | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1732 of file res_agi.c.
References ast_agi_send(), AST_FORMAT_SLINEAR, ast_speech_new(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
01733 { 01734 /* If a structure already exists, return an error */ 01735 if (agi->speech) { 01736 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01737 return RESULT_SUCCESS; 01738 } 01739 01740 if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR))) 01741 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01742 else 01743 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01744 01745 return RESULT_SUCCESS; 01746 }
| static int handle_speechdeactivategrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1833 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_deactivate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01834 { 01835 if (argc != 4) 01836 return RESULT_SHOWUSAGE; 01837 01838 if (!agi->speech) { 01839 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01840 return RESULT_SUCCESS; 01841 } 01842 01843 if (ast_speech_grammar_deactivate(agi->speech, argv[3])) 01844 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01845 else 01846 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01847 01848 return RESULT_SUCCESS; 01849 }
| static int handle_speechdestroy | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1766 of file res_agi.c.
References ast_agi_send(), ast_speech_destroy(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
01767 { 01768 if (agi->speech) { 01769 ast_speech_destroy(agi->speech); 01770 agi->speech = NULL; 01771 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01772 } else { 01773 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01774 } 01775 01776 return RESULT_SUCCESS; 01777 }
| static int handle_speechloadgrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1779 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_load(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01780 { 01781 if (argc != 5) 01782 return RESULT_SHOWUSAGE; 01783 01784 if (!agi->speech) { 01785 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01786 return RESULT_SUCCESS; 01787 } 01788 01789 if (ast_speech_grammar_load(agi->speech, argv[3], argv[4])) 01790 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01791 else 01792 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01793 01794 return RESULT_SUCCESS; 01795 }
| static int handle_speechrecognize | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1870 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.
01871 { 01872 struct ast_speech *speech = agi->speech; 01873 char *prompt, dtmf = 0, tmp[4096] = "", *buf = tmp; 01874 int timeout = 0, offset = 0, old_read_format = 0, res = 0, i = 0; 01875 long current_offset = 0; 01876 const char *reason = NULL; 01877 struct ast_frame *fr = NULL; 01878 struct ast_speech_result *result = NULL; 01879 size_t left = sizeof(tmp); 01880 time_t start = 0, current; 01881 01882 if (argc < 4) 01883 return RESULT_SHOWUSAGE; 01884 01885 if (!speech) { 01886 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01887 return RESULT_SUCCESS; 01888 } 01889 01890 prompt = argv[2]; 01891 timeout = atoi(argv[3]); 01892 01893 /* If offset is specified then convert from text to integer */ 01894 if (argc == 5) 01895 offset = atoi(argv[4]); 01896 01897 /* We want frames coming in signed linear */ 01898 old_read_format = chan->readformat; 01899 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 01900 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01901 return RESULT_SUCCESS; 01902 } 01903 01904 /* Setup speech structure */ 01905 if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) { 01906 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 01907 ast_speech_start(speech); 01908 } 01909 01910 /* Start playing prompt */ 01911 speech_streamfile(chan, prompt, chan->language, offset); 01912 01913 /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */ 01914 while (ast_strlen_zero(reason)) { 01915 /* Run scheduled items */ 01916 ast_sched_runq(chan->sched); 01917 01918 /* See maximum time of waiting */ 01919 if ((res = ast_sched_wait(chan->sched)) < 0) 01920 res = 1000; 01921 01922 /* Wait for frame */ 01923 if (ast_waitfor(chan, res) > 0) { 01924 if (!(fr = ast_read(chan))) { 01925 reason = "hangup"; 01926 break; 01927 } 01928 } 01929 01930 /* Perform timeout check */ 01931 if ((timeout > 0) && (start > 0)) { 01932 time(¤t); 01933 if ((current - start) >= timeout) { 01934 reason = "timeout"; 01935 if (fr) 01936 ast_frfree(fr); 01937 break; 01938 } 01939 } 01940 01941 /* Check the speech structure for any changes */ 01942 ast_mutex_lock(&speech->lock); 01943 01944 /* See if we need to quiet the audio stream playback */ 01945 if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) { 01946 current_offset = ast_tellstream(chan->stream); 01947 ast_stopstream(chan); 01948 ast_clear_flag(speech, AST_SPEECH_QUIET); 01949 } 01950 01951 /* Check each state */ 01952 switch (speech->state) { 01953 case AST_SPEECH_STATE_READY: 01954 /* If the stream is done, start timeout calculation */ 01955 if ((timeout > 0) && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) { 01956 ast_stopstream(chan); 01957 time(&start); 01958 } 01959 /* Write audio frame data into speech engine if possible */ 01960 if (fr && fr->frametype == AST_FRAME_VOICE) 01961 ast_speech_write(speech, fr->data.ptr, fr->datalen); 01962 break; 01963 case AST_SPEECH_STATE_WAIT: 01964 /* Cue waiting sound if not already playing */ 01965 if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) { 01966 ast_stopstream(chan); 01967 /* If a processing sound exists, or is not none - play it */ 01968 if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none")) 01969 speech_streamfile(chan, speech->processing_sound, chan->language, 0); 01970 } 01971 break; 01972 case AST_SPEECH_STATE_DONE: 01973 /* Get the results */ 01974 speech->results = ast_speech_results_get(speech); 01975 /* Change state to not ready */ 01976 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 01977 reason = "speech"; 01978 break; 01979 default: 01980 break; 01981 } 01982 ast_mutex_unlock(&speech->lock); 01983 01984 /* Check frame for DTMF or hangup */ 01985 if (fr) { 01986 if (fr->frametype == AST_FRAME_DTMF) { 01987 reason = "dtmf"; 01988 dtmf = fr->subclass; 01989 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_HANGUP) { 01990 reason = "hangup"; 01991 } 01992 ast_frfree(fr); 01993 } 01994 } 01995 01996 if (!strcasecmp(reason, "speech")) { 01997 /* Build string containing speech results */ 01998 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) { 01999 /* Build result string */ 02000 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); 02001 /* Increment result count */ 02002 i++; 02003 } 02004 /* Print out */ 02005 ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp); 02006 } else if (!strcasecmp(reason, "dtmf")) { 02007 ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset); 02008 } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) { 02009 ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset); 02010 } else { 02011 ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset); 02012 } 02013 02014 return RESULT_SUCCESS; 02015 }
| static int handle_speechset | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1748 of file res_agi.c.
References ast_agi_send(), ast_speech_change(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01749 { 01750 /* Check for minimum arguments */ 01751 if (argc != 3) 01752 return RESULT_SHOWUSAGE; 01753 01754 /* Check to make sure speech structure exists */ 01755 if (!agi->speech) { 01756 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01757 return RESULT_SUCCESS; 01758 } 01759 01760 ast_speech_change(agi->speech, argv[2], argv[3]); 01761 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01762 01763 return RESULT_SUCCESS; 01764 }
| static int handle_speechunloadgrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1797 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_unload(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01798 { 01799 if (argc != 4) 01800 return RESULT_SHOWUSAGE; 01801 01802 if (!agi->speech) { 01803 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01804 return RESULT_SUCCESS; 01805 } 01806 01807 if (ast_speech_grammar_unload(agi->speech, argv[3])) 01808 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01809 else 01810 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01811 01812 return RESULT_SUCCESS; 01813 }
| 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 1600 of file res_agi.c.
References ast_agi_send(), ast_verb, ast_channel::data, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01601 { 01602 int level = 0; 01603 01604 if (argc < 2) 01605 return RESULT_SHOWUSAGE; 01606 01607 if (argv[2]) 01608 sscanf(argv[2], "%30d", &level); 01609 01610 ast_verb(level, "%s: %s\n", chan->data, argv[1]); 01611 01612 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01613 01614 return RESULT_SUCCESS; 01615 }
| 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 2354 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().
02355 { 02356 char fullcmd[80], matchstr[80]; 02357 struct agi_command *e; 02358 02359 if (match) 02360 ast_join(matchstr, sizeof(matchstr), match); 02361 02362 ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description"); 02363 AST_RWLIST_RDLOCK(&agi_commands); 02364 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 02365 if (!e->cmda[0]) 02366 break; 02367 /* Hide commands that start with '_' */ 02368 if ((e->cmda[0])[0] == '_') 02369 continue; 02370 ast_join(fullcmd, sizeof(fullcmd), e->cmda); 02371 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr))) 02372 continue; 02373 ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, e->summary); 02374 } 02375 AST_RWLIST_UNLOCK(&agi_commands); 02376 02377 return CLI_SUCCESS; 02378 }
| 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 3079 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.
03080 { 03081 ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry)); 03082 /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as 03083 no other commands have been registered yet 03084 */ 03085 (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 03086 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip); 03087 ast_register_application(eapp, eagi_exec, esynopsis, descrip); 03088 ast_manager_register2("AGI", EVENT_FLAG_AGI, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi); 03089 return ast_register_application(app, agi_exec, synopsis, descrip); 03090 }
| static int parse_args | ( | char * | s, | |
| int * | max, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 2512 of file res_agi.c.
References ast_log(), LOG_WARNING, and MAX_ARGS.
Referenced by agi_handle_command().
02513 { 02514 int x = 0, quoted = 0, escaped = 0, whitespace = 1; 02515 char *cur; 02516 02517 cur = s; 02518 while(*s) { 02519 switch(*s) { 02520 case '"': 02521 /* If it's escaped, put a literal quote */ 02522 if (escaped) 02523 goto normal; 02524 else 02525 quoted = !quoted; 02526 if (quoted && whitespace) { 02527 /* If we're starting a quote, coming off white space start a new word, too */ 02528 argv[x++] = cur; 02529 whitespace=0; 02530 } 02531 escaped = 0; 02532 break; 02533 case ' ': 02534 case '\t': 02535 if (!quoted && !escaped) { 02536 /* If we're not quoted, mark this as whitespace, and 02537 end the previous argument */ 02538 whitespace = 1; 02539 *(cur++) = '\0'; 02540 } else 02541 /* Otherwise, just treat it as anything else */ 02542 goto normal; 02543 break; 02544 case '\\': 02545 /* If we're escaped, print a literal, otherwise enable escaping */ 02546 if (escaped) { 02547 goto normal; 02548 } else { 02549 escaped=1; 02550 } 02551 break; 02552 default: 02553 normal: 02554 if (whitespace) { 02555 if (x >= MAX_ARGS -1) { 02556 ast_log(LOG_WARNING, "Too many arguments, truncating\n"); 02557 break; 02558 } 02559 /* Coming off of whitespace, start the next argument */ 02560 argv[x++] = cur; 02561 whitespace=0; 02562 } 02563 *(cur++) = *s; 02564 escaped=0; 02565 } 02566 s++; 02567 } 02568 /* Null terminate */ 02569 *(cur++) = '\0'; 02570 argv[x] = NULL; 02571 *max = x; 02572 return 0; 02573 }
| 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 2647 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().
02648 { 02649 struct ast_channel *c; 02650 int outfd, ms, needhup = 0; 02651 enum agi_result returnstatus = AGI_RESULT_SUCCESS; 02652 struct ast_frame *f; 02653 char buf[AGI_BUF_LEN]; 02654 char *res = NULL; 02655 FILE *readf; 02656 /* how many times we'll retry if ast_waitfor_nandfs will return without either 02657 channel or file descriptor in case select is interrupted by a system call (EINTR) */ 02658 int retry = AGI_NANDFS_RETRY; 02659 int send_sighup; 02660 const char *sighup_str; 02661 02662 ast_channel_lock(chan); 02663 sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP"); 02664 send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str); 02665 ast_channel_unlock(chan); 02666 02667 if (!(readf = fdopen(agi->ctrl, "r"))) { 02668 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n"); 02669 if (send_sighup && pid > -1) 02670 kill(pid, SIGHUP); 02671 close(agi->ctrl); 02672 return AGI_RESULT_FAILURE; 02673 } 02674 02675 setlinebuf(readf); 02676 setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv); 02677 for (;;) { 02678 if (needhup) { 02679 needhup = 0; 02680 dead = 1; 02681 if (send_sighup) { 02682 if (pid > -1) { 02683 kill(pid, SIGHUP); 02684 } else if (agi->fast) { 02685 send(agi->ctrl, "HANGUP\n", 7, MSG_OOB); 02686 } 02687 } 02688 } 02689 ms = -1; 02690 c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms); 02691 if (c) { 02692 retry = AGI_NANDFS_RETRY; 02693 /* Idle the channel until we get a command */ 02694 f = ast_read(c); 02695 if (!f) { 02696 ast_debug(1, "%s hungup\n", chan->name); 02697 returnstatus = AGI_RESULT_HANGUP; 02698 needhup = 1; 02699 continue; 02700 } else { 02701 /* If it's voice, write it to the audio pipe */ 02702 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) { 02703 /* Write, ignoring errors */ 02704 if (write(agi->audio, f->data.ptr, f->datalen) < 0) { 02705 } 02706 } 02707 ast_frfree(f); 02708 } 02709 } else if (outfd > -1) { 02710 size_t len = sizeof(buf); 02711 size_t buflen = 0; 02712 02713 retry = AGI_NANDFS_RETRY; 02714 buf[0] = '\0'; 02715 02716 while (buflen < (len - 1)) { 02717 res = fgets(buf + buflen, len, readf); 02718 if (feof(readf)) 02719 break; 02720 if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN))) 02721 break; 02722 if (res != NULL && !agi->fast) 02723 break; 02724 buflen = strlen(buf); 02725 if (buflen && buf[buflen - 1] == '\n') 02726 break; 02727 len -= buflen; 02728 if (agidebug) 02729 ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno)); 02730 } 02731 02732 if (!buf[0]) { 02733 /* Program terminated */ 02734 if (returnstatus) { 02735 returnstatus = -1; 02736 } 02737 ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", chan->name, request, returnstatus); 02738 if (pid > 0) 02739 waitpid(pid, status, 0); 02740 /* No need to kill the pid anymore, since they closed us */ 02741 pid = -1; 02742 break; 02743 } 02744 02745 /* Special case for inability to execute child process */ 02746 if (*buf && strncasecmp(buf, "failure", 7) == 0) { 02747 returnstatus = AGI_RESULT_FAILURE; 02748 break; 02749 } 02750 02751 /* get rid of trailing newline, if any */ 02752 if (*buf && buf[strlen(buf) - 1] == '\n') 02753 buf[strlen(buf) - 1] = 0; 02754 if (agidebug) 02755 ast_verbose("<%s>AGI Rx << %s\n", chan->name, buf); 02756 returnstatus |= agi_handle_command(chan, agi, buf, dead); 02757 /* If the handle_command returns -1, we need to stop */ 02758 if (returnstatus < 0) { 02759 needhup = 1; 02760 continue; 02761 } 02762 } else { 02763 if (--retry <= 0) { 02764 ast_log(LOG_WARNING, "No channel, no fd?\n"); 02765 returnstatus = AGI_RESULT_FAILURE; 02766 break; 02767 } 02768 } 02769 } 02770 if (agi->speech) { 02771 ast_speech_destroy(agi->speech); 02772 } 02773 /* Notify process */ 02774 if (send_sighup) { 02775 if (pid > -1) { 02776 if (kill(pid, SIGHUP)) { 02777 ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno)); 02778 } else { /* Give the process a chance to die */ 02779 usleep(1); 02780 } 02781 waitpid(pid, status, WNOHANG); 02782 } else if (agi->fast) { 02783 send(agi->ctrl, "HANGUP\n", 7, MSG_OOB); 02784 } 02785 } 02786 fclose(readf); 02787 return returnstatus; 02788 }
| 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 1851 of file res_agi.c.
References ast_applystream(), ast_openstream(), ast_playstream(), and ast_seekstream().
Referenced by handle_speechrecognize().
01852 { 01853 struct ast_filestream *fs = NULL; 01854 01855 if (!(fs = ast_openstream(chan, filename, preflang))) 01856 return -1; 01857 01858 if (offset) 01859 ast_seekstream(fs, offset, SEEK_SET); 01860 01861 if (ast_applystream(chan, fs)) 01862 return -1; 01863 01864 if (ast_playstream(fs)) 01865 return -1; 01866 01867 return 0; 01868 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 3066 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.
03067 { 03068 ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry)); 03069 /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as 03070 we know that these commands were registered by this module and are still registered 03071 */ 03072 (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 03073 ast_unregister_application(eapp); 03074 ast_unregister_application(deadapp); 03075 ast_manager_unregister("AGI"); 03076 return ast_unregister_application(app); 03077 }
| static void write_html_escaped | ( | FILE * | htmlfile, | |
| char * | str | |||
| ) | [static] |
Convert string to use HTML escaped characters.
Definition at line 2830 of file res_agi.c.
Referenced by write_htmldump().
02831 { 02832 char *cur = str; 02833 02834 while(*cur) { 02835 switch (*cur) { 02836 case '<': 02837 fprintf(htmlfile, "%s", "<"); 02838 break; 02839 case '>': 02840 fprintf(htmlfile, "%s", ">"); 02841 break; 02842 case '&': 02843 fprintf(htmlfile, "%s", "&"); 02844 break; 02845 case '"': 02846 fprintf(htmlfile, "%s", """); 02847 break; 02848 default: 02849 fprintf(htmlfile, "%c", *cur); 02850 break; 02851 } 02852 cur++; 02853 } 02854 02855 return; 02856 }
| static int write_htmldump | ( | char * | filename | ) | [static] |
Definition at line 2858 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().
02859 { 02860 struct agi_command *command; 02861 char fullcmd[80]; 02862 FILE *htmlfile; 02863 02864 if (!(htmlfile = fopen(filename, "wt"))) 02865 return -1; 02866 02867 fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n"); 02868 fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n"); 02869 fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n"); 02870 02871 AST_RWLIST_RDLOCK(&agi_commands); 02872 AST_RWLIST_TRAVERSE(&agi_commands, command, list) { 02873 char *stringp, *tempstr; 02874 02875 if (!command->cmda[0]) /* end ? */ 02876 break; 02877 /* Hide commands that start with '_' */ 02878 if ((command->cmda[0])[0] == '_') 02879 continue; 02880 ast_join(fullcmd, sizeof(fullcmd), command->cmda); 02881 02882 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n"); 02883 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary); 02884 02885 stringp = command->usage; 02886 tempstr = strsep(&stringp, "\n"); 02887 02888 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">"); 02889 write_html_escaped(htmlfile, tempstr); 02890 fprintf(htmlfile, "</TD></TR>\n"); 02891 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n"); 02892 02893 while ((tempstr = strsep(&stringp, "\n")) != NULL) { 02894 write_html_escaped(htmlfile, tempstr); 02895 fprintf(htmlfile, "<BR>\n"); 02896 } 02897 fprintf(htmlfile, "</TD></TR>\n"); 02898 fprintf(htmlfile, "</TABLE></TD></TR>\n\n"); 02899 } 02900 AST_RWLIST_UNLOCK(&agi_commands); 02901 fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n"); 02902 fclose(htmlfile); 02903 return 0; 02904 }
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 3059 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 2303 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