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