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