#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_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 = { .handler = handle_cli_agi_dumphtml_deprecated , .summary = "Dumps a list of AGI commands in HTML format" ,__VA_ARGS__ } |
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_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 [] |
Definition in file res_agi.c.
#define AGI_BUF_INITSIZE 256 |
#define AGI_BUF_LEN 2048 |
#define AGI_BUF_SIZE 1024 |
Referenced by launch_asyncagi().
#define AGI_PORT 4573 |
#define AMI_BUF_SIZE 2048 |
Referenced by launch_asyncagi().
#define MAX_AGI_CONNECT 2000 |
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, chan, ast_channel::name, and s.
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, chan, ast_datastore::data, agi_cmd::entry, LOG_WARNING, and ast_channel::name.
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(), chan, 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 3010 of file res_agi.c.
References agi_exec_full(), ast_check_hangup(), and chan.
Referenced by deadagi_exec(), and load_module().
03011 { 03012 if (!ast_check_hangup(chan)) 03013 return agi_exec_full(chan, data, 0, 0); 03014 else 03015 return agi_exec_full(chan, data, 0, 1); 03016 }
static int agi_exec_full | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | enhanced, | |||
int | dead | |||
) | [static] |
Definition at line 2943 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, chan, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), run_agi(), and status.
Referenced by agi_exec(), and eagi_exec().
02944 { 02945 enum agi_result res; 02946 char buf[AGI_BUF_LEN] = "", *tmp = buf; 02947 int fds[2], efd = -1, pid; 02948 AST_DECLARE_APP_ARGS(args, 02949 AST_APP_ARG(arg)[MAX_ARGS]; 02950 ); 02951 AGI agi; 02952 02953 if (ast_strlen_zero(data)) { 02954 ast_log(LOG_WARNING, "AGI requires an argument (script)\n"); 02955 return -1; 02956 } 02957 if (dead) 02958 ast_debug(3, "Hungup channel detected, running agi in dead mode.\n"); 02959 ast_copy_string(buf, data, sizeof(buf)); 02960 memset(&agi, 0, sizeof(agi)); 02961 AST_STANDARD_APP_ARGS(args, tmp); 02962 args.argv[args.argc] = NULL; 02963 #if 0 02964 /* Answer if need be */ 02965 if (chan->_state != AST_STATE_UP) { 02966 if (ast_answer(chan)) 02967 return -1; 02968 } 02969 #endif 02970 res = launch_script(chan, args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid); 02971 /* Async AGI do not require run_agi(), so just proceed if normal AGI 02972 or Fast AGI are setup with success. */ 02973 if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) { 02974 int status = 0; 02975 agi.fd = fds[1]; 02976 agi.ctrl = fds[0]; 02977 agi.audio = efd; 02978 agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0; 02979 res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv); 02980 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */ 02981 if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status) 02982 res = AGI_RESULT_FAILURE; 02983 if (fds[1] != fds[0]) 02984 close(fds[1]); 02985 if (efd > -1) 02986 close(efd); 02987 } 02988 ast_safe_fork_cleanup(); 02989 02990 switch (res) { 02991 case AGI_RESULT_SUCCESS: 02992 case AGI_RESULT_SUCCESS_FAST: 02993 case AGI_RESULT_SUCCESS_ASYNC: 02994 pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS"); 02995 break; 02996 case AGI_RESULT_FAILURE: 02997 pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE"); 02998 break; 02999 case AGI_RESULT_NOTFOUND: 03000 pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND"); 03001 break; 03002 case AGI_RESULT_HANGUP: 03003 pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP"); 03004 return -1; 03005 } 03006 03007 return 0; 03008 }
static int agi_handle_command | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
char * | buf, | |||
int | dead | |||
) | [static] |
Definition at line 2564 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, chan, agi_command::dead, EVENT_FLAG_AGI, agi_state::fd, find_command(), agi_command::handler, manager_event, MAX_ARGS, agi_command::mod, ast_channel::name, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.
Referenced by launch_asyncagi(), and run_agi().
02565 { 02566 char *argv[MAX_ARGS]; 02567 int argc = MAX_ARGS, res; 02568 agi_command *c; 02569 const char *ami_res = "Unknown Result"; 02570 char *ami_cmd = ast_strdupa(buf); 02571 int command_id = ast_random(), resultcode = 200; 02572 02573 manager_event(EVENT_FLAG_AGI, "AGIExec", 02574 "SubEvent: Start\r\n" 02575 "Channel: %s\r\n" 02576 "CommandId: %d\r\n" 02577 "Command: %s\r\n", chan->name, command_id, ami_cmd); 02578 parse_args(buf, &argc, argv); 02579 if ((c = find_command(argv, 0)) && (!dead || (dead && c->dead))) { 02580 /* if this command wasnt registered by res_agi, be sure to usecount 02581 the module we are using */ 02582 if (c->mod != ast_module_info->self) 02583 ast_module_ref(c->mod); 02584 /* If the AGI command being executed is an actual application (using agi exec) 02585 the app field will be updated in pbx_exec via handle_exec */ 02586 if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC")) 02587 ast_cdr_setapp(chan->cdr, "AGI", buf); 02588 02589 res = c->handler(chan, agi, argc, argv); 02590 if (c->mod != ast_module_info->self) 02591 ast_module_unref(c->mod); 02592 switch (res) { 02593 case RESULT_SHOWUSAGE: ami_res = "Usage"; resultcode = 520; break; 02594 case RESULT_FAILURE: ami_res = "Failure"; resultcode = -1; break; 02595 case RESULT_SUCCESS: ami_res = "Success"; resultcode = 200; break; 02596 } 02597 manager_event(EVENT_FLAG_AGI, "AGIExec", 02598 "SubEvent: End\r\n" 02599 "Channel: %s\r\n" 02600 "CommandId: %d\r\n" 02601 "Command: %s\r\n" 02602 "ResultCode: %d\r\n" 02603 "Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res); 02604 switch(res) { 02605 case RESULT_SHOWUSAGE: 02606 ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n"); 02607 ast_agi_send(agi->fd, chan, "%s", c->usage); 02608 ast_agi_send(agi->fd, chan, "520 End of proper usage.\n"); 02609 break; 02610 case RESULT_FAILURE: 02611 /* They've already given the failure. We've been hung up on so handle this 02612 appropriately */ 02613 return -1; 02614 } 02615 } else if ((c = find_command(argv, 0))) { 02616 ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n"); 02617 manager_event(EVENT_FLAG_AGI, "AGIExec", 02618 "SubEvent: End\r\n" 02619 "Channel: %s\r\n" 02620 "CommandId: %d\r\n" 02621 "Command: %s\r\n" 02622 "ResultCode: 511\r\n" 02623 "Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd); 02624 } else { 02625 ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n"); 02626 manager_event(EVENT_FLAG_AGI, "AGIExec", 02627 "SubEvent: End\r\n" 02628 "Channel: %s\r\n" 02629 "CommandId: %d\r\n" 02630 "Command: %s\r\n" 02631 "ResultCode: 510\r\n" 02632 "Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd); 02633 } 02634 return 0; 02635 }
int ast_agi_register | ( | struct ast_module * | mod, | |
agi_command * | cmd | |||
) |
Definition at line 2369 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(), agi_command::list, LOG_WARNING, and agi_command::mod.
Referenced by ast_agi_register_multiple(), and load_module().
02370 { 02371 char fullcmd[80]; 02372 02373 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 02374 02375 if (!find_command(cmd->cmda,1)) { 02376 cmd->mod = mod; 02377 AST_RWLIST_WRLOCK(&agi_commands); 02378 AST_LIST_INSERT_TAIL(&agi_commands, cmd, list); 02379 AST_RWLIST_UNLOCK(&agi_commands); 02380 if (mod != ast_module_info->self) 02381 ast_module_ref(ast_module_info->self); 02382 ast_verb(2, "AGI Command '%s' registered\n",fullcmd); 02383 return 1; 02384 } else { 02385 ast_log(LOG_WARNING, "Command already registered!\n"); 02386 return 0; 02387 } 02388 }
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 2417 of file res_agi.c.
References ast_agi_register(), ast_agi_unregister(), and agi_command::mod.
Referenced by load_module().
02418 { 02419 unsigned int i, x = 0; 02420 02421 for (i = 0; i < len; i++) { 02422 if (ast_agi_register(mod, cmd + i) == 1) { 02423 x++; 02424 continue; 02425 } 02426 02427 /* registration failed, unregister everything 02428 that had been registered up to that point 02429 */ 02430 for (; x > 0; x--) { 02431 /* we are intentionally ignoring the 02432 result of ast_agi_unregister() here, 02433 but it should be safe to do so since 02434 we just registered these commands and 02435 the only possible way for unregistration 02436 to fail is if the command is not 02437 registered 02438 */ 02439 (void) ast_agi_unregister(mod, cmd + x - 1); 02440 } 02441 return -1; 02442 } 02443 02444 return 0; 02445 }
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, chan, and LOG_ERROR.
Referenced by agi_handle_command(), handle_answer(), 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 2390 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, agi_command::list, LOG_WARNING, and agi_command::mod.
Referenced by ast_agi_register_multiple(), ast_agi_unregister_multiple(), and unload_module().
02391 { 02392 struct agi_command *e; 02393 int unregistered = 0; 02394 char fullcmd[80]; 02395 02396 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 02397 02398 AST_RWLIST_WRLOCK(&agi_commands); 02399 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) { 02400 if (cmd == e) { 02401 AST_RWLIST_REMOVE_CURRENT(list); 02402 if (mod != ast_module_info->self) 02403 ast_module_unref(ast_module_info->self); 02404 unregistered=1; 02405 break; 02406 } 02407 } 02408 AST_RWLIST_TRAVERSE_SAFE_END; 02409 AST_RWLIST_UNLOCK(&agi_commands); 02410 if (unregistered) 02411 ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd); 02412 else 02413 ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd); 02414 return unregistered; 02415 }
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 2447 of file res_agi.c.
References ast_agi_unregister(), and agi_command::mod.
Referenced by unload_module().
02448 { 02449 unsigned int i; 02450 int res = 0; 02451 02452 for (i = 0; i < len; i++) { 02453 /* remember whether any of the unregistration 02454 attempts failed... there is no recourse if 02455 any of them do 02456 */ 02457 res |= ast_agi_unregister(mod, cmd + i); 02458 } 02459 02460 return res; 02461 }
static int deadagi_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3040 of file res_agi.c.
References agi_exec(), ast_log(), chan, and LOG_WARNING.
Referenced by load_module().
03041 { 03042 ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n"); 03043 return agi_exec(chan, data); 03044 }
static int eagi_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3018 of file res_agi.c.
References agi_exec_full(), ast_check_hangup(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), ast_set_read_format(), chan, LOG_ERROR, LOG_WARNING, ast_channel::name, and ast_channel::readformat.
Referenced by load_module().
03019 { 03020 int readformat, res; 03021 03022 if (ast_check_hangup(chan)) { 03023 ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n"); 03024 return 0; 03025 } 03026 readformat = chan->readformat; 03027 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 03028 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name); 03029 return -1; 03030 } 03031 res = agi_exec_full(chan, data, 1, 0); 03032 if (!res) { 03033 if (ast_set_read_format(chan, readformat)) { 03034 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat)); 03035 } 03036 } 03037 return res; 03038 }
static agi_command * find_command | ( | char * | cmds[], | |
int | exact | |||
) | [static] |
Definition at line 2463 of file res_agi.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, agi_command::list, and match().
02464 { 02465 int y, match; 02466 struct agi_command *e; 02467 02468 AST_RWLIST_RDLOCK(&agi_commands); 02469 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 02470 if (!e->cmda[0]) 02471 break; 02472 /* start optimistic */ 02473 match = 1; 02474 for (y = 0; match && cmds[y]; y++) { 02475 /* If there are no more words in the command (and we're looking for 02476 an exact match) or there is a difference between the two words, 02477 then this is not a match */ 02478 if (!e->cmda[y] && !exact) 02479 break; 02480 /* don't segfault if the next part of a command doesn't exist */ 02481 if (!e->cmda[y]) { 02482 AST_RWLIST_UNLOCK(&agi_commands); 02483 return NULL; 02484 } 02485 if (strcasecmp(e->cmda[y], cmds[y])) 02486 match = 0; 02487 } 02488 /* If more words are needed to complete the command then this is not 02489 a candidate (unless we're looking for a really inexact answer */ 02490 if ((exact > -1) && e->cmda[y]) 02491 match = 0; 02492 if (match) { 02493 AST_RWLIST_UNLOCK(&agi_commands); 02494 return e; 02495 } 02496 } 02497 AST_RWLIST_UNLOCK(&agi_commands); 02498 return NULL; 02499 }
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] |
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(), chan, ast_datastore::data, agi_cmd::entry, LOG_ERROR, and ast_channel::name.
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, chan, 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_autohangup | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1407 of file res_agi.c.
References ast_agi_send(), ast_channel_setwhentohangup_tv(), chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01408 { 01409 double timeout; 01410 struct timeval whentohangup = { 0, 0 }; 01411 01412 if (argc != 3) 01413 return RESULT_SHOWUSAGE; 01414 if (sscanf(argv[2], "%lf", &timeout) != 1) 01415 return RESULT_SHOWUSAGE; 01416 if (timeout < 0) 01417 timeout = 0; 01418 if (timeout) { 01419 whentohangup.tv_sec = timeout; 01420 whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0; 01421 } 01422 ast_channel_setwhentohangup_tv(chan, whentohangup); 01423 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01424 return RESULT_SUCCESS; 01425 }
static int handle_channelstatus | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1516 of file res_agi.c.
References ast_channel::_state, ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01517 { 01518 struct ast_channel *c; 01519 if (argc == 2) { 01520 /* no argument: supply info on the current channel */ 01521 ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state); 01522 return RESULT_SUCCESS; 01523 } else if (argc == 3) { 01524 /* one argument: look for info on the specified channel */ 01525 c = ast_get_channel_by_name_locked(argv[2]); 01526 if (c) { 01527 ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state); 01528 ast_channel_unlock(c); 01529 return RESULT_SUCCESS; 01530 } 01531 /* if we get this far no channel name matched the argument given */ 01532 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01533 return RESULT_SUCCESS; 01534 } else { 01535 return RESULT_SHOWUSAGE; 01536 } 01537 }
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_channel::name, 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 1681 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.
01682 { 01683 switch (cmd) { 01684 case CLI_INIT: 01685 e->command = "agi set debug [on|off]"; 01686 e->usage = 01687 "Usage: agi set debug [on|off]\n" 01688 " Enables/disables dumping of AGI transactions for\n" 01689 " debugging purposes.\n"; 01690 return NULL; 01691 01692 case CLI_GENERATE: 01693 return NULL; 01694 } 01695 01696 if (a->argc != e->args) 01697 return CLI_SHOWUSAGE; 01698 01699 if (strncasecmp(a->argv[3], "off", 3) == 0) { 01700 agidebug = 0; 01701 } else if (strncasecmp(a->argv[3], "on", 2) == 0) { 01702 agidebug = 1; 01703 } else { 01704 return CLI_SHOWUSAGE; 01705 } 01706 ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis"); 01707 return CLI_SUCCESS; 01708 }
static char* handle_cli_agi_dump_html | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2919 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().
02920 { 02921 switch (cmd) { 02922 case CLI_INIT: 02923 e->command = "agi dump html"; 02924 e->usage = 02925 "Usage: agi dump html <filename>\n" 02926 " Dumps the AGI command list in HTML format to the given\n" 02927 " file.\n"; 02928 return NULL; 02929 case CLI_GENERATE: 02930 return NULL; 02931 } 02932 if (a->argc != e->args + 1) 02933 return CLI_SHOWUSAGE; 02934 02935 if (write_htmldump(a->argv[e->args]) < 0) { 02936 ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]); 02937 return CLI_SHOWUSAGE; 02938 } 02939 ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]); 02940 return CLI_SUCCESS; 02941 }
static char* handle_cli_agi_dumphtml_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2895 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().
02896 { 02897 switch (cmd) { 02898 case CLI_INIT: 02899 e->command = "agi dumphtml"; 02900 e->usage = 02901 "Usage: agi dumphtml <filename>\n" 02902 " Dumps the AGI command list in HTML format to the given\n" 02903 " file.\n"; 02904 return NULL; 02905 case CLI_GENERATE: 02906 return NULL; 02907 } 02908 if (a->argc < e->args + 1) 02909 return CLI_SHOWUSAGE; 02910 02911 if (write_htmldump(a->argv[2]) < 0) { 02912 ast_cli(a->fd, "Could not create file '%s'\n", a->argv[2]); 02913 return CLI_SHOWUSAGE; 02914 } 02915 ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[2]); 02916 return CLI_SUCCESS; 02917 }
static char* handle_cli_agi_show | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2779 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.
02780 { 02781 struct agi_command *command; 02782 char fullcmd[80]; 02783 02784 switch (cmd) { 02785 case CLI_INIT: 02786 e->command = "agi show"; 02787 e->usage = 02788 "Usage: agi show [topic]\n" 02789 " When called with a topic as an argument, displays usage\n" 02790 " information on the given command. If called without a\n" 02791 " topic, it provides a list of AGI commands.\n"; 02792 case CLI_GENERATE: 02793 return NULL; 02794 } 02795 if (a->argc < e->args) 02796 return CLI_SHOWUSAGE; 02797 if (a->argc > e->args) { 02798 command = find_command(a->argv + e->args, 1); 02799 if (command) { 02800 ast_cli(a->fd, "%s", command->usage); 02801 ast_cli(a->fd, " Runs Dead : %s\n", command->dead ? "Yes" : "No"); 02802 } else { 02803 if (find_command(a->argv + e->args, -1)) { 02804 return help_workhorse(a->fd, a->argv + e->args); 02805 } else { 02806 ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args); 02807 ast_cli(a->fd, "No such command '%s'.\n", fullcmd); 02808 } 02809 } 02810 } else { 02811 return help_workhorse(a->fd, NULL); 02812 } 02813 return CLI_SUCCESS; 02814 }
static int handle_controlstreamfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 889 of file res_agi.c.
References ast_agi_send(), ast_control_streamfile(), ast_strlen_zero(), chan, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, skipms, and stop.
00890 { 00891 int res = 0, skipms = 3000; 00892 char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */ 00893 00894 if (argc < 5 || argc > 9) { 00895 return RESULT_SHOWUSAGE; 00896 } 00897 00898 if (!ast_strlen_zero(argv[4])) { 00899 stop = argv[4]; 00900 } 00901 00902 if ((argc > 5) && (sscanf(argv[5], "%d", &skipms) != 1)) { 00903 return RESULT_SHOWUSAGE; 00904 } 00905 00906 if (argc > 6 && !ast_strlen_zero(argv[6])) { 00907 fwd = argv[6]; 00908 } 00909 00910 if (argc > 7 && !ast_strlen_zero(argv[7])) { 00911 rev = argv[7]; 00912 } 00913 00914 if (argc > 8 && !ast_strlen_zero(argv[8])) { 00915 suspend = argv[8]; 00916 } 00917 00918 res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL); 00919 00920 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00921 00922 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00923 }
static int handle_dbdel | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1655 of file res_agi.c.
References ast_agi_send(), ast_db_del(), chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01656 { 01657 int res; 01658 01659 if (argc != 4) 01660 return RESULT_SHOWUSAGE; 01661 res = ast_db_del(argv[2], argv[3]); 01662 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01663 return RESULT_SUCCESS; 01664 }
static int handle_dbdeltree | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1666 of file res_agi.c.
References ast_agi_send(), ast_db_deltree(), chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01667 { 01668 int res; 01669 01670 if ((argc < 3) || (argc > 4)) 01671 return RESULT_SHOWUSAGE; 01672 if (argc == 4) 01673 res = ast_db_deltree(argv[2], argv[3]); 01674 else 01675 res = ast_db_deltree(argv[2], NULL); 01676 01677 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01678 return RESULT_SUCCESS; 01679 }
static int handle_dbget | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1611 of file res_agi.c.
References ast_agi_send(), ast_db_get(), ast_free, ast_str_create(), ast_str_make_space(), buf, chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01612 { 01613 int res; 01614 struct ast_str *buf; 01615 01616 if (argc != 4) 01617 return RESULT_SHOWUSAGE; 01618 01619 if (!(buf = ast_str_create(16))) { 01620 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01621 return RESULT_SUCCESS; 01622 } 01623 01624 do { 01625 res = ast_db_get(argv[2], argv[3], buf->str, buf->len); 01626 buf->used = strlen(buf->str); 01627 if (buf->used < buf->len - 1) { 01628 break; 01629 } 01630 if (ast_str_make_space(&buf, buf->len * 2)) { 01631 break; 01632 } 01633 } while (1); 01634 01635 if (res) 01636 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01637 else 01638 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf->str); 01639 01640 ast_free(buf); 01641 return RESULT_SUCCESS; 01642 }
static int handle_dbput | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1644 of file res_agi.c.
References ast_agi_send(), ast_db_put(), chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01645 { 01646 int res; 01647 01648 if (argc != 5) 01649 return RESULT_SHOWUSAGE; 01650 res = ast_db_put(argv[2], argv[3], argv[4]); 01651 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01652 return RESULT_SUCCESS; 01653 }
static int handle_exec | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1454 of file res_agi.c.
References ast_agi_send(), ast_compat_res_agi, ast_log(), ast_masq_park_call(), ast_strlen_zero(), ast_verb, chan, agi_state::fd, LOG_WARNING, PARK_APP_NAME, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.
01455 { 01456 int res; 01457 struct ast_app *app_to_exec; 01458 01459 if (argc < 2) 01460 return RESULT_SHOWUSAGE; 01461 01462 ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]); 01463 01464 if ((app_to_exec = pbx_findapp(argv[1]))) { 01465 if(!strcasecmp(argv[1], PARK_APP_NAME)) { 01466 ast_masq_park_call(chan, NULL, 0, NULL); 01467 } 01468 if (ast_compat_res_agi && !ast_strlen_zero(argv[2])) { 01469 char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr, *vptr; 01470 for (cptr = compat, vptr = argv[2]; *vptr; vptr++) { 01471 if (*vptr == ',') { 01472 *cptr++ = '\\'; 01473 *cptr++ = ','; 01474 } else if (*vptr == '|') { 01475 *cptr++ = ','; 01476 } else { 01477 *cptr++ = *vptr; 01478 } 01479 } 01480 *cptr = '\0'; 01481 res = pbx_exec(chan, app_to_exec, compat); 01482 } else { 01483 res = pbx_exec(chan, app_to_exec, argv[2]); 01484 } 01485 } else { 01486 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]); 01487 res = -2; 01488 } 01489 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01490 01491 /* Even though this is wrong, users are depending upon this result. */ 01492 return res; 01493 }
static int handle_getdata | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1167 of file res_agi.c.
References ast_agi_send(), ast_app_getdata_full(), agi_state::audio, chan, agi_state::ctrl, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01168 { 01169 int res, max, timeout; 01170 char data[1024]; 01171 01172 if (argc < 3) 01173 return RESULT_SHOWUSAGE; 01174 if (argc >= 4) 01175 timeout = atoi(argv[3]); 01176 else 01177 timeout = 0; 01178 if (argc >= 5) 01179 max = atoi(argv[4]); 01180 else 01181 max = 1024; 01182 res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl); 01183 if (res == 2) /* New command */ 01184 return RESULT_SUCCESS; 01185 else if (res == 1) 01186 ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data); 01187 else if (res < 0 ) 01188 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01189 else 01190 ast_agi_send(agi->fd, chan, "200 result=%s\n", data); 01191 return RESULT_SUCCESS; 01192 }
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 975 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, chan, agi_state::ctrl, ast_pbx::dtimeoutms, agi_state::fd, ast_channel::language, LOG_WARNING, ast_channel::pbx, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.
00976 { 00977 int res, vres; 00978 struct ast_filestream *fs, *vfs; 00979 long sample_offset = 0, max_length; 00980 int timeout = 0; 00981 char *edigits = ""; 00982 00983 if ( argc < 4 || argc > 5 ) 00984 return RESULT_SHOWUSAGE; 00985 00986 if ( argv[3] ) 00987 edigits = argv[3]; 00988 00989 if ( argc == 5 ) 00990 timeout = atoi(argv[4]); 00991 else if (chan->pbx->dtimeoutms) { 00992 /* by default dtimeout is set to 5sec */ 00993 timeout = chan->pbx->dtimeoutms; /* in msec */ 00994 } 00995 00996 if (!(fs = ast_openstream(chan, argv[2], chan->language))) { 00997 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset); 00998 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]); 00999 return RESULT_SUCCESS; 01000 } 01001 01002 if ((vfs = ast_openvstream(chan, argv[2], chan->language))) 01003 ast_debug(1, "Ooh, found a video stream, too\n"); 01004 01005 ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout); 01006 01007 ast_seekstream(fs, 0, SEEK_END); 01008 max_length = ast_tellstream(fs); 01009 ast_seekstream(fs, sample_offset, SEEK_SET); 01010 res = ast_applystream(chan, fs); 01011 if (vfs) 01012 vres = ast_applystream(chan, vfs); 01013 ast_playstream(fs); 01014 if (vfs) 01015 ast_playstream(vfs); 01016 01017 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 01018 /* this is to check for if ast_waitstream closed the stream, we probably are at 01019 * the end of the stream, return that amount, else check for the amount */ 01020 sample_offset = (chan->stream)?ast_tellstream(fs):max_length; 01021 ast_stopstream(chan); 01022 if (res == 1) { 01023 /* Stop this command, don't print a result line, as there is a new command */ 01024 return RESULT_SUCCESS; 01025 } 01026 01027 /* If the user didnt press a key, wait for digitTimeout*/ 01028 if (res == 0 ) { 01029 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl); 01030 /* Make sure the new result is in the escape digits of the GET OPTION */ 01031 if ( !strchr(edigits,res) ) 01032 res=0; 01033 } 01034 01035 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset); 01036 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01037 }
static int handle_getvariable | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1548 of file res_agi.c.
References ast_agi_send(), ast_func_read(), ast_strlen_zero(), chan, agi_state::fd, pbx_retrieve_variable(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01549 { 01550 char *ret; 01551 char tempstr[1024]; 01552 01553 if (argc != 3) 01554 return RESULT_SHOWUSAGE; 01555 01556 /* check if we want to execute an ast_custom_function */ 01557 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) { 01558 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr; 01559 } else { 01560 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL); 01561 } 01562 01563 if (ret) 01564 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret); 01565 else 01566 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01567 01568 return RESULT_SUCCESS; 01569 }
static int handle_getvariablefull | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1571 of file res_agi.c.
References ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), chan, agi_state::fd, pbx_substitute_variables_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01572 { 01573 char tmp[4096]; 01574 struct ast_channel *chan2=NULL; 01575 01576 if ((argc != 4) && (argc != 5)) 01577 return RESULT_SHOWUSAGE; 01578 if (argc == 5) { 01579 chan2 = ast_get_channel_by_name_locked(argv[4]); 01580 } else { 01581 chan2 = chan; 01582 } 01583 if (chan2) { 01584 pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1); 01585 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp); 01586 } else { 01587 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01588 } 01589 if (chan2 && (chan2 != chan)) 01590 ast_channel_unlock(chan2); 01591 return RESULT_SUCCESS; 01592 }
static int handle_hangup | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1427 of file res_agi.c.
References ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01428 { 01429 struct ast_channel *c; 01430 01431 if (argc == 1) { 01432 /* no argument: hangup the current channel */ 01433 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT); 01434 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01435 return RESULT_SUCCESS; 01436 } else if (argc == 2) { 01437 /* one argument: look for info on the specified channel */ 01438 c = ast_get_channel_by_name_locked(argv[1]); 01439 if (c) { 01440 /* we have a matching channel */ 01441 ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT); 01442 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01443 ast_channel_unlock(c); 01444 return RESULT_SUCCESS; 01445 } 01446 /* if we get this far no channel name matched the argument given */ 01447 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01448 return RESULT_SUCCESS; 01449 } else { 01450 return RESULT_SHOWUSAGE; 01451 } 01452 }
static int handle_noop | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | arg, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1710 of file res_agi.c.
References ast_agi_send(), chan, agi_state::fd, and RESULT_SUCCESS.
01711 { 01712 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01713 return RESULT_SUCCESS; 01714 }
static int handle_recordfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1230 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(), chan, f, agi_state::fd, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, THRESHOLD_SILENCE, and ast_dsp::totalsilence.
01231 { 01232 struct ast_filestream *fs; 01233 struct ast_frame *f; 01234 struct timeval start; 01235 long sample_offset = 0; 01236 int res = 0; 01237 int ms; 01238 01239 struct ast_dsp *sildet=NULL; /* silence detector dsp */ 01240 int totalsilence = 0; 01241 int dspsilence = 0; 01242 int silence = 0; /* amount of silence to allow */ 01243 int gotsilence = 0; /* did we timeout for silence? */ 01244 char *silencestr = NULL; 01245 int rfmt = 0; 01246 01247 /* XXX EAGI FIXME XXX */ 01248 01249 if (argc < 6) 01250 return RESULT_SHOWUSAGE; 01251 if (sscanf(argv[5], "%d", &ms) != 1) 01252 return RESULT_SHOWUSAGE; 01253 01254 if (argc > 6) 01255 silencestr = strchr(argv[6],'s'); 01256 if ((argc > 7) && (!silencestr)) 01257 silencestr = strchr(argv[7],'s'); 01258 if ((argc > 8) && (!silencestr)) 01259 silencestr = strchr(argv[8],'s'); 01260 01261 if (silencestr) { 01262 if (strlen(silencestr) > 2) { 01263 if ((silencestr[0] == 's') && (silencestr[1] == '=')) { 01264 silencestr++; 01265 silencestr++; 01266 if (silencestr) 01267 silence = atoi(silencestr); 01268 if (silence > 0) 01269 silence *= 1000; 01270 } 01271 } 01272 } 01273 01274 if (silence > 0) { 01275 rfmt = chan->readformat; 01276 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 01277 if (res < 0) { 01278 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 01279 return -1; 01280 } 01281 sildet = ast_dsp_new(); 01282 if (!sildet) { 01283 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 01284 return -1; 01285 } 01286 ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE)); 01287 } 01288 01289 /* backward compatibility, if no offset given, arg[6] would have been 01290 * caught below and taken to be a beep, else if it is a digit then it is a 01291 * offset */ 01292 if ((argc >6) && (sscanf(argv[6], "%ld", &sample_offset) != 1) && (!strchr(argv[6], '='))) 01293 res = ast_streamfile(chan, "beep", chan->language); 01294 01295 if ((argc > 7) && (!strchr(argv[7], '='))) 01296 res = ast_streamfile(chan, "beep", chan->language); 01297 01298 if (!res) 01299 res = ast_waitstream(chan, argv[4]); 01300 if (res) { 01301 ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset); 01302 } else { 01303 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE); 01304 if (!fs) { 01305 res = -1; 01306 ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res); 01307 if (sildet) 01308 ast_dsp_free(sildet); 01309 return RESULT_FAILURE; 01310 } 01311 01312 /* Request a video update */ 01313 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 01314 01315 chan->stream = fs; 01316 ast_applystream(chan,fs); 01317 /* really should have checks */ 01318 ast_seekstream(fs, sample_offset, SEEK_SET); 01319 ast_truncstream(fs); 01320 01321 start = ast_tvnow(); 01322 while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) { 01323 res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start)); 01324 if (res < 0) { 01325 ast_closestream(fs); 01326 ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset); 01327 if (sildet) 01328 ast_dsp_free(sildet); 01329 return RESULT_FAILURE; 01330 } 01331 f = ast_read(chan); 01332 if (!f) { 01333 ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset); 01334 ast_closestream(fs); 01335 if (sildet) 01336 ast_dsp_free(sildet); 01337 return RESULT_FAILURE; 01338 } 01339 switch(f->frametype) { 01340 case AST_FRAME_DTMF: 01341 if (strchr(argv[4], f->subclass)) { 01342 /* This is an interrupting chracter, so rewind to chop off any small 01343 amount of DTMF that may have been recorded 01344 */ 01345 ast_stream_rewind(fs, 200); 01346 ast_truncstream(fs); 01347 sample_offset = ast_tellstream(fs); 01348 ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset); 01349 ast_closestream(fs); 01350 ast_frfree(f); 01351 if (sildet) 01352 ast_dsp_free(sildet); 01353 return RESULT_SUCCESS; 01354 } 01355 break; 01356 case AST_FRAME_VOICE: 01357 ast_writestream(fs, f); 01358 /* this is a safe place to check progress since we know that fs 01359 * is valid after a write, and it will then have our current 01360 * location */ 01361 sample_offset = ast_tellstream(fs); 01362 if (silence > 0) { 01363 dspsilence = 0; 01364 ast_dsp_silence(sildet, f, &dspsilence); 01365 if (dspsilence) { 01366 totalsilence = dspsilence; 01367 } else { 01368 totalsilence = 0; 01369 } 01370 if (totalsilence > silence) { 01371 /* Ended happily with silence */ 01372 gotsilence = 1; 01373 break; 01374 } 01375 } 01376 break; 01377 case AST_FRAME_VIDEO: 01378 ast_writestream(fs, f); 01379 default: 01380 /* Ignore all other frames */ 01381 break; 01382 } 01383 ast_frfree(f); 01384 if (gotsilence) 01385 break; 01386 } 01387 01388 if (gotsilence) { 01389 ast_stream_rewind(fs, silence-1000); 01390 ast_truncstream(fs); 01391 sample_offset = ast_tellstream(fs); 01392 } 01393 ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset); 01394 ast_closestream(fs); 01395 } 01396 01397 if (silence > 0) { 01398 res = ast_set_read_format(chan, rfmt); 01399 if (res) 01400 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 01401 ast_dsp_free(sildet); 01402 } 01403 01404 return RESULT_SUCCESS; 01405 }
static int handle_recvchar | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 809 of file res_agi.c.
References ast_agi_send(), ast_recvchar(), chan, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00810 { 00811 int res; 00812 00813 if (argc != 3) 00814 return RESULT_SHOWUSAGE; 00815 00816 res = ast_recvchar(chan,atoi(argv[2])); 00817 if (res == 0) { 00818 ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res); 00819 return RESULT_SUCCESS; 00820 } 00821 if (res > 0) { 00822 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00823 return RESULT_SUCCESS; 00824 } 00825 ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res); 00826 return RESULT_FAILURE; 00827 }
static int handle_recvtext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 829 of file res_agi.c.
References ast_agi_send(), ast_free, ast_recvtext(), buf, chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00830 { 00831 char *buf; 00832 00833 if (argc != 3) 00834 return RESULT_SHOWUSAGE; 00835 00836 buf = ast_recvtext(chan, atoi(argv[2])); 00837 if (buf) { 00838 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf); 00839 ast_free(buf); 00840 } else { 00841 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 00842 } 00843 return RESULT_SUCCESS; 00844 }
static int handle_sayalpha | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1075 of file res_agi.c.
References ast_agi_send(), ast_say_character_str_full, agi_state::audio, chan, agi_state::ctrl, agi_state::fd, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01076 { 01077 int res; 01078 01079 if (argc != 4) 01080 return RESULT_SHOWUSAGE; 01081 01082 res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01083 if (res == 1) /* New command */ 01084 return RESULT_SUCCESS; 01085 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01086 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01087 }
static int handle_saydate | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1089 of file res_agi.c.
References ast_agi_send(), ast_say_date, chan, agi_state::fd, ast_channel::language, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01090 { 01091 int res, num; 01092 01093 if (argc != 4) 01094 return RESULT_SHOWUSAGE; 01095 if (sscanf(argv[2], "%d", &num) != 1) 01096 return RESULT_SHOWUSAGE; 01097 res = ast_say_date(chan, num, argv[3], chan->language); 01098 if (res == 1) 01099 return RESULT_SUCCESS; 01100 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01101 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01102 }
static int handle_saydatetime | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1119 of file res_agi.c.
References ast_agi_send(), ast_get_time_t(), ast_say_date_with_format, ast_strlen_zero(), chan, agi_state::fd, format, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01120 { 01121 int res = 0; 01122 time_t unixtime; 01123 char *format, *zone = NULL; 01124 01125 if (argc < 4) 01126 return RESULT_SHOWUSAGE; 01127 01128 if (argc > 4) { 01129 format = argv[4]; 01130 } else { 01131 /* XXX this doesn't belong here, but in the 'say' module */ 01132 if (!strcasecmp(chan->language, "de")) { 01133 format = "A dBY HMS"; 01134 } else { 01135 format = "ABdY 'digits/at' IMp"; 01136 } 01137 } 01138 01139 if (argc > 5 && !ast_strlen_zero(argv[5])) 01140 zone = argv[5]; 01141 01142 if (ast_get_time_t(argv[2], &unixtime, 0, NULL)) 01143 return RESULT_SHOWUSAGE; 01144 01145 res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone); 01146 if (res == 1) 01147 return RESULT_SUCCESS; 01148 01149 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01150 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01151 }
static int handle_saydigits | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1059 of file res_agi.c.
References ast_agi_send(), ast_say_digit_str_full, agi_state::audio, chan, agi_state::ctrl, agi_state::fd, ast_channel::language, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01060 { 01061 int res, num; 01062 01063 if (argc != 4) 01064 return RESULT_SHOWUSAGE; 01065 if (sscanf(argv[2], "%d", &num) != 1) 01066 return RESULT_SHOWUSAGE; 01067 01068 res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01069 if (res == 1) /* New command */ 01070 return RESULT_SUCCESS; 01071 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01072 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01073 }
static int handle_saynumber | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Say number in various language syntaxes.
Definition at line 1044 of file res_agi.c.
References ast_agi_send(), ast_say_number_full, agi_state::audio, chan, agi_state::ctrl, agi_state::fd, ast_channel::language, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01045 { 01046 int res, num; 01047 01048 if (argc < 4 || argc > 5) 01049 return RESULT_SHOWUSAGE; 01050 if (sscanf(argv[2], "%d", &num) != 1) 01051 return RESULT_SHOWUSAGE; 01052 res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl); 01053 if (res == 1) 01054 return RESULT_SUCCESS; 01055 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01056 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01057 }
static int handle_sayphonetic | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1153 of file res_agi.c.
References ast_agi_send(), ast_say_phonetic_str_full, agi_state::audio, chan, agi_state::ctrl, agi_state::fd, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01154 { 01155 int res; 01156 01157 if (argc != 4) 01158 return RESULT_SHOWUSAGE; 01159 01160 res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01161 if (res == 1) /* New command */ 01162 return RESULT_SUCCESS; 01163 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01164 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01165 }
static int handle_saytime | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1104 of file res_agi.c.
References ast_agi_send(), ast_say_time, chan, agi_state::fd, ast_channel::language, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01105 { 01106 int res, num; 01107 01108 if (argc != 4) 01109 return RESULT_SHOWUSAGE; 01110 if (sscanf(argv[2], "%d", &num) != 1) 01111 return RESULT_SHOWUSAGE; 01112 res = ast_say_time(chan, num, argv[3], chan->language); 01113 if (res == 1) 01114 return RESULT_SUCCESS; 01115 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01116 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01117 }
static int handle_sendimage | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 873 of file res_agi.c.
References ast_agi_send(), ast_check_hangup(), ast_send_image(), chan, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00874 { 00875 int res; 00876 00877 if (argc != 3) { 00878 return RESULT_SHOWUSAGE; 00879 } 00880 00881 res = ast_send_image(chan, argv[2]); 00882 if (!ast_check_hangup(chan)) { 00883 res = 0; 00884 } 00885 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00886 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00887 }
static int handle_sendtext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 790 of file res_agi.c.
References ast_agi_send(), ast_sendtext(), chan, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00791 { 00792 int res; 00793 00794 if (argc != 3) 00795 return RESULT_SHOWUSAGE; 00796 00797 /* At the moment, the parser (perhaps broken) returns with 00798 the last argument PLUS the newline at the end of the input 00799 buffer. This probably needs to be fixed, but I wont do that 00800 because other stuff may break as a result. The right way 00801 would probably be to strip off the trailing newline before 00802 parsing, then here, add a newline at the end of the string 00803 before sending it to ast_sendtext --DUDE */ 00804 res = ast_sendtext(chan, argv[2]); 00805 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00806 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00807 }
static int handle_setcallerid | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1495 of file res_agi.c.
References ast_agi_send(), ast_callerid_parse(), ast_copy_string(), ast_set_callerid(), ast_shrink_phone_number(), chan, agi_state::fd, and RESULT_SUCCESS.
01496 { 01497 char tmp[256]=""; 01498 char *l = NULL, *n = NULL; 01499 01500 if (argv[2]) { 01501 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01502 ast_callerid_parse(tmp, &n, &l); 01503 if (l) 01504 ast_shrink_phone_number(l); 01505 else 01506 l = ""; 01507 if (!n) 01508 n = ""; 01509 ast_set_callerid(chan, l, n, NULL); 01510 } 01511 01512 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01513 return RESULT_SUCCESS; 01514 }
static int handle_setcontext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1194 of file res_agi.c.
References ast_agi_send(), ast_copy_string(), chan, ast_channel::context, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01195 { 01196 01197 if (argc != 3) 01198 return RESULT_SHOWUSAGE; 01199 ast_copy_string(chan->context, argv[2], sizeof(chan->context)); 01200 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01201 return RESULT_SUCCESS; 01202 }
static int handle_setextension | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1204 of file res_agi.c.
References ast_agi_send(), ast_copy_string(), chan, ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01205 { 01206 if (argc != 3) 01207 return RESULT_SHOWUSAGE; 01208 ast_copy_string(chan->exten, argv[2], sizeof(chan->exten)); 01209 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01210 return RESULT_SUCCESS; 01211 }
static int handle_setmusic | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1716 of file res_agi.c.
References ast_agi_send(), ast_moh_start(), ast_moh_stop(), chan, agi_state::fd, and RESULT_SUCCESS.
01717 { 01718 if (!strncasecmp(argv[2], "on", 2)) 01719 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL); 01720 else if (!strncasecmp(argv[2], "off", 3)) 01721 ast_moh_stop(chan); 01722 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01723 return RESULT_SUCCESS; 01724 }
static int handle_setpriority | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1213 of file res_agi.c.
References ast_agi_send(), ast_explicit_goto(), ast_findlabel_extension(), chan, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01214 { 01215 int pri; 01216 01217 if (argc != 3) 01218 return RESULT_SHOWUSAGE; 01219 01220 if (sscanf(argv[2], "%d", &pri) != 1) { 01221 if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1) 01222 return RESULT_SHOWUSAGE; 01223 } 01224 01225 ast_explicit_goto(chan, NULL, NULL, pri); 01226 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01227 return RESULT_SUCCESS; 01228 }
static int handle_setvariable | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1539 of file res_agi.c.
References ast_agi_send(), chan, agi_state::fd, pbx_builtin_setvar_helper(), and RESULT_SUCCESS.
01540 { 01541 if (argv[3]) 01542 pbx_builtin_setvar_helper(chan, argv[2], argv[3]); 01543 01544 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01545 return RESULT_SUCCESS; 01546 }
static int handle_speechactivategrammar | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1809 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_activate(), chan, agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01810 { 01811 if (argc != 4) 01812 return RESULT_SHOWUSAGE; 01813 01814 if (!agi->speech) { 01815 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01816 return RESULT_SUCCESS; 01817 } 01818 01819 if (ast_speech_grammar_activate(agi->speech, argv[3])) 01820 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01821 else 01822 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01823 01824 return RESULT_SUCCESS; 01825 }
static int handle_speechcreate | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1726 of file res_agi.c.
References ast_agi_send(), AST_FORMAT_SLINEAR, ast_speech_new(), chan, agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
01727 { 01728 /* If a structure already exists, return an error */ 01729 if (agi->speech) { 01730 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01731 return RESULT_SUCCESS; 01732 } 01733 01734 if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR))) 01735 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01736 else 01737 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01738 01739 return RESULT_SUCCESS; 01740 }
static int handle_speechdeactivategrammar | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1827 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_deactivate(), chan, agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01828 { 01829 if (argc != 4) 01830 return RESULT_SHOWUSAGE; 01831 01832 if (!agi->speech) { 01833 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01834 return RESULT_SUCCESS; 01835 } 01836 01837 if (ast_speech_grammar_deactivate(agi->speech, argv[3])) 01838 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01839 else 01840 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01841 01842 return RESULT_SUCCESS; 01843 }
static int handle_speechdestroy | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1760 of file res_agi.c.
References ast_agi_send(), ast_speech_destroy(), chan, agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
01761 { 01762 if (agi->speech) { 01763 ast_speech_destroy(agi->speech); 01764 agi->speech = NULL; 01765 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01766 } else { 01767 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01768 } 01769 01770 return RESULT_SUCCESS; 01771 }
static int handle_speechloadgrammar | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1773 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_load(), chan, agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01774 { 01775 if (argc != 5) 01776 return RESULT_SHOWUSAGE; 01777 01778 if (!agi->speech) { 01779 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01780 return RESULT_SUCCESS; 01781 } 01782 01783 if (ast_speech_grammar_load(agi->speech, argv[3], argv[4])) 01784 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01785 else 01786 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01787 01788 return RESULT_SUCCESS; 01789 }
static int handle_speechrecognize | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1864 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, chan, ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, ast_speech_result::grammar, ast_channel::language, ast_speech::lock, 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.
01865 { 01866 struct ast_speech *speech = agi->speech; 01867 char *prompt, dtmf = 0, tmp[4096] = "", *buf = tmp; 01868 int timeout = 0, offset = 0, old_read_format = 0, res = 0, i = 0; 01869 long current_offset = 0; 01870 const char *reason = NULL; 01871 struct ast_frame *fr = NULL; 01872 struct ast_speech_result *result = NULL; 01873 size_t left = sizeof(tmp); 01874 time_t start = 0, current; 01875 01876 if (argc < 4) 01877 return RESULT_SHOWUSAGE; 01878 01879 if (!speech) { 01880 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01881 return RESULT_SUCCESS; 01882 } 01883 01884 prompt = argv[2]; 01885 timeout = atoi(argv[3]); 01886 01887 /* If offset is specified then convert from text to integer */ 01888 if (argc == 5) 01889 offset = atoi(argv[4]); 01890 01891 /* We want frames coming in signed linear */ 01892 old_read_format = chan->readformat; 01893 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 01894 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01895 return RESULT_SUCCESS; 01896 } 01897 01898 /* Setup speech structure */ 01899 if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) { 01900 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 01901 ast_speech_start(speech); 01902 } 01903 01904 /* Start playing prompt */ 01905 speech_streamfile(chan, prompt, chan->language, offset); 01906 01907 /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */ 01908 while (ast_strlen_zero(reason)) { 01909 /* Run scheduled items */ 01910 ast_sched_runq(chan->sched); 01911 01912 /* See maximum time of waiting */ 01913 if ((res = ast_sched_wait(chan->sched)) < 0) 01914 res = 1000; 01915 01916 /* Wait for frame */ 01917 if (ast_waitfor(chan, res) > 0) { 01918 if (!(fr = ast_read(chan))) { 01919 reason = "hangup"; 01920 break; 01921 } 01922 } 01923 01924 /* Perform timeout check */ 01925 if ((timeout > 0) && (start > 0)) { 01926 time(¤t); 01927 if ((current - start) >= timeout) { 01928 reason = "timeout"; 01929 if (fr) 01930 ast_frfree(fr); 01931 break; 01932 } 01933 } 01934 01935 /* Check the speech structure for any changes */ 01936 ast_mutex_lock(&speech->lock); 01937 01938 /* See if we need to quiet the audio stream playback */ 01939 if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) { 01940 current_offset = ast_tellstream(chan->stream); 01941 ast_stopstream(chan); 01942 ast_clear_flag(speech, AST_SPEECH_QUIET); 01943 } 01944 01945 /* Check each state */ 01946 switch (speech->state) { 01947 case AST_SPEECH_STATE_READY: 01948 /* If the stream is done, start timeout calculation */ 01949 if ((timeout > 0) && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) { 01950 ast_stopstream(chan); 01951 time(&start); 01952 } 01953 /* Write audio frame data into speech engine if possible */ 01954 if (fr && fr->frametype == AST_FRAME_VOICE) 01955 ast_speech_write(speech, fr->data.ptr, fr->datalen); 01956 break; 01957 case AST_SPEECH_STATE_WAIT: 01958 /* Cue waiting sound if not already playing */ 01959 if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) { 01960 ast_stopstream(chan); 01961 /* If a processing sound exists, or is not none - play it */ 01962 if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none")) 01963 speech_streamfile(chan, speech->processing_sound, chan->language, 0); 01964 } 01965 break; 01966 case AST_SPEECH_STATE_DONE: 01967 /* Get the results */ 01968 speech->results = ast_speech_results_get(speech); 01969 /* Change state to not ready */ 01970 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 01971 reason = "speech"; 01972 break; 01973 default: 01974 break; 01975 } 01976 ast_mutex_unlock(&speech->lock); 01977 01978 /* Check frame for DTMF or hangup */ 01979 if (fr) { 01980 if (fr->frametype == AST_FRAME_DTMF) { 01981 reason = "dtmf"; 01982 dtmf = fr->subclass; 01983 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_HANGUP) { 01984 reason = "hangup"; 01985 } 01986 ast_frfree(fr); 01987 } 01988 } 01989 01990 if (!strcasecmp(reason, "speech")) { 01991 /* Build string containing speech results */ 01992 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) { 01993 /* Build result string */ 01994 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); 01995 /* Increment result count */ 01996 i++; 01997 } 01998 /* Print out */ 01999 ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp); 02000 } else if (!strcasecmp(reason, "dtmf")) { 02001 ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset); 02002 } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) { 02003 ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset); 02004 } else { 02005 ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset); 02006 } 02007 02008 return RESULT_SUCCESS; 02009 }
static int handle_speechset | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1742 of file res_agi.c.
References ast_agi_send(), ast_speech_change(), chan, agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01743 { 01744 /* Check for minimum arguments */ 01745 if (argc != 3) 01746 return RESULT_SHOWUSAGE; 01747 01748 /* Check to make sure speech structure exists */ 01749 if (!agi->speech) { 01750 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01751 return RESULT_SUCCESS; 01752 } 01753 01754 ast_speech_change(agi->speech, argv[2], argv[3]); 01755 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01756 01757 return RESULT_SUCCESS; 01758 }
static int handle_speechunloadgrammar | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1791 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_unload(), chan, agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
01792 { 01793 if (argc != 4) 01794 return RESULT_SHOWUSAGE; 01795 01796 if (!agi->speech) { 01797 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01798 return RESULT_SUCCESS; 01799 } 01800 01801 if (ast_speech_grammar_unload(agi->speech, argv[3])) 01802 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01803 else 01804 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01805 01806 return RESULT_SUCCESS; 01807 }
static int handle_streamfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 925 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, chan, agi_state::ctrl, agi_state::fd, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.
00926 { 00927 int res, vres; 00928 struct ast_filestream *fs, *vfs; 00929 long sample_offset = 0, max_length; 00930 char *edigits = ""; 00931 00932 if (argc < 4 || argc > 5) 00933 return RESULT_SHOWUSAGE; 00934 00935 if (argv[3]) 00936 edigits = argv[3]; 00937 00938 if ((argc > 4) && (sscanf(argv[4], "%ld", &sample_offset) != 1)) 00939 return RESULT_SHOWUSAGE; 00940 00941 if (!(fs = ast_openstream(chan, argv[2], chan->language))) { 00942 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset); 00943 return RESULT_SUCCESS; 00944 } 00945 00946 if ((vfs = ast_openvstream(chan, argv[2], chan->language))) 00947 ast_debug(1, "Ooh, found a video stream, too\n"); 00948 00949 ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset); 00950 00951 ast_seekstream(fs, 0, SEEK_END); 00952 max_length = ast_tellstream(fs); 00953 ast_seekstream(fs, sample_offset, SEEK_SET); 00954 res = ast_applystream(chan, fs); 00955 if (vfs) 00956 vres = ast_applystream(chan, vfs); 00957 ast_playstream(fs); 00958 if (vfs) 00959 ast_playstream(vfs); 00960 00961 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 00962 /* this is to check for if ast_waitstream closed the stream, we probably are at 00963 * the end of the stream, return that amount, else check for the amount */ 00964 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; 00965 ast_stopstream(chan); 00966 if (res == 1) { 00967 /* Stop this command, don't print a result line, as there is a new command */ 00968 return RESULT_SUCCESS; 00969 } 00970 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset); 00971 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00972 }
static int handle_tddmode | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 846 of file res_agi.c.
References ast_agi_send(), ast_channel_setoption(), AST_OPTION_TDD, chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00847 { 00848 int res, x; 00849 00850 if (argc != 3) 00851 return RESULT_SHOWUSAGE; 00852 00853 if (!strncasecmp(argv[2],"on",2)) { 00854 x = 1; 00855 } else { 00856 x = 0; 00857 } 00858 if (!strncasecmp(argv[2],"mate",4)) { 00859 x = 2; 00860 } 00861 if (!strncasecmp(argv[2],"tdd",3)) { 00862 x = 1; 00863 } 00864 res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0); 00865 if (res != RESULT_SUCCESS) { 00866 ast_agi_send(agi->fd, chan, "200 result=0\n"); 00867 } else { 00868 ast_agi_send(agi->fd, chan, "200 result=1\n"); 00869 } 00870 return RESULT_SUCCESS; 00871 }
static int handle_verbose | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1594 of file res_agi.c.
References ast_agi_send(), ast_verb, chan, ast_channel::data, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01595 { 01596 int level = 0; 01597 01598 if (argc < 2) 01599 return RESULT_SHOWUSAGE; 01600 01601 if (argv[2]) 01602 sscanf(argv[2], "%d", &level); 01603 01604 ast_verb(level, "%s: %s\n", chan->data, argv[1]); 01605 01606 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01607 01608 return RESULT_SUCCESS; 01609 }
static int handle_waitfordigit | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 777 of file res_agi.c.
References ast_agi_send(), ast_waitfordigit_full(), agi_state::audio, chan, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00778 { 00779 int res, to; 00780 00781 if (argc != 4) 00782 return RESULT_SHOWUSAGE; 00783 if (sscanf(argv[3], "%d", &to) != 1) 00784 return RESULT_SHOWUSAGE; 00785 res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl); 00786 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 00787 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00788 }
static char* help_workhorse | ( | int | fd, | |
char * | match[] | |||
) | [static] |
Definition at line 2343 of file res_agi.c.
References ast_cli(), ast_join(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_SUCCESS, agi_command::cmda, agi_command::dead, agi_command::list, and agi_command::summary.
Referenced by handle_cli_agi_show().
02344 { 02345 char fullcmd[80], matchstr[80]; 02346 struct agi_command *e; 02347 02348 if (match) 02349 ast_join(matchstr, sizeof(matchstr), match); 02350 02351 ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description"); 02352 AST_RWLIST_RDLOCK(&agi_commands); 02353 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 02354 if (!e->cmda[0]) 02355 break; 02356 /* Hide commands that start with '_' */ 02357 if ((e->cmda[0])[0] == '_') 02358 continue; 02359 ast_join(fullcmd, sizeof(fullcmd), e->cmda); 02360 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr))) 02361 continue; 02362 ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, e->summary); 02363 } 02364 AST_RWLIST_UNLOCK(&agi_commands); 02365 02366 return CLI_SUCCESS; 02367 }
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, chan, agi_cmd::cmd_buffer, agi_cmd::cmd_id, agi_state::ctrl, EVENT_FLAG_AGI, f, agi_state::fast, agi_state::fd, free_agi_cmd(), get_agi_cmd(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, manager_event, ast_channel::name, quit, setup_env(), and agi_state::speech.
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, ahp, 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, chan, 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 3068 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.
03069 { 03070 ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry)); 03071 /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as 03072 no other commands have been registered yet 03073 */ 03074 (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 03075 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip); 03076 ast_register_application(eapp, eagi_exec, esynopsis, descrip); 03077 ast_manager_register2("AGI", EVENT_FLAG_AGI, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi); 03078 return ast_register_application(app, agi_exec, synopsis, descrip); 03079 }
static int parse_args | ( | char * | s, | |
int * | max, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2501 of file res_agi.c.
References ast_log(), LOG_WARNING, and MAX_ARGS.
02502 { 02503 int x = 0, quoted = 0, escaped = 0, whitespace = 1; 02504 char *cur; 02505 02506 cur = s; 02507 while(*s) { 02508 switch(*s) { 02509 case '"': 02510 /* If it's escaped, put a literal quote */ 02511 if (escaped) 02512 goto normal; 02513 else 02514 quoted = !quoted; 02515 if (quoted && whitespace) { 02516 /* If we're starting a quote, coming off white space start a new word, too */ 02517 argv[x++] = cur; 02518 whitespace=0; 02519 } 02520 escaped = 0; 02521 break; 02522 case ' ': 02523 case '\t': 02524 if (!quoted && !escaped) { 02525 /* If we're not quoted, mark this as whitespace, and 02526 end the previous argument */ 02527 whitespace = 1; 02528 *(cur++) = '\0'; 02529 } else 02530 /* Otherwise, just treat it as anything else */ 02531 goto normal; 02532 break; 02533 case '\\': 02534 /* If we're escaped, print a literal, otherwise enable escaping */ 02535 if (escaped) { 02536 goto normal; 02537 } else { 02538 escaped=1; 02539 } 02540 break; 02541 default: 02542 normal: 02543 if (whitespace) { 02544 if (x >= MAX_ARGS -1) { 02545 ast_log(LOG_WARNING, "Too many arguments, truncating\n"); 02546 break; 02547 } 02548 /* Coming off of whitespace, start the next argument */ 02549 argv[x++] = cur; 02550 whitespace=0; 02551 } 02552 *(cur++) = *s; 02553 escaped=0; 02554 } 02555 s++; 02556 } 02557 /* Null terminate */ 02558 *(cur++) = '\0'; 02559 argv[x] = NULL; 02560 *max = x; 02561 return 0; 02562 }
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 2636 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_strlen_zero(), ast_verb, ast_verbose, ast_waitfor_nandfds(), agi_state::audio, buf, chan, agi_state::ctrl, errno, f, agi_state::fast, agi_state::fd, len(), LOG_WARNING, ast_channel::name, pbx_builtin_getvar_helper(), and setup_env().
Referenced by agi_exec_full().
02637 { 02638 struct ast_channel *c; 02639 int outfd, ms, needhup = 0; 02640 enum agi_result returnstatus = AGI_RESULT_SUCCESS; 02641 struct ast_frame *f; 02642 char buf[AGI_BUF_LEN]; 02643 char *res = NULL; 02644 FILE *readf; 02645 /* how many times we'll retry if ast_waitfor_nandfs will return without either 02646 channel or file descriptor in case select is interrupted by a system call (EINTR) */ 02647 int retry = AGI_NANDFS_RETRY; 02648 int send_sighup; 02649 const char *sighup_str; 02650 02651 ast_channel_lock(chan); 02652 sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP"); 02653 send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str); 02654 ast_channel_unlock(chan); 02655 02656 if (!(readf = fdopen(agi->ctrl, "r"))) { 02657 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n"); 02658 if (send_sighup && pid > -1) 02659 kill(pid, SIGHUP); 02660 close(agi->ctrl); 02661 return AGI_RESULT_FAILURE; 02662 } 02663 02664 setlinebuf(readf); 02665 setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv); 02666 for (;;) { 02667 if (needhup) { 02668 needhup = 0; 02669 dead = 1; 02670 if (send_sighup) { 02671 if (pid > -1) { 02672 kill(pid, SIGHUP); 02673 } else if (agi->fast) { 02674 send(agi->ctrl, "HANGUP\n", 7, MSG_OOB); 02675 } 02676 } 02677 } 02678 ms = -1; 02679 c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms); 02680 if (c) { 02681 retry = AGI_NANDFS_RETRY; 02682 /* Idle the channel until we get a command */ 02683 f = ast_read(c); 02684 if (!f) { 02685 ast_debug(1, "%s hungup\n", chan->name); 02686 returnstatus = AGI_RESULT_HANGUP; 02687 needhup = 1; 02688 continue; 02689 } else { 02690 /* If it's voice, write it to the audio pipe */ 02691 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) { 02692 /* Write, ignoring errors */ 02693 if (write(agi->audio, f->data.ptr, f->datalen) < 0) { 02694 } 02695 } 02696 ast_frfree(f); 02697 } 02698 } else if (outfd > -1) { 02699 size_t len = sizeof(buf); 02700 size_t buflen = 0; 02701 02702 retry = AGI_NANDFS_RETRY; 02703 buf[0] = '\0'; 02704 02705 while (buflen < (len - 1)) { 02706 res = fgets(buf + buflen, len, readf); 02707 if (feof(readf)) 02708 break; 02709 if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN))) 02710 break; 02711 if (res != NULL && !agi->fast) 02712 break; 02713 buflen = strlen(buf); 02714 if (buflen && buf[buflen - 1] == '\n') 02715 break; 02716 len -= buflen; 02717 if (agidebug) 02718 ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno)); 02719 } 02720 02721 if (!buf[0]) { 02722 /* Program terminated */ 02723 if (returnstatus) { 02724 returnstatus = -1; 02725 } 02726 ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", chan->name, request, returnstatus); 02727 if (pid > 0) 02728 waitpid(pid, status, 0); 02729 /* No need to kill the pid anymore, since they closed us */ 02730 pid = -1; 02731 break; 02732 } 02733 02734 /* Special case for inability to execute child process */ 02735 if (*buf && strncasecmp(buf, "failure", 7) == 0) { 02736 returnstatus = AGI_RESULT_FAILURE; 02737 break; 02738 } 02739 02740 /* get rid of trailing newline, if any */ 02741 if (*buf && buf[strlen(buf) - 1] == '\n') 02742 buf[strlen(buf) - 1] = 0; 02743 if (agidebug) 02744 ast_verbose("<%s>AGI Rx << %s\n", chan->name, buf); 02745 returnstatus |= agi_handle_command(chan, agi, buf, dead); 02746 /* If the handle_command returns -1, we need to stop */ 02747 if (returnstatus < 0) { 02748 needhup = 1; 02749 continue; 02750 } 02751 } else { 02752 if (--retry <= 0) { 02753 ast_log(LOG_WARNING, "No channel, no fd?\n"); 02754 returnstatus = AGI_RESULT_FAILURE; 02755 break; 02756 } 02757 } 02758 } 02759 if (agi->speech) { 02760 ast_speech_destroy(agi->speech); 02761 } 02762 /* Notify process */ 02763 if (send_sighup) { 02764 if (pid > -1) { 02765 if (kill(pid, SIGHUP)) { 02766 ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno)); 02767 } else { /* Give the process a chance to die */ 02768 usleep(1); 02769 } 02770 waitpid(pid, status, WNOHANG); 02771 } else if (agi->fast) { 02772 send(agi->ctrl, "HANGUP\n", 7, MSG_OOB); 02773 } 02774 } 02775 fclose(readf); 02776 return returnstatus; 02777 }
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_channel::accountcode, ast_agi_send(), ast_get_version(), chan, 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::language, ast_channel::name, ast_channel::priority, S_OR, ast_channel::tech, ast_channel_tech::type, and ast_channel::uniqueid.
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 1845 of file res_agi.c.
References ast_applystream(), ast_openstream(), ast_playstream(), ast_seekstream(), and chan.
01846 { 01847 struct ast_filestream *fs = NULL; 01848 01849 if (!(fs = ast_openstream(chan, filename, preflang))) 01850 return -1; 01851 01852 if (offset) 01853 ast_seekstream(fs, offset, SEEK_SET); 01854 01855 if (ast_applystream(chan, fs)) 01856 return -1; 01857 01858 if (ast_playstream(fs)) 01859 return -1; 01860 01861 return 0; 01862 }
static int unload_module | ( | void | ) | [static] |
Definition at line 3055 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.
03056 { 03057 ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry)); 03058 /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as 03059 we know that these commands were registered by this module and are still registered 03060 */ 03061 (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 03062 ast_unregister_application(eapp); 03063 ast_unregister_application(deadapp); 03064 ast_manager_unregister("AGI"); 03065 return ast_unregister_application(app); 03066 }
static void write_html_escaped | ( | FILE * | htmlfile, | |
char * | str | |||
) | [static] |
Convert string to use HTML escaped characters.
Definition at line 2819 of file res_agi.c.
Referenced by write_htmldump().
02820 { 02821 char *cur = str; 02822 02823 while(*cur) { 02824 switch (*cur) { 02825 case '<': 02826 fprintf(htmlfile, "%s", "<"); 02827 break; 02828 case '>': 02829 fprintf(htmlfile, "%s", ">"); 02830 break; 02831 case '&': 02832 fprintf(htmlfile, "%s", "&"); 02833 break; 02834 case '"': 02835 fprintf(htmlfile, "%s", """); 02836 break; 02837 default: 02838 fprintf(htmlfile, "%c", *cur); 02839 break; 02840 } 02841 cur++; 02842 } 02843 02844 return; 02845 }
static int write_htmldump | ( | char * | filename | ) | [static] |
Definition at line 2847 of file res_agi.c.
References ast_join(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, agi_command::list, strsep(), agi_command::summary, agi_command::usage, and write_html_escaped().
Referenced by handle_cli_agi_dump_html(), and handle_cli_agi_dumphtml_deprecated().
02848 { 02849 struct agi_command *command; 02850 char fullcmd[80]; 02851 FILE *htmlfile; 02852 02853 if (!(htmlfile = fopen(filename, "wt"))) 02854 return -1; 02855 02856 fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n"); 02857 fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n"); 02858 fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n"); 02859 02860 AST_RWLIST_RDLOCK(&agi_commands); 02861 AST_RWLIST_TRAVERSE(&agi_commands, command, list) { 02862 char *stringp, *tempstr; 02863 02864 if (!command->cmda[0]) /* end ? */ 02865 break; 02866 /* Hide commands that start with '_' */ 02867 if ((command->cmda[0])[0] == '_') 02868 continue; 02869 ast_join(fullcmd, sizeof(fullcmd), command->cmda); 02870 02871 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n"); 02872 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary); 02873 02874 stringp = command->usage; 02875 tempstr = strsep(&stringp, "\n"); 02876 02877 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">"); 02878 write_html_escaped(htmlfile, tempstr); 02879 fprintf(htmlfile, "</TD></TR>\n"); 02880 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n"); 02881 02882 while ((tempstr = strsep(&stringp, "\n")) != NULL) { 02883 write_html_escaped(htmlfile, tempstr); 02884 fprintf(htmlfile, "<BR>\n"); 02885 } 02886 fprintf(htmlfile, "</TD></TR>\n"); 02887 fprintf(htmlfile, "</TABLE></TD></TR>\n\n"); 02888 } 02889 AST_RWLIST_UNLOCK(&agi_commands); 02890 fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n"); 02891 fclose(htmlfile); 02892 return 0; 02893 }
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] |
Initial value:
{ .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] |
struct ast_cli_entry cli_agi_dumphtml_deprecated = { .handler = handle_cli_agi_dumphtml_deprecated , .summary = "Dumps a list of AGI commands in HTML format" ,__VA_ARGS__ } [static] |
struct agi_command commands[] [static] |
AGI commands list.
Definition at line 2293 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] |
char usage_answer[] [static] |
char usage_autohangup[] [static] |
Initial value:
" 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] |
Initial value:
" 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] |