AGI - the Asterisk Gateway Interface. More...
#include "asterisk.h"#include <math.h>#include <signal.h>#include <sys/time.h>#include <sys/wait.h>#include <sys/stat.h>#include <pthread.h>#include "asterisk/paths.h"#include "asterisk/network.h"#include "asterisk/file.h"#include "asterisk/channel.h"#include "asterisk/pbx.h"#include "asterisk/module.h"#include "asterisk/astdb.h"#include "asterisk/callerid.h"#include "asterisk/cli.h"#include "asterisk/image.h"#include "asterisk/say.h"#include "asterisk/app.h"#include "asterisk/dsp.h"#include "asterisk/musiconhold.h"#include "asterisk/utils.h"#include "asterisk/lock.h"#include "asterisk/strings.h"#include "asterisk/manager.h"#include "asterisk/ast_version.h"#include "asterisk/speech.h"#include "asterisk/features.h"#include "asterisk/term.h"#include "asterisk/xmldoc.h"#include "asterisk/agi.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 | AST_API_MODULE |
| #define | MAX_AGI_CONNECT 2000 |
| #define | MAX_ARGS 128 |
| #define | MAX_CMD_LEN 80 |
| #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) |
| Registers an AGI command. | |
| 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) |
| Unregisters an AGI command. | |
| int | ast_agi_unregister_multiple (struct ast_module *mod, struct agi_command *cmd, unsigned int len) |
| Unregisters a group of AGI commands, provided as an array of struct agi_command entries. | |
| static int | deadagi_exec (struct ast_channel *chan, void *data) |
| static int | eagi_exec (struct ast_channel *chan, void *data) |
| static agi_command * | find_command (char *cmds[], int exact) |
| static void | free_agi_cmd (struct agi_cmd *cmd) |
| static struct agi_cmd * | get_agi_cmd (struct ast_channel *chan) |
| static int | handle_answer (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_asyncagi_break (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_autohangup (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
| static int | handle_channelstatus (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
| static char * | handle_cli_agi_add_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command to add applications to execute in Async AGI. | |
| static char * | handle_cli_agi_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_agi_dump_html (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_agi_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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } |
| static struct ast_threadstorage | agi_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_agi_buf , .custom_init = NULL , } |
| static struct ast_datastore_info | agi_commands_datastore_info |
| static int | agidebug = 0 |
| static char * | app = "AGI" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_cli_entry | cli_agi [] |
| static struct 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_autohangup [] |
| static char | usage_controlstreamfile [] |
| 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_setpriority [] |
| static char | usage_setvariable [] |
| static char | usage_speechactivategrammar [] |
| static char | usage_speechcreate [] |
| static char | usage_speechdeactivategrammar [] |
| static char | usage_speechdestroy [] |
| static char | usage_speechloadgrammar [] |
| static char | usage_speechrecognize [] |
| static char | usage_speechset [] |
| static char | usage_speechunloadgrammar [] |
| static char | usage_streamfile [] |
| static char | usage_tddmode [] |
| static char | usage_verbose [] |
| static char | usage_waitfordigit [] |
AGI - the Asterisk Gateway Interface.
Definition in file res_agi.c.
| #define AGI_BUF_INITSIZE 256 |
Definition at line 373 of file res_agi.c.
Referenced by ast_agi_send().
| #define AGI_BUF_LEN 2048 |
Definition at line 320 of file res_agi.c.
Referenced by agi_exec_full(), and run_agi().
| #define AGI_BUF_SIZE 1024 |
Referenced by launch_asyncagi().
| #define AGI_PORT 4573 |
Definition at line 359 of file res_agi.c.
Referenced by launch_netscript().
| #define AMI_BUF_SIZE 2048 |
Referenced by launch_asyncagi().
| #define MAX_AGI_CONNECT 2000 |
Definition at line 357 of file res_agi.c.
Referenced by launch_netscript().
| #define MAX_CMD_LEN 80 |
Definition at line 318 of file res_agi.c.
Referenced by ast_agi_register(), ast_agi_unregister(), handle_cli_agi_show(), help_workhorse(), and write_htmldump().
| 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 361 of file res_agi.c.
00361 { 00362 AGI_RESULT_FAILURE = -1, 00363 AGI_RESULT_SUCCESS, 00364 AGI_RESULT_SUCCESS_FAST, 00365 AGI_RESULT_SUCCESS_ASYNC, 00366 AGI_RESULT_NOTFOUND, 00367 AGI_RESULT_HANGUP, 00368 };
| 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 587 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, and ast_channel::name.
Referenced by load_module().
00588 { 00589 const char *channel = astman_get_header(m, "Channel"); 00590 const char *cmdbuff = astman_get_header(m, "Command"); 00591 const char *cmdid = astman_get_header(m, "CommandID"); 00592 struct ast_channel *chan; 00593 char buf[256]; 00594 if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) { 00595 astman_send_error(s, m, "Both, Channel and Command are *required*"); 00596 return 0; 00597 } 00598 chan = ast_get_channel_by_name_locked(channel); 00599 if (!chan) { 00600 snprintf(buf, sizeof(buf), "Channel %s does not exists or cannot get its lock", channel); 00601 astman_send_error(s, m, buf); 00602 return 0; 00603 } 00604 if (add_agi_cmd(chan, cmdbuff, cmdid)) { 00605 snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", chan->name); 00606 astman_send_error(s, m, buf); 00607 ast_channel_unlock(chan); 00608 return 0; 00609 } 00610 astman_send_ack(s, m, "Added AGI command to queue"); 00611 ast_channel_unlock(chan); 00612 return 0; 00613 }
| static int add_agi_cmd | ( | struct ast_channel * | chan, | |
| const char * | cmd_buff, | |||
| const char * | cmd_id | |||
| ) | [static] |
Definition at line 467 of file res_agi.c.
References agi_commands_datastore_info, ast_calloc, ast_channel_datastore_find(), ast_free, AST_LIST_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strdup, agi_cmd::cmd_buffer, agi_cmd::cmd_id, ast_datastore::data, agi_cmd::entry, LOG_WARNING, and ast_channel::name.
Referenced by action_add_agi_cmd(), and handle_cli_agi_add_cmd().
00468 { 00469 struct ast_datastore *store; 00470 struct agi_cmd *cmd; 00471 AST_LIST_HEAD(, agi_cmd) *agi_commands; 00472 00473 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 00474 if (!store) { 00475 ast_log(LOG_WARNING, "Channel %s is not at Async AGI.\n", chan->name); 00476 return -1; 00477 } 00478 agi_commands = store->data; 00479 cmd = ast_calloc(1, sizeof(*cmd)); 00480 if (!cmd) { 00481 return -1; 00482 } 00483 cmd->cmd_buffer = ast_strdup(cmd_buff); 00484 if (!cmd->cmd_buffer) { 00485 ast_free(cmd); 00486 return -1; 00487 } 00488 cmd->cmd_id = ast_strdup(cmd_id); 00489 if (!cmd->cmd_id) { 00490 ast_free(cmd->cmd_buffer); 00491 ast_free(cmd); 00492 return -1; 00493 } 00494 AST_LIST_LOCK(agi_commands); 00495 AST_LIST_INSERT_TAIL(agi_commands, cmd, entry); 00496 AST_LIST_UNLOCK(agi_commands); 00497 return 0; 00498 }
| static int add_to_agi | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 500 of file res_agi.c.
References agi_commands_datastore_info, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, ast_log(), ast_datastore::data, and LOG_ERROR.
Referenced by launch_asyncagi().
00501 { 00502 struct ast_datastore *datastore; 00503 AST_LIST_HEAD(, agi_cmd) *agi_cmds_list; 00504 00505 /* check if already on AGI */ 00506 ast_channel_lock(chan); 00507 datastore = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 00508 ast_channel_unlock(chan); 00509 if (datastore) { 00510 /* we already have an AGI datastore, let's just 00511 return success */ 00512 return 0; 00513 } 00514 00515 /* the channel has never been on Async AGI, 00516 let's allocate it's datastore */ 00517 datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI"); 00518 if (!datastore) { 00519 return -1; 00520 } 00521 agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list)); 00522 if (!agi_cmds_list) { 00523 ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n"); 00524 ast_datastore_free(datastore); 00525 return -1; 00526 } 00527 datastore->data = agi_cmds_list; 00528 AST_LIST_HEAD_INIT(agi_cmds_list); 00529 ast_channel_lock(chan); 00530 ast_channel_datastore_add(chan, datastore); 00531 ast_channel_unlock(chan); 00532 return 0; 00533 }
| static void agi_destroy_commands_cb | ( | void * | data | ) | [static] |
Definition at line 419 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().
00420 { 00421 struct agi_cmd *cmd; 00422 AST_LIST_HEAD(, agi_cmd) *chan_cmds = data; 00423 AST_LIST_LOCK(chan_cmds); 00424 while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) { 00425 free_agi_cmd(cmd); 00426 } 00427 AST_LIST_UNLOCK(chan_cmds); 00428 AST_LIST_HEAD_DESTROY(chan_cmds); 00429 ast_free(chan_cmds); 00430 }
| static int agi_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3279 of file res_agi.c.
References agi_exec_full(), and ast_check_hangup().
Referenced by deadagi_exec(), and load_module().
03280 { 03281 if (!ast_check_hangup(chan)) 03282 return agi_exec_full(chan, data, 0, 0); 03283 else 03284 return agi_exec_full(chan, data, 0, 1); 03285 }
| static int agi_exec_full | ( | struct ast_channel * | chan, | |
| void * | data, | |||
| int | enhanced, | |||
| int | dead | |||
| ) | [static] |
Definition at line 3212 of file res_agi.c.
References ast_channel::_state, AGI_BUF_LEN, AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_NOTFOUND, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, AGI_RESULT_SUCCESS_FAST, ast_answer(), AST_APP_ARG, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_log(), ast_safe_fork_cleanup(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strlen_zero(), buf, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), run_agi(), and status.
Referenced by agi_exec(), and eagi_exec().
03213 { 03214 enum agi_result res; 03215 char buf[AGI_BUF_LEN] = "", *tmp = buf; 03216 int fds[2], efd = -1, pid; 03217 AST_DECLARE_APP_ARGS(args, 03218 AST_APP_ARG(arg)[MAX_ARGS]; 03219 ); 03220 AGI agi; 03221 03222 if (ast_strlen_zero(data)) { 03223 ast_log(LOG_WARNING, "AGI requires an argument (script)\n"); 03224 return -1; 03225 } 03226 if (dead) 03227 ast_debug(3, "Hungup channel detected, running agi in dead mode.\n"); 03228 ast_copy_string(buf, data, sizeof(buf)); 03229 memset(&agi, 0, sizeof(agi)); 03230 AST_STANDARD_APP_ARGS(args, tmp); 03231 args.argv[args.argc] = NULL; 03232 #if 0 03233 /* Answer if need be */ 03234 if (chan->_state != AST_STATE_UP) { 03235 if (ast_answer(chan)) 03236 return -1; 03237 } 03238 #endif 03239 res = launch_script(chan, args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid); 03240 /* Async AGI do not require run_agi(), so just proceed if normal AGI 03241 or Fast AGI are setup with success. */ 03242 if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) { 03243 int status = 0; 03244 agi.fd = fds[1]; 03245 agi.ctrl = fds[0]; 03246 agi.audio = efd; 03247 agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0; 03248 res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv); 03249 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */ 03250 if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status) 03251 res = AGI_RESULT_FAILURE; 03252 if (fds[1] != fds[0]) 03253 close(fds[1]); 03254 if (efd > -1) 03255 close(efd); 03256 } 03257 ast_safe_fork_cleanup(); 03258 03259 switch (res) { 03260 case AGI_RESULT_SUCCESS: 03261 case AGI_RESULT_SUCCESS_FAST: 03262 case AGI_RESULT_SUCCESS_ASYNC: 03263 pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS"); 03264 break; 03265 case AGI_RESULT_FAILURE: 03266 pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE"); 03267 break; 03268 case AGI_RESULT_NOTFOUND: 03269 pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND"); 03270 break; 03271 case AGI_RESULT_HANGUP: 03272 pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP"); 03273 return -1; 03274 } 03275 03276 return 0; 03277 }
| static int agi_handle_command | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| char * | buf, | |||
| int | dead | |||
| ) | [static] |
Definition at line 2777 of file res_agi.c.
References ast_agi_send(), ast_cdr_setapp(), ast_check_hangup(), ast_module_ref(), ast_module_unref(), ast_random(), ast_strlen_zero(), ast_channel::cdr, agi_command::dead, EVENT_FLAG_AGI, agi_state::fd, find_command(), agi_command::handler, manager_event, MAX_ARGS, agi_command::mod, ast_channel::name, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.
Referenced by launch_asyncagi(), and run_agi().
02778 { 02779 char *argv[MAX_ARGS]; 02780 int argc = MAX_ARGS, res; 02781 agi_command *c; 02782 const char *ami_res = "Unknown Result"; 02783 char *ami_cmd = ast_strdupa(buf); 02784 int command_id = ast_random(), resultcode = 200; 02785 02786 manager_event(EVENT_FLAG_AGI, "AGIExec", 02787 "SubEvent: Start\r\n" 02788 "Channel: %s\r\n" 02789 "CommandId: %d\r\n" 02790 "Command: %s\r\n", chan->name, command_id, ami_cmd); 02791 parse_args(buf, &argc, argv); 02792 if ((c = find_command(argv, 0)) && (!dead || (dead && c->dead))) { 02793 /* if this command wasnt registered by res_agi, be sure to usecount 02794 the module we are using */ 02795 if (c->mod != ast_module_info->self) 02796 ast_module_ref(c->mod); 02797 /* If the AGI command being executed is an actual application (using agi exec) 02798 the app field will be updated in pbx_exec via handle_exec */ 02799 if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC")) 02800 ast_cdr_setapp(chan->cdr, "AGI", buf); 02801 02802 res = c->handler(chan, agi, argc, argv); 02803 if (c->mod != ast_module_info->self) 02804 ast_module_unref(c->mod); 02805 switch (res) { 02806 case RESULT_SHOWUSAGE: ami_res = "Usage"; resultcode = 520; break; 02807 case RESULT_FAILURE: ami_res = "Failure"; resultcode = -1; break; 02808 case RESULT_SUCCESS: ami_res = "Success"; resultcode = 200; break; 02809 } 02810 manager_event(EVENT_FLAG_AGI, "AGIExec", 02811 "SubEvent: End\r\n" 02812 "Channel: %s\r\n" 02813 "CommandId: %d\r\n" 02814 "Command: %s\r\n" 02815 "ResultCode: %d\r\n" 02816 "Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res); 02817 switch(res) { 02818 case RESULT_SHOWUSAGE: 02819 if (ast_strlen_zero(c->usage)) { 02820 ast_agi_send(agi->fd, chan, "520 Invalid command syntax. Proper usage not available.\n"); 02821 } else { 02822 ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n"); 02823 ast_agi_send(agi->fd, chan, "%s", c->usage); 02824 ast_agi_send(agi->fd, chan, "520 End of proper usage.\n"); 02825 } 02826 break; 02827 case RESULT_FAILURE: 02828 /* They've already given the failure. We've been hung up on so handle this 02829 appropriately */ 02830 return -1; 02831 } 02832 } else if ((c = find_command(argv, 0))) { 02833 ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n"); 02834 manager_event(EVENT_FLAG_AGI, "AGIExec", 02835 "SubEvent: End\r\n" 02836 "Channel: %s\r\n" 02837 "CommandId: %d\r\n" 02838 "Command: %s\r\n" 02839 "ResultCode: 511\r\n" 02840 "Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd); 02841 } else { 02842 ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n"); 02843 manager_event(EVENT_FLAG_AGI, "AGIExec", 02844 "SubEvent: End\r\n" 02845 "Channel: %s\r\n" 02846 "CommandId: %d\r\n" 02847 "Command: %s\r\n" 02848 "ResultCode: 510\r\n" 02849 "Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd); 02850 } 02851 return 0; 02852 }
| int ast_agi_register | ( | struct ast_module * | mod, | |
| agi_command * | cmd | |||
| ) |
Registers an AGI command.
| mod | Pointer to the module_info structure for the module that is registering the command | |
| cmd | Pointer to the descriptor for the command |
Definition at line 2556 of file res_agi.c.
References ast_join(), AST_LIST_INSERT_TAIL, ast_log(), ast_module_ref(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_strdup, ast_strlen_zero(), ast_verb, AST_XML_DOC, ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), agi_command::cmda, agi_command::docsrc, find_command(), agi_command::list, LOG_WARNING, MAX_CMD_LEN, agi_command::mod, agi_command::seealso, agi_command::summary, agi_command::syntax, and agi_command::usage.
Referenced by ast_agi_register_multiple(), and load_module().
02557 { 02558 char fullcmd[MAX_CMD_LEN]; 02559 02560 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 02561 02562 if (!find_command(cmd->cmda,1)) { 02563 cmd->docsrc = AST_STATIC_DOC; 02564 if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) { 02565 #ifdef AST_XML_DOCS 02566 *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd); 02567 *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd); 02568 *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd); 02569 *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd); 02570 *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC; 02571 #elif (!defined(HAVE_NULLSAFE_PRINTF)) 02572 *((char **) &cmd->summary) = ast_strdup(""); 02573 *((char **) &cmd->usage) = ast_strdup(""); 02574 *((char **) &cmd->syntax) = ast_strdup(""); 02575 *((char **) &cmd->seealso) = ast_strdup(""); 02576 #endif 02577 } 02578 02579 cmd->mod = mod; 02580 AST_RWLIST_WRLOCK(&agi_commands); 02581 AST_LIST_INSERT_TAIL(&agi_commands, cmd, list); 02582 AST_RWLIST_UNLOCK(&agi_commands); 02583 if (mod != ast_module_info->self) 02584 ast_module_ref(ast_module_info->self); 02585 ast_verb(2, "AGI Command '%s' registered\n",fullcmd); 02586 return 1; 02587 } else { 02588 ast_log(LOG_WARNING, "Command already registered!\n"); 02589 return 0; 02590 } 02591 }
| 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 command descriptors | |
| len | Length of the array (use the ARRAY_LEN macro to determine this easily) |
Definition at line 2630 of file res_agi.c.
References ast_agi_register(), and ast_agi_unregister().
Referenced by load_module().
02631 { 02632 unsigned int i, x = 0; 02633 02634 for (i = 0; i < len; i++) { 02635 if (ast_agi_register(mod, cmd + i) == 1) { 02636 x++; 02637 continue; 02638 } 02639 02640 /* registration failed, unregister everything 02641 that had been registered up to that point 02642 */ 02643 for (; x > 0; x--) { 02644 /* we are intentionally ignoring the 02645 result of ast_agi_unregister() here, 02646 but it should be safe to do so since 02647 we just registered these commands and 02648 the only possible way for unregistration 02649 to fail is if the command is not 02650 registered 02651 */ 02652 (void) ast_agi_unregister(mod, cmd + x - 1); 02653 } 02654 return -1; 02655 } 02656 02657 return 0; 02658 }
| 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 375 of file res_agi.c.
References agi_buf, AGI_BUF_INITSIZE, ast_carefulwrite(), ast_log(), ast_str_buffer(), ast_str_set_va(), ast_str_strlen(), ast_str_thread_get(), ast_verbose, buf, LOG_ERROR, and ast_channel::name.
Referenced by agi_handle_command(), handle_answer(), handle_asyncagi_break(), handle_autohangup(), handle_channelstatus(), handle_controlstreamfile(), handle_dbdel(), handle_dbdeltree(), handle_dbget(), handle_dbput(), handle_exec(), handle_getdata(), handle_getoption(), handle_getvariable(), handle_getvariablefull(), handle_gosub(), handle_hangup(), handle_noop(), handle_recordfile(), handle_recvchar(), handle_recvtext(), handle_sayalpha(), handle_saydate(), handle_saydatetime(), handle_saydigits(), handle_saynumber(), handle_sayphonetic(), handle_saytime(), handle_sendimage(), handle_sendtext(), handle_setcallerid(), handle_setcontext(), handle_setextension(), handle_setmusic(), handle_setpriority(), handle_setvariable(), handle_speechactivategrammar(), handle_speechcreate(), handle_speechdeactivategrammar(), handle_speechdestroy(), handle_speechloadgrammar(), handle_speechrecognize(), handle_speechset(), handle_speechunloadgrammar(), handle_streamfile(), handle_tddmode(), handle_verbose(), handle_waitfordigit(), launch_netscript(), and setup_env().
00376 { 00377 int res = 0; 00378 va_list ap; 00379 struct ast_str *buf; 00380 00381 if (!(buf = ast_str_thread_get(&agi_buf, AGI_BUF_INITSIZE))) 00382 return -1; 00383 00384 va_start(ap, fmt); 00385 res = ast_str_set_va(&buf, 0, fmt, ap); 00386 va_end(ap); 00387 00388 if (res == -1) { 00389 ast_log(LOG_ERROR, "Out of memory\n"); 00390 return -1; 00391 } 00392 00393 if (agidebug) { 00394 if (chan) { 00395 ast_verbose("<%s>AGI Tx >> %s", chan->name, ast_str_buffer(buf)); 00396 } else { 00397 ast_verbose("AGI Tx >> %s", ast_str_buffer(buf)); 00398 } 00399 } 00400 00401 return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100); 00402 }
| int ast_agi_unregister | ( | struct ast_module * | mod, | |
| agi_command * | cmd | |||
| ) |
Unregisters an AGI command.
| mod | Pointer to the module_info structure for the module that is unregistering the command | |
| cmd | Pointer to the descriptor for the command |
Definition at line 2593 of file res_agi.c.
References ast_free, 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, AST_XML_DOC, agi_command::cmda, agi_command::docsrc, agi_command::list, LOG_WARNING, MAX_CMD_LEN, agi_command::seealso, agi_command::summary, agi_command::syntax, and agi_command::usage.
Referenced by ast_agi_register_multiple(), ast_agi_unregister_multiple(), and unload_module().
02594 { 02595 struct agi_command *e; 02596 int unregistered = 0; 02597 char fullcmd[MAX_CMD_LEN]; 02598 02599 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda); 02600 02601 AST_RWLIST_WRLOCK(&agi_commands); 02602 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) { 02603 if (cmd == e) { 02604 AST_RWLIST_REMOVE_CURRENT(list); 02605 if (mod != ast_module_info->self) 02606 ast_module_unref(ast_module_info->self); 02607 #ifdef AST_XML_DOCS 02608 if (e->docsrc == AST_XML_DOC) { 02609 ast_free(e->summary); 02610 ast_free(e->usage); 02611 ast_free(e->syntax); 02612 ast_free(e->seealso); 02613 e->summary = NULL, e->usage = NULL; 02614 e->syntax = NULL, e->seealso = NULL; 02615 } 02616 #endif 02617 unregistered=1; 02618 break; 02619 } 02620 } 02621 AST_RWLIST_TRAVERSE_SAFE_END; 02622 AST_RWLIST_UNLOCK(&agi_commands); 02623 if (unregistered) 02624 ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd); 02625 else 02626 ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd); 02627 return unregistered; 02628 }
| 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 command descriptors | |
| len | Length of the array (use the ARRAY_LEN macro to determine this easily) |
Definition at line 2660 of file res_agi.c.
References ast_agi_unregister().
Referenced by unload_module().
02661 { 02662 unsigned int i; 02663 int res = 0; 02664 02665 for (i = 0; i < len; i++) { 02666 /* remember whether any of the unregistration 02667 attempts failed... there is no recourse if 02668 any of them do 02669 */ 02670 res |= ast_agi_unregister(mod, cmd + i); 02671 } 02672 02673 return res; 02674 }
| static int deadagi_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3309 of file res_agi.c.
References agi_exec(), ast_log(), and LOG_WARNING.
Referenced by load_module().
03310 { 03311 ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n"); 03312 return agi_exec(chan, data); 03313 }
| static int eagi_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3287 of file res_agi.c.
References agi_exec_full(), ast_check_hangup(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), ast_set_read_format(), LOG_ERROR, LOG_WARNING, ast_channel::name, and ast_channel::readformat.
Referenced by load_module().
03288 { 03289 int readformat, res; 03290 03291 if (ast_check_hangup(chan)) { 03292 ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n"); 03293 return 0; 03294 } 03295 readformat = chan->readformat; 03296 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 03297 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name); 03298 return -1; 03299 } 03300 res = agi_exec_full(chan, data, 1, 0); 03301 if (!res) { 03302 if (ast_set_read_format(chan, readformat)) { 03303 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat)); 03304 } 03305 } 03306 return res; 03307 }
| static agi_command * find_command | ( | char * | cmds[], | |
| int | exact | |||
| ) | [static] |
Definition at line 2676 of file res_agi.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, agi_command::list, and match().
Referenced by agi_handle_command(), ast_agi_register(), and handle_cli_agi_show().
02677 { 02678 int y, match; 02679 struct agi_command *e; 02680 02681 AST_RWLIST_RDLOCK(&agi_commands); 02682 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 02683 if (!e->cmda[0]) 02684 break; 02685 /* start optimistic */ 02686 match = 1; 02687 for (y = 0; match && cmds[y]; y++) { 02688 /* If there are no more words in the command (and we're looking for 02689 an exact match) or there is a difference between the two words, 02690 then this is not a match */ 02691 if (!e->cmda[y] && !exact) 02692 break; 02693 /* don't segfault if the next part of a command doesn't exist */ 02694 if (!e->cmda[y]) { 02695 AST_RWLIST_UNLOCK(&agi_commands); 02696 return NULL; 02697 } 02698 if (strcasecmp(e->cmda[y], cmds[y])) 02699 match = 0; 02700 } 02701 /* If more words are needed to complete the command then this is not 02702 a candidate (unless we're looking for a really inexact answer */ 02703 if ((exact > -1) && e->cmda[y]) 02704 match = 0; 02705 if (match) { 02706 AST_RWLIST_UNLOCK(&agi_commands); 02707 return e; 02708 } 02709 } 02710 AST_RWLIST_UNLOCK(&agi_commands); 02711 return NULL; 02712 }
| static void free_agi_cmd | ( | struct agi_cmd * | cmd | ) | [static] |
Definition at line 411 of file res_agi.c.
References ast_free.
Referenced by agi_destroy_commands_cb(), and launch_asyncagi().
00412 { 00413 ast_free(cmd->cmd_buffer); 00414 ast_free(cmd->cmd_id); 00415 ast_free(cmd); 00416 }
| static struct agi_cmd* get_agi_cmd | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 446 of file res_agi.c.
References agi_commands_datastore_info, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_datastore::data, agi_cmd::entry, LOG_ERROR, and ast_channel::name.
Referenced by launch_asyncagi().
00447 { 00448 struct ast_datastore *store; 00449 struct agi_cmd *cmd; 00450 AST_LIST_HEAD(, agi_cmd) *agi_commands; 00451 00452 ast_channel_lock(chan); 00453 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL); 00454 ast_channel_unlock(chan); 00455 if (!store) { 00456 ast_log(LOG_ERROR, "Hu? datastore disappeared at Async AGI on Channel %s!\n", chan->name); 00457 return NULL; 00458 } 00459 agi_commands = store->data; 00460 AST_LIST_LOCK(agi_commands); 00461 cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry); 00462 AST_LIST_UNLOCK(agi_commands); 00463 return cmd; 00464 }
| static int handle_answer | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1023 of file res_agi.c.
References ast_channel::_state, ast_agi_send(), ast_answer(), AST_STATE_UP, agi_state::fd, RESULT_FAILURE, and RESULT_SUCCESS.
01024 { 01025 int res = 0; 01026 01027 /* Answer the channel */ 01028 if (chan->_state != AST_STATE_UP) 01029 res = ast_answer(chan); 01030 01031 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01032 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01033 }
| static int handle_asyncagi_break | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1035 of file res_agi.c.
References ast_agi_send(), agi_state::fd, and RESULT_FAILURE.
01036 { 01037 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01038 return RESULT_FAILURE; 01039 }
| static int handle_autohangup | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1671 of file res_agi.c.
References ast_agi_send(), ast_channel_setwhentohangup_tv(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01672 { 01673 double timeout; 01674 struct timeval whentohangup = { 0, 0 }; 01675 01676 if (argc != 3) 01677 return RESULT_SHOWUSAGE; 01678 if (sscanf(argv[2], "%30lf", &timeout) != 1) 01679 return RESULT_SHOWUSAGE; 01680 if (timeout < 0) 01681 timeout = 0; 01682 if (timeout) { 01683 whentohangup.tv_sec = timeout; 01684 whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0; 01685 } 01686 ast_channel_setwhentohangup_tv(chan, whentohangup); 01687 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01688 return RESULT_SUCCESS; 01689 }
| static int handle_channelstatus | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1786 of file res_agi.c.
References ast_channel::_state, ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01787 { 01788 struct ast_channel *c; 01789 if (argc == 2) { 01790 /* no argument: supply info on the current channel */ 01791 ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state); 01792 return RESULT_SUCCESS; 01793 } else if (argc == 3) { 01794 /* one argument: look for info on the specified channel */ 01795 c = ast_get_channel_by_name_locked(argv[2]); 01796 if (c) { 01797 ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state); 01798 ast_channel_unlock(c); 01799 return RESULT_SUCCESS; 01800 } 01801 /* if we get this far no channel name matched the argument given */ 01802 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01803 return RESULT_SUCCESS; 01804 } else { 01805 return RESULT_SHOWUSAGE; 01806 } 01807 }
| 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 544 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.
00545 { 00546 struct ast_channel *chan; 00547 switch (cmd) { 00548 case CLI_INIT: 00549 e->command = "agi exec"; 00550 e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n" 00551 " Add AGI command to the execute queue of the specified channel in Async AGI\n"; 00552 return NULL; 00553 case CLI_GENERATE: 00554 if (a->pos == 2) 00555 return ast_complete_channels(a->line, a->word, a->pos, a->n, 2); 00556 return NULL; 00557 } 00558 00559 if (a->argc < 4) 00560 return CLI_SHOWUSAGE; 00561 chan = ast_get_channel_by_name_locked(a->argv[2]); 00562 if (!chan) { 00563 ast_log(LOG_WARNING, "Channel %s does not exists or cannot lock it\n", a->argv[2]); 00564 return CLI_FAILURE; 00565 } 00566 if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) { 00567 ast_log(LOG_WARNING, "failed to add AGI command to queue of channel %s\n", chan->name); 00568 ast_channel_unlock(chan); 00569 return CLI_FAILURE; 00570 } 00571 ast_log(LOG_DEBUG, "Added AGI command to channel %s queue\n", chan->name); 00572 ast_channel_unlock(chan); 00573 return CLI_SUCCESS; 00574 }
| static char* handle_cli_agi_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1951 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.
01952 { 01953 switch (cmd) { 01954 case CLI_INIT: 01955 e->command = "agi set debug [on|off]"; 01956 e->usage = 01957 "Usage: agi set debug [on|off]\n" 01958 " Enables/disables dumping of AGI transactions for\n" 01959 " debugging purposes.\n"; 01960 return NULL; 01961 01962 case CLI_GENERATE: 01963 return NULL; 01964 } 01965 01966 if (a->argc != e->args) 01967 return CLI_SHOWUSAGE; 01968 01969 if (strncasecmp(a->argv[3], "off", 3) == 0) { 01970 agidebug = 0; 01971 } else if (strncasecmp(a->argv[3], "on", 2) == 0) { 01972 agidebug = 1; 01973 } else { 01974 return CLI_SHOWUSAGE; 01975 } 01976 ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis"); 01977 return CLI_SUCCESS; 01978 }
| static char* handle_cli_agi_dump_html | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3188 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().
03189 { 03190 switch (cmd) { 03191 case CLI_INIT: 03192 e->command = "agi dump html"; 03193 e->usage = 03194 "Usage: agi dump html <filename>\n" 03195 " Dumps the AGI command list in HTML format to the given\n" 03196 " file.\n"; 03197 return NULL; 03198 case CLI_GENERATE: 03199 return NULL; 03200 } 03201 if (a->argc != e->args + 1) 03202 return CLI_SHOWUSAGE; 03203 03204 if (write_htmldump(a->argv[e->args]) < 0) { 03205 ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]); 03206 return CLI_SHOWUSAGE; 03207 } 03208 ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]); 03209 return CLI_SUCCESS; 03210 }
| static char* handle_cli_agi_show | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2996 of file res_agi.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_free, ast_join(), ast_malloc, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, agi_command::dead, description, agi_command::docsrc, ast_cli_args::fd, find_command(), help_workhorse(), MAX_CMD_LEN, S_OR, agi_command::seealso, agi_command::summary, agi_command::syntax, term_color(), agi_command::usage, and ast_cli_entry::usage.
02997 { 02998 struct agi_command *command; 02999 char fullcmd[MAX_CMD_LEN]; 03000 int error = 0; 03001 03002 switch (cmd) { 03003 case CLI_INIT: 03004 e->command = "agi show commands [topic]"; 03005 e->usage = 03006 "Usage: agi show commands [topic] <topic>\n" 03007 " When called with a topic as an argument, displays usage\n" 03008 " information on the given command. If called without a\n" 03009 " topic, it provides a list of AGI commands.\n"; 03010 case CLI_GENERATE: 03011 return NULL; 03012 } 03013 if (a->argc < e->args - 1 || (a->argc >= e->args && strcasecmp(a->argv[e->args - 1], "topic"))) 03014 return CLI_SHOWUSAGE; 03015 if (a->argc > e->args - 1) { 03016 command = find_command(a->argv + e->args, 1); 03017 if (command) { 03018 char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL; 03019 char info[30 + MAX_CMD_LEN]; /* '-= Info about...' */ 03020 char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS]; /* '-= Info about...' with colors */ 03021 char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */ 03022 char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Description]\n with colors */ 03023 char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Runs Dead]\n with colors */ 03024 char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS]; /* 'Yes' or 'No' with colors */ 03025 char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS]; /* [See Also]\n with colors */ 03026 char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */ 03027 size_t synlen, desclen, seealsolen, stxlen; 03028 03029 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle)); 03030 term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle)); 03031 term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle)); 03032 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle)); 03033 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle)); 03034 term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent)); 03035 03036 ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args); 03037 snprintf(info, sizeof(info), "\n -= Info about agi '%s' =- ", fullcmd); 03038 term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle)); 03039 #ifdef AST_XML_DOCS 03040 if (command->docsrc == AST_XML_DOC) { 03041 synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1); 03042 description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1); 03043 seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1); 03044 if (!seealso || !description || !synopsis) { 03045 error = 1; 03046 goto return_cleanup; 03047 } 03048 } else 03049 #endif 03050 { 03051 synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; 03052 synopsis = ast_malloc(synlen); 03053 03054 desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; 03055 description = ast_malloc(desclen); 03056 03057 seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; 03058 seealso = ast_malloc(seealsolen); 03059 03060 if (!synopsis || !description || !seealso) { 03061 error = 1; 03062 goto return_cleanup; 03063 } 03064 term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen); 03065 term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen); 03066 term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen); 03067 } 03068 03069 stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS; 03070 syntax = ast_malloc(stxlen); 03071 if (!syntax) { 03072 error = 1; 03073 goto return_cleanup; 03074 } 03075 term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen); 03076 03077 ast_cli(a->fd, "%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", infotitle, stxtitle, syntax, 03078 desctitle, description, syntitle, synopsis, deadtitle, deadcontent, 03079 seealsotitle, seealso); 03080 return_cleanup: 03081 ast_free(synopsis); 03082 ast_free(description); 03083 ast_free(syntax); 03084 ast_free(seealso); 03085 } else { 03086 if (find_command(a->argv + e->args, -1)) { 03087 return help_workhorse(a->fd, a->argv + e->args); 03088 } else { 03089 ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args); 03090 ast_cli(a->fd, "No such command '%s'.\n", fullcmd); 03091 } 03092 } 03093 } else { 03094 return help_workhorse(a->fd, NULL); 03095 } 03096 return (error ? CLI_FAILURE : CLI_SUCCESS); 03097 }
| static int handle_controlstreamfile | ( | 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_control_streamfile(), ast_strlen_zero(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, skipms, and stop.
01154 { 01155 int res = 0, skipms = 3000; 01156 char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */ 01157 01158 if (argc < 5 || argc > 9) { 01159 return RESULT_SHOWUSAGE; 01160 } 01161 01162 if (!ast_strlen_zero(argv[4])) { 01163 stop = argv[4]; 01164 } 01165 01166 if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) { 01167 return RESULT_SHOWUSAGE; 01168 } 01169 01170 if (argc > 6 && !ast_strlen_zero(argv[6])) { 01171 fwd = argv[6]; 01172 } 01173 01174 if (argc > 7 && !ast_strlen_zero(argv[7])) { 01175 rev = argv[7]; 01176 } 01177 01178 if (argc > 8 && !ast_strlen_zero(argv[8])) { 01179 suspend = argv[8]; 01180 } 01181 01182 res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL); 01183 01184 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01185 01186 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01187 }
| static int handle_dbdel | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1925 of file res_agi.c.
References ast_agi_send(), ast_db_del(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01926 { 01927 int res; 01928 01929 if (argc != 4) 01930 return RESULT_SHOWUSAGE; 01931 res = ast_db_del(argv[2], argv[3]); 01932 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01933 return RESULT_SUCCESS; 01934 }
| static int handle_dbdeltree | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1936 of file res_agi.c.
References ast_agi_send(), ast_db_deltree(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01937 { 01938 int res; 01939 01940 if ((argc < 3) || (argc > 4)) 01941 return RESULT_SHOWUSAGE; 01942 if (argc == 4) 01943 res = ast_db_deltree(argv[2], argv[3]); 01944 else 01945 res = ast_db_deltree(argv[2], NULL); 01946 01947 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01948 return RESULT_SUCCESS; 01949 }
| static int handle_dbget | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1881 of file res_agi.c.
References ast_agi_send(), ast_db_get(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_make_space(), ast_str_size(), ast_str_strlen(), ast_str_update(), buf, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01882 { 01883 int res; 01884 struct ast_str *buf; 01885 01886 if (argc != 4) 01887 return RESULT_SHOWUSAGE; 01888 01889 if (!(buf = ast_str_create(16))) { 01890 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01891 return RESULT_SUCCESS; 01892 } 01893 01894 do { 01895 res = ast_db_get(argv[2], argv[3], ast_str_buffer(buf), ast_str_size(buf)); 01896 ast_str_update(buf); 01897 if (ast_str_strlen(buf) < ast_str_size(buf) - 1) { 01898 break; 01899 } 01900 if (ast_str_make_space(&buf, ast_str_size(buf) * 2)) { 01901 break; 01902 } 01903 } while (1); 01904 01905 if (res) 01906 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01907 else 01908 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(buf)); 01909 01910 ast_free(buf); 01911 return RESULT_SUCCESS; 01912 }
| static int handle_dbput | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1914 of file res_agi.c.
References ast_agi_send(), ast_db_put(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01915 { 01916 int res; 01917 01918 if (argc != 5) 01919 return RESULT_SHOWUSAGE; 01920 res = ast_db_put(argv[2], argv[3], argv[4]); 01921 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1'); 01922 return RESULT_SUCCESS; 01923 }
| static int handle_exec | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1718 of file res_agi.c.
References ast_agi_send(), ast_clear_flag, ast_compat_res_agi, AST_FLAG_DISABLE_WORKAROUNDS, ast_log(), ast_masq_park_call(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_verb, agi_state::fd, LOG_WARNING, PARK_APP_NAME, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.
01719 { 01720 int res, workaround; 01721 struct ast_app *app_to_exec; 01722 01723 if (argc < 2) 01724 return RESULT_SHOWUSAGE; 01725 01726 ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : ""); 01727 01728 if ((app_to_exec = pbx_findapp(argv[1]))) { 01729 if(!strcasecmp(argv[1], PARK_APP_NAME)) { 01730 ast_masq_park_call(chan, NULL, 0, NULL); 01731 } 01732 if (!(workaround = ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS))) { 01733 ast_set_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS); 01734 } 01735 if (ast_compat_res_agi && argc >= 3 && !ast_strlen_zero(argv[2])) { 01736 char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr, *vptr; 01737 for (cptr = compat, vptr = argv[2]; *vptr; vptr++) { 01738 if (*vptr == ',') { 01739 *cptr++ = '\\'; 01740 *cptr++ = ','; 01741 } else if (*vptr == '|') { 01742 *cptr++ = ','; 01743 } else { 01744 *cptr++ = *vptr; 01745 } 01746 } 01747 *cptr = '\0'; 01748 res = pbx_exec(chan, app_to_exec, compat); 01749 } else { 01750 res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]); 01751 } 01752 if (!workaround) { 01753 ast_clear_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS); 01754 } 01755 } else { 01756 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]); 01757 res = -2; 01758 } 01759 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01760 01761 /* Even though this is wrong, users are depending upon this result. */ 01762 return res; 01763 }
| static int handle_getdata | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1431 of file res_agi.c.
References ast_agi_send(), ast_app_getdata_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01432 { 01433 int res, max, timeout; 01434 char data[1024]; 01435 01436 if (argc < 3) 01437 return RESULT_SHOWUSAGE; 01438 if (argc >= 4) 01439 timeout = atoi(argv[3]); 01440 else 01441 timeout = 0; 01442 if (argc >= 5) 01443 max = atoi(argv[4]); 01444 else 01445 max = 1024; 01446 res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl); 01447 if (res == 2) /* New command */ 01448 return RESULT_SUCCESS; 01449 else if (res == 1) 01450 ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data); 01451 else if (res < 0 ) 01452 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01453 else 01454 ast_agi_send(agi->fd, chan, "200 result=%s\n", data); 01455 return RESULT_SUCCESS; 01456 }
| 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 1239 of file res_agi.c.
References ast_agi_send(), ast_applystream(), ast_debug, ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verb, ast_waitfordigit_full(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, ast_pbx::dtimeoutms, agi_state::fd, ast_channel::language, LOG_WARNING, ast_channel::pbx, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.
01240 { 01241 int res, vres; 01242 struct ast_filestream *fs, *vfs; 01243 long sample_offset = 0, max_length; 01244 int timeout = 0; 01245 char *edigits = ""; 01246 01247 if ( argc < 4 || argc > 5 ) 01248 return RESULT_SHOWUSAGE; 01249 01250 if ( argv[3] ) 01251 edigits = argv[3]; 01252 01253 if ( argc == 5 ) 01254 timeout = atoi(argv[4]); 01255 else if (chan->pbx->dtimeoutms) { 01256 /* by default dtimeout is set to 5sec */ 01257 timeout = chan->pbx->dtimeoutms; /* in msec */ 01258 } 01259 01260 if (!(fs = ast_openstream(chan, argv[2], chan->language))) { 01261 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset); 01262 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]); 01263 return RESULT_SUCCESS; 01264 } 01265 01266 if ((vfs = ast_openvstream(chan, argv[2], chan->language))) 01267 ast_debug(1, "Ooh, found a video stream, too\n"); 01268 01269 ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout); 01270 01271 ast_seekstream(fs, 0, SEEK_END); 01272 max_length = ast_tellstream(fs); 01273 ast_seekstream(fs, sample_offset, SEEK_SET); 01274 res = ast_applystream(chan, fs); 01275 if (vfs) 01276 vres = ast_applystream(chan, vfs); 01277 ast_playstream(fs); 01278 if (vfs) 01279 ast_playstream(vfs); 01280 01281 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 01282 /* this is to check for if ast_waitstream closed the stream, we probably are at 01283 * the end of the stream, return that amount, else check for the amount */ 01284 sample_offset = (chan->stream)?ast_tellstream(fs):max_length; 01285 ast_stopstream(chan); 01286 if (res == 1) { 01287 /* Stop this command, don't print a result line, as there is a new command */ 01288 return RESULT_SUCCESS; 01289 } 01290 01291 /* If the user didnt press a key, wait for digitTimeout*/ 01292 if (res == 0 ) { 01293 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl); 01294 /* Make sure the new result is in the escape digits of the GET OPTION */ 01295 if ( !strchr(edigits,res) ) 01296 res=0; 01297 } 01298 01299 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset); 01300 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01301 }
| static int handle_getvariable | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1818 of file res_agi.c.
References ast_agi_send(), ast_func_read(), ast_strlen_zero(), agi_state::fd, pbx_retrieve_variable(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01819 { 01820 char *ret; 01821 char tempstr[1024]; 01822 01823 if (argc != 3) 01824 return RESULT_SHOWUSAGE; 01825 01826 /* check if we want to execute an ast_custom_function */ 01827 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) { 01828 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr; 01829 } else { 01830 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL); 01831 } 01832 01833 if (ret) 01834 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret); 01835 else 01836 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01837 01838 return RESULT_SUCCESS; 01839 }
| static int handle_getvariablefull | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1841 of file res_agi.c.
References ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, pbx_substitute_variables_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01842 { 01843 char tmp[4096]; 01844 struct ast_channel *chan2=NULL; 01845 01846 if ((argc != 4) && (argc != 5)) 01847 return RESULT_SHOWUSAGE; 01848 if (argc == 5) { 01849 chan2 = ast_get_channel_by_name_locked(argv[4]); 01850 } else { 01851 chan2 = chan; 01852 } 01853 if (chan2) { 01854 pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1); 01855 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp); 01856 } else { 01857 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01858 } 01859 if (chan2 && (chan2 != chan)) 01860 ast_channel_unlock(chan2); 01861 return RESULT_SUCCESS; 01862 }
| static int handle_hangup | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1691 of file res_agi.c.
References ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01692 { 01693 struct ast_channel *c; 01694 01695 if (argc == 1) { 01696 /* no argument: hangup the current channel */ 01697 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT); 01698 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01699 return RESULT_SUCCESS; 01700 } else if (argc == 2) { 01701 /* one argument: look for info on the specified channel */ 01702 c = ast_get_channel_by_name_locked(argv[1]); 01703 if (c) { 01704 /* we have a matching channel */ 01705 ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT); 01706 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01707 ast_channel_unlock(c); 01708 return RESULT_SUCCESS; 01709 } 01710 /* if we get this far no channel name matched the argument given */ 01711 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01712 return RESULT_SUCCESS; 01713 } else { 01714 return RESULT_SHOWUSAGE; 01715 } 01716 }
| static int handle_noop | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | arg, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1980 of file res_agi.c.
References ast_agi_send(), agi_state::fd, and RESULT_SUCCESS.
01981 { 01982 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01983 return RESULT_SUCCESS; 01984 }
| static int handle_recordfile | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1494 of file res_agi.c.
References ast_agi_send(), ast_applystream(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_get_threshold_from_settings(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate(), ast_log(), ast_read(), ast_seekstream(), ast_set_read_format(), ast_stream_rewind(), ast_streamfile(), ast_tellstream(), ast_truncstream(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), f, agi_state::fd, ast_frame::frametype, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, ast_frame::subclass, THRESHOLD_SILENCE, and ast_dsp::totalsilence.
01495 { 01496 struct ast_filestream *fs; 01497 struct ast_frame *f; 01498 struct timeval start; 01499 long sample_offset = 0; 01500 int res = 0; 01501 int ms; 01502 01503 struct ast_dsp *sildet=NULL; /* silence detector dsp */ 01504 int totalsilence = 0; 01505 int dspsilence = 0; 01506 int silence = 0; /* amount of silence to allow */ 01507 int gotsilence = 0; /* did we timeout for silence? */ 01508 char *silencestr = NULL; 01509 int rfmt = 0; 01510 01511 /* XXX EAGI FIXME XXX */ 01512 01513 if (argc < 6) 01514 return RESULT_SHOWUSAGE; 01515 if (sscanf(argv[5], "%30d", &ms) != 1) 01516 return RESULT_SHOWUSAGE; 01517 01518 if (argc > 6) 01519 silencestr = strchr(argv[6],'s'); 01520 if ((argc > 7) && (!silencestr)) 01521 silencestr = strchr(argv[7],'s'); 01522 if ((argc > 8) && (!silencestr)) 01523 silencestr = strchr(argv[8],'s'); 01524 01525 if (silencestr) { 01526 if (strlen(silencestr) > 2) { 01527 if ((silencestr[0] == 's') && (silencestr[1] == '=')) { 01528 silencestr++; 01529 silencestr++; 01530 if (silencestr) 01531 silence = atoi(silencestr); 01532 if (silence > 0) 01533 silence *= 1000; 01534 } 01535 } 01536 } 01537 01538 if (silence > 0) { 01539 rfmt = chan->readformat; 01540 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 01541 if (res < 0) { 01542 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 01543 return -1; 01544 } 01545 sildet = ast_dsp_new(); 01546 if (!sildet) { 01547 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 01548 return -1; 01549 } 01550 ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE)); 01551 } 01552 01553 /* backward compatibility, if no offset given, arg[6] would have been 01554 * caught below and taken to be a beep, else if it is a digit then it is a 01555 * offset */ 01556 if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '='))) 01557 res = ast_streamfile(chan, "beep", chan->language); 01558 01559 if ((argc > 7) && (!strchr(argv[7], '='))) 01560 res = ast_streamfile(chan, "beep", chan->language); 01561 01562 if (!res) 01563 res = ast_waitstream(chan, argv[4]); 01564 if (res) { 01565 ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset); 01566 } else { 01567 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE); 01568 if (!fs) { 01569 res = -1; 01570 ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res); 01571 if (sildet) 01572 ast_dsp_free(sildet); 01573 return RESULT_FAILURE; 01574 } 01575 01576 /* Request a video update */ 01577 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 01578 01579 chan->stream = fs; 01580 ast_applystream(chan,fs); 01581 /* really should have checks */ 01582 ast_seekstream(fs, sample_offset, SEEK_SET); 01583 ast_truncstream(fs); 01584 01585 start = ast_tvnow(); 01586 while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) { 01587 res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start)); 01588 if (res < 0) { 01589 ast_closestream(fs); 01590 ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset); 01591 if (sildet) 01592 ast_dsp_free(sildet); 01593 return RESULT_FAILURE; 01594 } 01595 f = ast_read(chan); 01596 if (!f) { 01597 ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset); 01598 ast_closestream(fs); 01599 if (sildet) 01600 ast_dsp_free(sildet); 01601 return RESULT_FAILURE; 01602 } 01603 switch(f->frametype) { 01604 case AST_FRAME_DTMF: 01605 if (strchr(argv[4], f->subclass)) { 01606 /* This is an interrupting chracter, so rewind to chop off any small 01607 amount of DTMF that may have been recorded 01608 */ 01609 ast_stream_rewind(fs, 200); 01610 ast_truncstream(fs); 01611 sample_offset = ast_tellstream(fs); 01612 ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset); 01613 ast_closestream(fs); 01614 ast_frfree(f); 01615 if (sildet) 01616 ast_dsp_free(sildet); 01617 return RESULT_SUCCESS; 01618 } 01619 break; 01620 case AST_FRAME_VOICE: 01621 ast_writestream(fs, f); 01622 /* this is a safe place to check progress since we know that fs 01623 * is valid after a write, and it will then have our current 01624 * location */ 01625 sample_offset = ast_tellstream(fs); 01626 if (silence > 0) { 01627 dspsilence = 0; 01628 ast_dsp_silence(sildet, f, &dspsilence); 01629 if (dspsilence) { 01630 totalsilence = dspsilence; 01631 } else { 01632 totalsilence = 0; 01633 } 01634 if (totalsilence > silence) { 01635 /* Ended happily with silence */ 01636 gotsilence = 1; 01637 break; 01638 } 01639 } 01640 break; 01641 case AST_FRAME_VIDEO: 01642 ast_writestream(fs, f); 01643 default: 01644 /* Ignore all other frames */ 01645 break; 01646 } 01647 ast_frfree(f); 01648 if (gotsilence) 01649 break; 01650 } 01651 01652 if (gotsilence) { 01653 ast_stream_rewind(fs, silence-1000); 01654 ast_truncstream(fs); 01655 sample_offset = ast_tellstream(fs); 01656 } 01657 ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset); 01658 ast_closestream(fs); 01659 } 01660 01661 if (silence > 0) { 01662 res = ast_set_read_format(chan, rfmt); 01663 if (res) 01664 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 01665 ast_dsp_free(sildet); 01666 } 01667 01668 return RESULT_SUCCESS; 01669 }
| static int handle_recvchar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1073 of file res_agi.c.
References ast_agi_send(), ast_recvchar(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01074 { 01075 int res; 01076 01077 if (argc != 3) 01078 return RESULT_SHOWUSAGE; 01079 01080 res = ast_recvchar(chan,atoi(argv[2])); 01081 if (res == 0) { 01082 ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res); 01083 return RESULT_SUCCESS; 01084 } 01085 if (res > 0) { 01086 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01087 return RESULT_SUCCESS; 01088 } 01089 ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res); 01090 return RESULT_FAILURE; 01091 }
| static int handle_recvtext | ( | 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_free, ast_recvtext(), buf, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01094 { 01095 char *buf; 01096 01097 if (argc != 3) 01098 return RESULT_SHOWUSAGE; 01099 01100 buf = ast_recvtext(chan, atoi(argv[2])); 01101 if (buf) { 01102 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf); 01103 ast_free(buf); 01104 } else { 01105 ast_agi_send(agi->fd, chan, "200 result=-1\n"); 01106 } 01107 return RESULT_SUCCESS; 01108 }
| static int handle_sayalpha | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1339 of file res_agi.c.
References ast_agi_send(), ast_say_character_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01340 { 01341 int res; 01342 01343 if (argc != 4) 01344 return RESULT_SHOWUSAGE; 01345 01346 res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01347 if (res == 1) /* New command */ 01348 return RESULT_SUCCESS; 01349 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01350 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01351 }
| static int handle_saydate | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1353 of file res_agi.c.
References ast_agi_send(), ast_say_date, agi_state::fd, ast_channel::language, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01354 { 01355 int res, num; 01356 01357 if (argc != 4) 01358 return RESULT_SHOWUSAGE; 01359 if (sscanf(argv[2], "%30d", &num) != 1) 01360 return RESULT_SHOWUSAGE; 01361 res = ast_say_date(chan, num, argv[3], chan->language); 01362 if (res == 1) 01363 return RESULT_SUCCESS; 01364 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01365 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01366 }
| static int handle_saydatetime | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1383 of file res_agi.c.
References ast_agi_send(), ast_get_time_t(), ast_say_date_with_format, ast_strlen_zero(), agi_state::fd, format, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01384 { 01385 int res = 0; 01386 time_t unixtime; 01387 char *format, *zone = NULL; 01388 01389 if (argc < 4) 01390 return RESULT_SHOWUSAGE; 01391 01392 if (argc > 4) { 01393 format = argv[4]; 01394 } else { 01395 /* XXX this doesn't belong here, but in the 'say' module */ 01396 if (!strcasecmp(chan->language, "de")) { 01397 format = "A dBY HMS"; 01398 } else { 01399 format = "ABdY 'digits/at' IMp"; 01400 } 01401 } 01402 01403 if (argc > 5 && !ast_strlen_zero(argv[5])) 01404 zone = argv[5]; 01405 01406 if (ast_get_time_t(argv[2], &unixtime, 0, NULL)) 01407 return RESULT_SHOWUSAGE; 01408 01409 res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone); 01410 if (res == 1) 01411 return RESULT_SUCCESS; 01412 01413 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01414 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01415 }
| static int handle_saydigits | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1323 of file res_agi.c.
References ast_agi_send(), ast_say_digit_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, ast_channel::language, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01324 { 01325 int res, num; 01326 01327 if (argc != 4) 01328 return RESULT_SHOWUSAGE; 01329 if (sscanf(argv[2], "%30d", &num) != 1) 01330 return RESULT_SHOWUSAGE; 01331 01332 res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01333 if (res == 1) /* New command */ 01334 return RESULT_SUCCESS; 01335 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01336 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01337 }
| static int handle_saynumber | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Say number in various language syntaxes.
Definition at line 1308 of file res_agi.c.
References ast_agi_send(), ast_say_number_full, agi_state::audio, agi_state::ctrl, agi_state::fd, ast_channel::language, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01309 { 01310 int res, num; 01311 01312 if (argc < 4 || argc > 5) 01313 return RESULT_SHOWUSAGE; 01314 if (sscanf(argv[2], "%30d", &num) != 1) 01315 return RESULT_SHOWUSAGE; 01316 res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl); 01317 if (res == 1) 01318 return RESULT_SUCCESS; 01319 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01320 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01321 }
| static int handle_sayphonetic | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1417 of file res_agi.c.
References ast_agi_send(), ast_say_phonetic_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01418 { 01419 int res; 01420 01421 if (argc != 4) 01422 return RESULT_SHOWUSAGE; 01423 01424 res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 01425 if (res == 1) /* New command */ 01426 return RESULT_SUCCESS; 01427 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01428 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01429 }
| static int handle_saytime | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1368 of file res_agi.c.
References ast_agi_send(), ast_say_time, agi_state::fd, ast_channel::language, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01369 { 01370 int res, num; 01371 01372 if (argc != 4) 01373 return RESULT_SHOWUSAGE; 01374 if (sscanf(argv[2], "%30d", &num) != 1) 01375 return RESULT_SHOWUSAGE; 01376 res = ast_say_time(chan, num, argv[3], chan->language); 01377 if (res == 1) 01378 return RESULT_SUCCESS; 01379 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01380 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01381 }
| static int handle_sendimage | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1137 of file res_agi.c.
References ast_agi_send(), ast_check_hangup(), ast_send_image(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01138 { 01139 int res; 01140 01141 if (argc != 3) { 01142 return RESULT_SHOWUSAGE; 01143 } 01144 01145 res = ast_send_image(chan, argv[2]); 01146 if (!ast_check_hangup(chan)) { 01147 res = 0; 01148 } 01149 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01150 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01151 }
| static int handle_sendtext | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1054 of file res_agi.c.
References ast_agi_send(), ast_sendtext(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01055 { 01056 int res; 01057 01058 if (argc != 3) 01059 return RESULT_SHOWUSAGE; 01060 01061 /* At the moment, the parser (perhaps broken) returns with 01062 the last argument PLUS the newline at the end of the input 01063 buffer. This probably needs to be fixed, but I wont do that 01064 because other stuff may break as a result. The right way 01065 would probably be to strip off the trailing newline before 01066 parsing, then here, add a newline at the end of the string 01067 before sending it to ast_sendtext --DUDE */ 01068 res = ast_sendtext(chan, argv[2]); 01069 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01070 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01071 }
| static int handle_setcallerid | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1765 of file res_agi.c.
References ast_agi_send(), ast_callerid_parse(), ast_copy_string(), ast_set_callerid(), ast_shrink_phone_number(), agi_state::fd, and RESULT_SUCCESS.
01766 { 01767 char tmp[256]=""; 01768 char *l = NULL, *n = NULL; 01769 01770 if (argv[2]) { 01771 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01772 ast_callerid_parse(tmp, &n, &l); 01773 if (l) 01774 ast_shrink_phone_number(l); 01775 else 01776 l = ""; 01777 if (!n) 01778 n = ""; 01779 ast_set_callerid(chan, l, n, NULL); 01780 } 01781 01782 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01783 return RESULT_SUCCESS; 01784 }
| static int handle_setcontext | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1458 of file res_agi.c.
References ast_agi_send(), ast_copy_string(), ast_channel::context, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01459 { 01460 01461 if (argc != 3) 01462 return RESULT_SHOWUSAGE; 01463 ast_copy_string(chan->context, argv[2], sizeof(chan->context)); 01464 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01465 return RESULT_SUCCESS; 01466 }
| static int handle_setextension | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1468 of file res_agi.c.
References ast_agi_send(), ast_copy_string(), ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01469 { 01470 if (argc != 3) 01471 return RESULT_SHOWUSAGE; 01472 ast_copy_string(chan->exten, argv[2], sizeof(chan->exten)); 01473 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01474 return RESULT_SUCCESS; 01475 }
| static int handle_setmusic | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1986 of file res_agi.c.
References ast_agi_send(), ast_moh_start(), ast_moh_stop(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01987 { 01988 if (argc < 3) { 01989 return RESULT_SHOWUSAGE; 01990 } 01991 if (!strncasecmp(argv[2], "on", 2)) 01992 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL); 01993 else if (!strncasecmp(argv[2], "off", 3)) 01994 ast_moh_stop(chan); 01995 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01996 return RESULT_SUCCESS; 01997 }
| static int handle_setpriority | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1477 of file res_agi.c.
References ast_agi_send(), ast_explicit_goto(), ast_findlabel_extension(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01478 { 01479 int pri; 01480 01481 if (argc != 3) 01482 return RESULT_SHOWUSAGE; 01483 01484 if (sscanf(argv[2], "%30d", &pri) != 1) { 01485 if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1) 01486 return RESULT_SHOWUSAGE; 01487 } 01488 01489 ast_explicit_goto(chan, NULL, NULL, pri); 01490 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01491 return RESULT_SUCCESS; 01492 }
| static int handle_setvariable | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1809 of file res_agi.c.
References ast_agi_send(), agi_state::fd, pbx_builtin_setvar_helper(), and RESULT_SUCCESS.
01810 { 01811 if (argv[3]) 01812 pbx_builtin_setvar_helper(chan, argv[2], argv[3]); 01813 01814 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01815 return RESULT_SUCCESS; 01816 }
| static int handle_speechactivategrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 2082 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_activate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02083 { 02084 if (argc != 4) 02085 return RESULT_SHOWUSAGE; 02086 02087 if (!agi->speech) { 02088 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02089 return RESULT_SUCCESS; 02090 } 02091 02092 if (ast_speech_grammar_activate(agi->speech, argv[3])) 02093 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02094 else 02095 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02096 02097 return RESULT_SUCCESS; 02098 }
| static int handle_speechcreate | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1999 of file res_agi.c.
References ast_agi_send(), AST_FORMAT_SLINEAR, ast_speech_new(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
02000 { 02001 /* If a structure already exists, return an error */ 02002 if (agi->speech) { 02003 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02004 return RESULT_SUCCESS; 02005 } 02006 02007 if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR))) 02008 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02009 else 02010 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02011 02012 return RESULT_SUCCESS; 02013 }
| static int handle_speechdeactivategrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 2100 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_deactivate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02101 { 02102 if (argc != 4) 02103 return RESULT_SHOWUSAGE; 02104 02105 if (!agi->speech) { 02106 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02107 return RESULT_SUCCESS; 02108 } 02109 02110 if (ast_speech_grammar_deactivate(agi->speech, argv[3])) 02111 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02112 else 02113 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02114 02115 return RESULT_SUCCESS; 02116 }
| static int handle_speechdestroy | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 2033 of file res_agi.c.
References ast_agi_send(), ast_speech_destroy(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.
02034 { 02035 if (agi->speech) { 02036 ast_speech_destroy(agi->speech); 02037 agi->speech = NULL; 02038 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02039 } else { 02040 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02041 } 02042 02043 return RESULT_SUCCESS; 02044 }
| static int handle_speechloadgrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 2046 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_load(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02047 { 02048 if (argc != 5) 02049 return RESULT_SHOWUSAGE; 02050 02051 if (!agi->speech) { 02052 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02053 return RESULT_SUCCESS; 02054 } 02055 02056 if (ast_speech_grammar_load(agi->speech, argv[3], argv[4])) 02057 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02058 else 02059 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02060 02061 return RESULT_SUCCESS; 02062 }
| static int handle_speechrecognize | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 2137 of file res_agi.c.
References ast_agi_send(), ast_build_string(), ast_clear_flag, AST_CONTROL_HANGUP, AST_FORMAT_SLINEAR, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_LIST_NEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_set_read_format(), ast_speech_change_state(), AST_SPEECH_QUIET, ast_speech_results_get(), ast_speech_start(), AST_SPEECH_STATE_DONE, AST_SPEECH_STATE_NOT_READY, AST_SPEECH_STATE_READY, AST_SPEECH_STATE_WAIT, ast_speech_write(), ast_stopstream(), ast_strlen_zero(), ast_tellstream(), ast_test_flag, ast_waitfor(), buf, ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, ast_speech_result::grammar, ast_channel::language, ast_speech_result::list, ast_speech::lock, ast_speech::processing_sound, prompt, ast_frame::ptr, ast_channel::readformat, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_speech::results, ast_channel::sched, ast_speech_result::score, agi_state::speech, speech_streamfile(), ast_speech::state, ast_channel::stream, ast_channel::streamid, ast_frame::subclass, ast_speech_result::text, and ast_channel::timingfunc.
02138 { 02139 struct ast_speech *speech = agi->speech; 02140 char *prompt, dtmf = 0, tmp[4096] = "", *buf = tmp; 02141 int timeout = 0, offset = 0, old_read_format = 0, res = 0, i = 0; 02142 long current_offset = 0; 02143 const char *reason = NULL; 02144 struct ast_frame *fr = NULL; 02145 struct ast_speech_result *result = NULL; 02146 size_t left = sizeof(tmp); 02147 time_t start = 0, current; 02148 02149 if (argc < 4) 02150 return RESULT_SHOWUSAGE; 02151 02152 if (!speech) { 02153 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02154 return RESULT_SUCCESS; 02155 } 02156 02157 prompt = argv[2]; 02158 timeout = atoi(argv[3]); 02159 02160 /* If offset is specified then convert from text to integer */ 02161 if (argc == 5) 02162 offset = atoi(argv[4]); 02163 02164 /* We want frames coming in signed linear */ 02165 old_read_format = chan->readformat; 02166 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 02167 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02168 return RESULT_SUCCESS; 02169 } 02170 02171 /* Setup speech structure */ 02172 if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) { 02173 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 02174 ast_speech_start(speech); 02175 } 02176 02177 /* Start playing prompt */ 02178 speech_streamfile(chan, prompt, chan->language, offset); 02179 02180 /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */ 02181 while (ast_strlen_zero(reason)) { 02182 /* Run scheduled items */ 02183 ast_sched_runq(chan->sched); 02184 02185 /* See maximum time of waiting */ 02186 if ((res = ast_sched_wait(chan->sched)) < 0) 02187 res = 1000; 02188 02189 /* Wait for frame */ 02190 if (ast_waitfor(chan, res) > 0) { 02191 if (!(fr = ast_read(chan))) { 02192 reason = "hangup"; 02193 break; 02194 } 02195 } 02196 02197 /* Perform timeout check */ 02198 if ((timeout > 0) && (start > 0)) { 02199 time(¤t); 02200 if ((current - start) >= timeout) { 02201 reason = "timeout"; 02202 if (fr) 02203 ast_frfree(fr); 02204 break; 02205 } 02206 } 02207 02208 /* Check the speech structure for any changes */ 02209 ast_mutex_lock(&speech->lock); 02210 02211 /* See if we need to quiet the audio stream playback */ 02212 if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) { 02213 current_offset = ast_tellstream(chan->stream); 02214 ast_stopstream(chan); 02215 ast_clear_flag(speech, AST_SPEECH_QUIET); 02216 } 02217 02218 /* Check each state */ 02219 switch (speech->state) { 02220 case AST_SPEECH_STATE_READY: 02221 /* If the stream is done, start timeout calculation */ 02222 if ((timeout > 0) && start == 0 && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) { 02223 ast_stopstream(chan); 02224 time(&start); 02225 } 02226 /* Write audio frame data into speech engine if possible */ 02227 if (fr && fr->frametype == AST_FRAME_VOICE) 02228 ast_speech_write(speech, fr->data.ptr, fr->datalen); 02229 break; 02230 case AST_SPEECH_STATE_WAIT: 02231 /* Cue waiting sound if not already playing */ 02232 if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) { 02233 ast_stopstream(chan); 02234 /* If a processing sound exists, or is not none - play it */ 02235 if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none")) 02236 speech_streamfile(chan, speech->processing_sound, chan->language, 0); 02237 } 02238 break; 02239 case AST_SPEECH_STATE_DONE: 02240 /* Get the results */ 02241 speech->results = ast_speech_results_get(speech); 02242 /* Change state to not ready */ 02243 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); 02244 reason = "speech"; 02245 break; 02246 default: 02247 break; 02248 } 02249 ast_mutex_unlock(&speech->lock); 02250 02251 /* Check frame for DTMF or hangup */ 02252 if (fr) { 02253 if (fr->frametype == AST_FRAME_DTMF) { 02254 reason = "dtmf"; 02255 dtmf = fr->subclass; 02256 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_HANGUP) { 02257 reason = "hangup"; 02258 } 02259 ast_frfree(fr); 02260 } 02261 } 02262 02263 if (!strcasecmp(reason, "speech")) { 02264 /* Build string containing speech results */ 02265 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) { 02266 /* Build result string */ 02267 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); 02268 /* Increment result count */ 02269 i++; 02270 } 02271 /* Print out */ 02272 ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp); 02273 } else if (!strcasecmp(reason, "dtmf")) { 02274 ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset); 02275 } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) { 02276 ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset); 02277 } else { 02278 ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset); 02279 } 02280 02281 return RESULT_SUCCESS; 02282 }
| static int handle_speechset | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 2015 of file res_agi.c.
References ast_agi_send(), ast_speech_change(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02016 { 02017 /* Check for minimum arguments */ 02018 if (argc != 3) 02019 return RESULT_SHOWUSAGE; 02020 02021 /* Check to make sure speech structure exists */ 02022 if (!agi->speech) { 02023 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02024 return RESULT_SUCCESS; 02025 } 02026 02027 ast_speech_change(agi->speech, argv[2], argv[3]); 02028 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02029 02030 return RESULT_SUCCESS; 02031 }
| static int handle_speechunloadgrammar | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 2064 of file res_agi.c.
References ast_agi_send(), ast_speech_grammar_unload(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.
02065 { 02066 if (argc != 4) 02067 return RESULT_SHOWUSAGE; 02068 02069 if (!agi->speech) { 02070 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02071 return RESULT_SUCCESS; 02072 } 02073 02074 if (ast_speech_grammar_unload(agi->speech, argv[3])) 02075 ast_agi_send(agi->fd, chan, "200 result=0\n"); 02076 else 02077 ast_agi_send(agi->fd, chan, "200 result=1\n"); 02078 02079 return RESULT_SUCCESS; 02080 }
| static int handle_streamfile | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1189 of file res_agi.c.
References ast_agi_send(), ast_applystream(), ast_debug, ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verb, ast_waitstream_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.
01190 { 01191 int res, vres; 01192 struct ast_filestream *fs, *vfs; 01193 long sample_offset = 0, max_length; 01194 char *edigits = ""; 01195 01196 if (argc < 4 || argc > 5) 01197 return RESULT_SHOWUSAGE; 01198 01199 if (argv[3]) 01200 edigits = argv[3]; 01201 01202 if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1)) 01203 return RESULT_SHOWUSAGE; 01204 01205 if (!(fs = ast_openstream(chan, argv[2], chan->language))) { 01206 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset); 01207 return RESULT_SUCCESS; 01208 } 01209 01210 if ((vfs = ast_openvstream(chan, argv[2], chan->language))) 01211 ast_debug(1, "Ooh, found a video stream, too\n"); 01212 01213 ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset); 01214 01215 ast_seekstream(fs, 0, SEEK_END); 01216 max_length = ast_tellstream(fs); 01217 ast_seekstream(fs, sample_offset, SEEK_SET); 01218 res = ast_applystream(chan, fs); 01219 if (vfs) 01220 vres = ast_applystream(chan, vfs); 01221 ast_playstream(fs); 01222 if (vfs) 01223 ast_playstream(vfs); 01224 01225 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 01226 /* this is to check for if ast_waitstream closed the stream, we probably are at 01227 * the end of the stream, return that amount, else check for the amount */ 01228 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; 01229 ast_stopstream(chan); 01230 if (res == 1) { 01231 /* Stop this command, don't print a result line, as there is a new command */ 01232 return RESULT_SUCCESS; 01233 } 01234 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset); 01235 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01236 }
| static int handle_tddmode | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1110 of file res_agi.c.
References ast_agi_send(), ast_channel_setoption(), AST_OPTION_TDD, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01111 { 01112 int res, x; 01113 01114 if (argc != 3) 01115 return RESULT_SHOWUSAGE; 01116 01117 if (!strncasecmp(argv[2],"on",2)) { 01118 x = 1; 01119 } else { 01120 x = 0; 01121 } 01122 if (!strncasecmp(argv[2],"mate",4)) { 01123 x = 2; 01124 } 01125 if (!strncasecmp(argv[2],"tdd",3)) { 01126 x = 1; 01127 } 01128 res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0); 01129 if (res != RESULT_SUCCESS) { 01130 ast_agi_send(agi->fd, chan, "200 result=0\n"); 01131 } else { 01132 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01133 } 01134 return RESULT_SUCCESS; 01135 }
| static int handle_verbose | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char ** | argv | |||
| ) | [static] |
Definition at line 1864 of file res_agi.c.
References ast_agi_send(), ast_verb, ast_channel::data, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01865 { 01866 int level = 0; 01867 01868 if (argc < 2) 01869 return RESULT_SHOWUSAGE; 01870 01871 if (argv[2]) 01872 sscanf(argv[2], "%30d", &level); 01873 01874 ast_verb(level, "%s: %s\n", chan->data, argv[1]); 01875 01876 ast_agi_send(agi->fd, chan, "200 result=1\n"); 01877 01878 return RESULT_SUCCESS; 01879 }
| static int handle_waitfordigit | ( | struct ast_channel * | chan, | |
| AGI * | agi, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1041 of file res_agi.c.
References ast_agi_send(), ast_waitfordigit_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01042 { 01043 int res, to; 01044 01045 if (argc != 4) 01046 return RESULT_SHOWUSAGE; 01047 if (sscanf(argv[3], "%30d", &to) != 1) 01048 return RESULT_SHOWUSAGE; 01049 res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl); 01050 ast_agi_send(agi->fd, chan, "200 result=%d\n", res); 01051 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 01052 }
| static char* help_workhorse | ( | int | fd, | |
| char * | match[] | |||
| ) | [static] |
Definition at line 2530 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, MAX_CMD_LEN, S_OR, and agi_command::summary.
Referenced by handle_cli_agi_show().
02531 { 02532 char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN]; 02533 struct agi_command *e; 02534 02535 if (match) 02536 ast_join(matchstr, sizeof(matchstr), match); 02537 02538 ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description"); 02539 AST_RWLIST_RDLOCK(&agi_commands); 02540 AST_RWLIST_TRAVERSE(&agi_commands, e, list) { 02541 if (!e->cmda[0]) 02542 break; 02543 /* Hide commands that start with '_' */ 02544 if ((e->cmda[0])[0] == '_') 02545 continue; 02546 ast_join(fullcmd, sizeof(fullcmd), e->cmda); 02547 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr))) 02548 continue; 02549 ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, S_OR(e->summary, "Not available")); 02550 } 02551 AST_RWLIST_UNLOCK(&agi_commands); 02552 02553 return CLI_SUCCESS; 02554 }
| static enum agi_result launch_asyncagi | ( | struct ast_channel * | chan, | |
| char * | argv[], | |||
| int * | efd | |||
| ) | [static] |
Definition at line 617 of file res_agi.c.
References add_to_agi(), AGI_BUF_SIZE, agi_handle_command(), AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS_ASYNC, AMI_BUF_SIZE, ast_check_hangup(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_frfree, ast_log(), ast_read(), ast_speech_destroy(), ast_strlen_zero(), ast_uri_encode(), ast_waitfor(), agi_state::audio, agi_cmd::cmd_buffer, agi_cmd::cmd_id, agi_state::ctrl, EVENT_FLAG_AGI, f, agi_state::fast, agi_state::fd, ast_frame::frametype, free_agi_cmd(), get_agi_cmd(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, manager_event, ast_channel::name, quit, setup_env(), agi_state::speech, and ast_frame::subclass.
Referenced by launch_script().
00618 { 00619 /* This buffer sizes might cause truncation if the AGI command writes more data 00620 than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command 00621 that writes a response larger than 1024 bytes?, I don't think so, most of 00622 them are just result=blah stuff. However probably if GET VARIABLE is called 00623 and the variable has large amount of data, that could be a problem. We could 00624 make this buffers dynamic, but let's leave that as a second step. 00625 00626 AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe 00627 number. Some characters of AGI buf will be url encoded to be sent to manager 00628 clients. An URL encoded character will take 3 bytes, but again, to cause 00629 truncation more than about 70% of the AGI buffer should be URL encoded for 00630 that to happen. Not likely at all. 00631 00632 On the other hand. I wonder if read() could eventually return less data than 00633 the amount already available in the pipe? If so, how to deal with that? 00634 So far, my tests on Linux have not had any problems. 00635 */ 00636 #define AGI_BUF_SIZE 1024 00637 #define AMI_BUF_SIZE 2048 00638 struct ast_frame *f; 00639 struct agi_cmd *cmd; 00640 int res, fds[2]; 00641 int timeout = 100; 00642 char agi_buffer[AGI_BUF_SIZE + 1]; 00643 char ami_buffer[AMI_BUF_SIZE]; 00644 enum agi_result returnstatus = AGI_RESULT_SUCCESS_ASYNC; 00645 AGI async_agi; 00646 00647 if (efd) { 00648 ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n"); 00649 return AGI_RESULT_FAILURE; 00650 } 00651 00652 /* add AsyncAGI datastore to the channel */ 00653 if (add_to_agi(chan)) { 00654 ast_log(LOG_ERROR, "failed to start Async AGI on channel %s\n", chan->name); 00655 return AGI_RESULT_FAILURE; 00656 } 00657 00658 /* this pipe allows us to create a "fake" AGI struct to use 00659 the AGI commands */ 00660 res = pipe(fds); 00661 if (res) { 00662 ast_log(LOG_ERROR, "failed to create Async AGI pipe\n"); 00663 /* intentionally do not remove datastore, added with 00664 add_to_agi(), from channel. It will be removed when 00665 the channel is hung up anyways */ 00666 return AGI_RESULT_FAILURE; 00667 } 00668 00669 /* handlers will get the pipe write fd and we read the AGI responses 00670 from the pipe read fd */ 00671 async_agi.fd = fds[1]; 00672 async_agi.ctrl = fds[1]; 00673 async_agi.audio = -1; /* no audio support */ 00674 async_agi.fast = 0; 00675 async_agi.speech = NULL; 00676 00677 /* notify possible manager users of a new channel ready to 00678 receive commands */ 00679 setup_env(chan, "async", fds[1], 0, 0, NULL); 00680 /* read the environment */ 00681 res = read(fds[0], agi_buffer, AGI_BUF_SIZE); 00682 if (!res) { 00683 ast_log(LOG_ERROR, "failed to read from Async AGI pipe on channel %s\n", chan->name); 00684 returnstatus = AGI_RESULT_FAILURE; 00685 goto quit; 00686 } 00687 agi_buffer[res] = '\0'; 00688 /* encode it and send it thru the manager so whoever is going to take 00689 care of AGI commands on this channel can decide which AGI commands 00690 to execute based on the setup info */ 00691 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1); 00692 manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Start\r\nChannel: %s\r\nEnv: %s\r\n", chan->name, ami_buffer); 00693 while (1) { 00694 /* bail out if we need to hangup */ 00695 if (ast_check_hangup(chan)) { 00696 ast_log(LOG_DEBUG, "ast_check_hangup returned true on chan %s\n", chan->name); 00697 break; 00698 } 00699 /* retrieve a command 00700 (commands are added via the manager or the cli threads) */ 00701 cmd = get_agi_cmd(chan); 00702 if (cmd) { 00703 /* OK, we have a command, let's call the 00704 command handler. */ 00705 res = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0); 00706 if (res < 0) { 00707 free_agi_cmd(cmd); 00708 break; 00709 } 00710 /* the command handler must have written to our fake 00711 AGI struct fd (the pipe), let's read the response */ 00712 res = read(fds[0], agi_buffer, AGI_BUF_SIZE); 00713 if (!res) { 00714 returnstatus = AGI_RESULT_FAILURE; 00715 ast_log(LOG_ERROR, "failed to read from AsyncAGI pipe on channel %s\n", chan->name); 00716 free_agi_cmd(cmd); 00717 break; 00718 } 00719 /* we have a response, let's send the response thru the 00720 manager. Include the CommandID if it was specified 00721 when the command was added */ 00722 agi_buffer[res] = '\0'; 00723 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1); 00724 if (ast_strlen_zero(cmd->cmd_id)) 00725 manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Exec\r\nChannel: %s\r\nResult: %s\r\n", chan->name, ami_buffer); 00726 else 00727 manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Exec\r\nChannel: %s\r\nCommandID: %s\r\nResult: %s\r\n", chan->name, cmd->cmd_id, ami_buffer); 00728 free_agi_cmd(cmd); 00729 } else { 00730 /* no command so far, wait a bit for a frame to read */ 00731 res = ast_waitfor(chan, timeout); 00732 if (res < 0) { 00733 ast_log(LOG_DEBUG, "ast_waitfor returned <= 0 on chan %s\n", chan->name); 00734 break; 00735 } 00736 if (res == 0) 00737 continue; 00738 f = ast_read(chan); 00739 if (!f) { 00740 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 00741 returnstatus = AGI_RESULT_HANGUP; 00742 break; 00743 } 00744 /* is there any other frame we should care about 00745 besides AST_CONTROL_HANGUP? */ 00746 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 00747 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 00748 ast_frfree(f); 00749 break; 00750 } 00751 ast_frfree(f); 00752 } 00753 } 00754 00755 if (async_agi.speech) { 00756 ast_speech_destroy(async_agi.speech); 00757 } 00758 quit: 00759 /* notify manager users this channel cannot be 00760 controlled anymore by Async AGI */ 00761 manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: End\r\nChannel: %s\r\n", chan->name); 00762 00763 /* close the pipe */ 00764 close(fds[0]); 00765 close(fds[1]); 00766 00767 /* intentionally don't get rid of the datastore. So commands can be 00768 still in the queue in case AsyncAGI gets called again. 00769 Datastore destructor will be called on channel destroy anyway */ 00770 00771 return returnstatus; 00772 00773 #undef AGI_BUF_SIZE 00774 #undef AMI_BUF_SIZE 00775 }
| static enum agi_result launch_netscript | ( | char * | agiurl, | |
| char * | argv[], | |||
| int * | fds, | |||
| int * | efd, | |||
| int * | opid | |||
| ) | [static] |
Definition at line 779 of file res_agi.c.
References AGI_PORT, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS_FAST, ast_agi_send(), ast_debug, ast_gethostbyname(), ast_log(), ast_poll, ast_strlen_zero(), errno, hp, LOG_WARNING, MAX_AGI_CONNECT, and s.
Referenced by launch_script().
00780 { 00781 int s, flags, res, port = AGI_PORT; 00782 struct pollfd pfds[1]; 00783 char *host, *c, *script = ""; 00784 struct sockaddr_in addr_in; 00785 struct hostent *hp; 00786 struct ast_hostent ahp; 00787 00788 /* agiusl is "agi://host.domain[:port][/script/name]" */ 00789 host = ast_strdupa(agiurl + 6); /* Remove agi:// */ 00790 /* Strip off any script name */ 00791 if ((c = strchr(host, '/'))) { 00792 *c = '\0'; 00793 c++; 00794 script = c; 00795 } 00796 if ((c = strchr(host, ':'))) { 00797 *c = '\0'; 00798 c++; 00799 port = atoi(c); 00800 } 00801 if (efd) { 00802 ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n"); 00803 return -1; 00804 } 00805 if (!(hp = ast_gethostbyname(host, &ahp))) { 00806 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host); 00807 return -1; 00808 } 00809 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00810 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 00811 return -1; 00812 } 00813 if ((flags = fcntl(s, F_GETFL)) < 0) { 00814 ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno)); 00815 close(s); 00816 return -1; 00817 } 00818 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { 00819 ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno)); 00820 close(s); 00821 return -1; 00822 } 00823 memset(&addr_in, 0, sizeof(addr_in)); 00824 addr_in.sin_family = AF_INET; 00825 addr_in.sin_port = htons(port); 00826 memcpy(&addr_in.sin_addr, hp->h_addr, sizeof(addr_in.sin_addr)); 00827 if (connect(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) && (errno != EINPROGRESS)) { 00828 ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno)); 00829 close(s); 00830 return AGI_RESULT_FAILURE; 00831 } 00832 00833 pfds[0].fd = s; 00834 pfds[0].events = POLLOUT; 00835 while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) { 00836 if (errno != EINTR) { 00837 if (!res) { 00838 ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n", 00839 agiurl, MAX_AGI_CONNECT); 00840 } else 00841 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 00842 close(s); 00843 return AGI_RESULT_FAILURE; 00844 } 00845 } 00846 00847 if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) { 00848 if (errno != EINTR) { 00849 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 00850 close(s); 00851 return AGI_RESULT_FAILURE; 00852 } 00853 } 00854 00855 /* If we have a script parameter, relay it to the fastagi server */ 00856 /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */ 00857 if (!ast_strlen_zero(script)) 00858 ast_agi_send(s, NULL, "agi_network_script: %s\n", script); 00859 00860 ast_debug(4, "Wow, connected!\n"); 00861 fds[0] = s; 00862 fds[1] = s; 00863 *opid = -1; 00864 return AGI_RESULT_SUCCESS_FAST; 00865 }
| static enum agi_result launch_script | ( | struct ast_channel * | chan, | |
| char * | script, | |||
| char * | argv[], | |||
| int * | fds, | |||
| int * | efd, | |||
| int * | opid | |||
| ) | [static] |
Definition at line 867 of file res_agi.c.
References AGI_RESULT_FAILURE, AGI_RESULT_NOTFOUND, AGI_RESULT_SUCCESS, ast_child_verbose(), ast_close_fds_above_n(), ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_CONFIG_FILE, ast_config_AST_DATA_DIR, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_MONITOR_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_VAR_DIR, ast_log(), ast_safe_fork(), ast_set_priority(), ast_verb, errno, launch_asyncagi(), launch_netscript(), and LOG_WARNING.
Referenced by agi_exec_full().
00868 { 00869 char tmp[256]; 00870 int pid, toast[2], fromast[2], audio[2], res; 00871 struct stat st; 00872 00873 if (!strncasecmp(script, "agi://", 6)) 00874 return launch_netscript(script, argv, fds, efd, opid); 00875 if (!strncasecmp(script, "agi:async", sizeof("agi:async")-1)) 00876 return launch_asyncagi(chan, argv, efd); 00877 00878 if (script[0] != '/') { 00879 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script); 00880 script = tmp; 00881 } 00882 00883 /* Before even trying let's see if the file actually exists */ 00884 if (stat(script, &st)) { 00885 ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script); 00886 return AGI_RESULT_NOTFOUND; 00887 } 00888 00889 if (pipe(toast)) { 00890 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno)); 00891 return AGI_RESULT_FAILURE; 00892 } 00893 if (pipe(fromast)) { 00894 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno)); 00895 close(toast[0]); 00896 close(toast[1]); 00897 return AGI_RESULT_FAILURE; 00898 } 00899 if (efd) { 00900 if (pipe(audio)) { 00901 ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno)); 00902 close(fromast[0]); 00903 close(fromast[1]); 00904 close(toast[0]); 00905 close(toast[1]); 00906 return AGI_RESULT_FAILURE; 00907 } 00908 res = fcntl(audio[1], F_GETFL); 00909 if (res > -1) 00910 res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK); 00911 if (res < 0) { 00912 ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno)); 00913 close(fromast[0]); 00914 close(fromast[1]); 00915 close(toast[0]); 00916 close(toast[1]); 00917 close(audio[0]); 00918 close(audio[1]); 00919 return AGI_RESULT_FAILURE; 00920 } 00921 } 00922 00923 if ((pid = ast_safe_fork(1)) < 0) { 00924 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); 00925 return AGI_RESULT_FAILURE; 00926 } 00927 if (!pid) { 00928 /* Pass paths to AGI via environmental variables */ 00929 setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1); 00930 setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1); 00931 setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1); 00932 setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1); 00933 setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1); 00934 setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1); 00935 setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1); 00936 setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1); 00937 setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1); 00938 setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1); 00939 setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1); 00940 00941 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */ 00942 ast_set_priority(0); 00943 00944 /* Redirect stdin and out, provide enhanced audio channel if desired */ 00945 dup2(fromast[0], STDIN_FILENO); 00946 dup2(toast[1], STDOUT_FILENO); 00947 if (efd) 00948 dup2(audio[0], STDERR_FILENO + 1); 00949 else 00950 close(STDERR_FILENO + 1); 00951 00952 /* Close everything but stdin/out/error */ 00953 ast_close_fds_above_n(STDERR_FILENO + 1); 00954 00955 /* Execute script */ 00956 /* XXX argv should be deprecated in favor of passing agi_argX paramaters */ 00957 execv(script, argv); 00958 /* Can't use ast_log since FD's are closed */ 00959 ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno)); 00960 /* Special case to set status of AGI to failure */ 00961 fprintf(stdout, "failure\n"); 00962 fflush(stdout); 00963 _exit(1); 00964 } 00965 ast_verb(3, "Launched AGI Script %s\n", script); 00966 fds[0] = toast[0]; 00967 fds[1] = fromast[1]; 00968 if (efd) 00969 *efd = audio[1]; 00970 /* close what we're not using in the parent */ 00971 close(toast[1]); 00972 close(fromast[0]); 00973 00974 if (efd) 00975 close(audio[0]); 00976 00977 *opid = pid; 00978 return AGI_RESULT_SUCCESS; 00979 }
| static int load_module | ( | void | ) | [static] |
Definition at line 3335 of file res_agi.c.
References action_add_agi_cmd(), agi_exec(), ARRAY_LEN, ast_agi_register_multiple(), ast_cli_register_multiple(), ast_manager_register2(), ast_register_application, cli_agi, commands, deadagi_exec(), eagi_exec(), EVENT_FLAG_AGI, and mandescr_asyncagi.
03336 { 03337 ast_cli_register_multiple(cli_agi, ARRAY_LEN(cli_agi)); 03338 /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as 03339 no other commands have been registered yet 03340 */ 03341 (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 03342 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip); 03343 ast_register_application(eapp, eagi_exec, esynopsis, descrip); 03344 ast_manager_register2("AGI", EVENT_FLAG_AGI, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi); 03345 return ast_register_application(app, agi_exec, synopsis, descrip); 03346 }
| static int parse_args | ( | char * | s, | |
| int * | max, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 2714 of file res_agi.c.
References ast_log(), LOG_WARNING, and MAX_ARGS.
Referenced by agi_handle_command().
02715 { 02716 int x = 0, quoted = 0, escaped = 0, whitespace = 1; 02717 char *cur; 02718 02719 cur = s; 02720 while(*s) { 02721 switch(*s) { 02722 case '"': 02723 /* If it's escaped, put a literal quote */ 02724 if (escaped) 02725 goto normal; 02726 else 02727 quoted = !quoted; 02728 if (quoted && whitespace) { 02729 /* If we're starting a quote, coming off white space start a new word, too */ 02730 argv[x++] = cur; 02731 whitespace=0; 02732 } 02733 escaped = 0; 02734 break; 02735 case ' ': 02736 case '\t': 02737 if (!quoted && !escaped) { 02738 /* If we're not quoted, mark this as whitespace, and 02739 end the previous argument */ 02740 whitespace = 1; 02741 *(cur++) = '\0'; 02742 } else 02743 /* Otherwise, just treat it as anything else */ 02744 goto normal; 02745 break; 02746 case '\\': 02747 /* If we're escaped, print a literal, otherwise enable escaping */ 02748 if (escaped) { 02749 goto normal; 02750 } else { 02751 escaped=1; 02752 } 02753 break; 02754 default: 02755 normal: 02756 if (whitespace) { 02757 if (x >= MAX_ARGS -1) { 02758 ast_log(LOG_WARNING, "Too many arguments, truncating\n"); 02759 break; 02760 } 02761 /* Coming off of whitespace, start the next argument */ 02762 argv[x++] = cur; 02763 whitespace=0; 02764 } 02765 *(cur++) = *s; 02766 escaped=0; 02767 } 02768 s++; 02769 } 02770 /* Null terminate */ 02771 *(cur++) = '\0'; 02772 argv[x] = NULL; 02773 *max = x; 02774 return 0; 02775 }
| 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 2853 of file res_agi.c.
References AGI_BUF_LEN, agi_handle_command(), AGI_NANDFS_RETRY, AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS, ast_channel_lock, ast_channel_unlock, ast_debug, ast_false(), AST_FRAME_VOICE, ast_frfree, ast_log(), ast_read(), ast_speech_destroy(), ast_strlen_zero(), ast_verb, ast_verbose, ast_waitfor_nandfds(), agi_state::audio, buf, agi_state::ctrl, ast_frame::data, ast_frame::datalen, errno, f, agi_state::fast, agi_state::fd, ast_frame::frametype, len(), LOG_WARNING, ast_channel::name, pbx_builtin_getvar_helper(), ast_frame::ptr, setup_env(), and agi_state::speech.
Referenced by agi_exec_full().
02854 { 02855 struct ast_channel *c; 02856 int outfd, ms, needhup = 0; 02857 enum agi_result returnstatus = AGI_RESULT_SUCCESS; 02858 struct ast_frame *f; 02859 char buf[AGI_BUF_LEN]; 02860 char *res = NULL; 02861 FILE *readf; 02862 /* how many times we'll retry if ast_waitfor_nandfs will return without either 02863 channel or file descriptor in case select is interrupted by a system call (EINTR) */ 02864 int retry = AGI_NANDFS_RETRY; 02865 int send_sighup; 02866 const char *sighup_str; 02867 02868 ast_channel_lock(chan); 02869 sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP"); 02870 send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str); 02871 ast_channel_unlock(chan); 02872 02873 if (!(readf = fdopen(agi->ctrl, "r"))) { 02874 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n"); 02875 if (send_sighup && pid > -1) 02876 kill(pid, SIGHUP); 02877 close(agi->ctrl); 02878 return AGI_RESULT_FAILURE; 02879 } 02880 02881 setlinebuf(readf); 02882 setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv); 02883 for (;;) { 02884 if (needhup) { 02885 needhup = 0; 02886 dead = 1; 02887 if (send_sighup) { 02888 if (pid > -1) { 02889 kill(pid, SIGHUP); 02890 } else if (agi->fast) { 02891 send(agi->ctrl, "HANGUP\n", 7, MSG_OOB); 02892 } 02893 } 02894 } 02895 ms = -1; 02896 c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms); 02897 if (c) { 02898 retry = AGI_NANDFS_RETRY; 02899 /* Idle the channel until we get a command */ 02900 f = ast_read(c); 02901 if (!f) { 02902 ast_debug(1, "%s hungup\n", chan->name); 02903 returnstatus = AGI_RESULT_HANGUP; 02904 needhup = 1; 02905 continue; 02906 } else { 02907 /* If it's voice, write it to the audio pipe */ 02908 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) { 02909 /* Write, ignoring errors */ 02910 if (write(agi->audio, f->data.ptr, f->datalen) < 0) { 02911 } 02912 } 02913 ast_frfree(f); 02914 } 02915 } else if (outfd > -1) { 02916 size_t len = sizeof(buf); 02917 size_t buflen = 0; 02918 02919 retry = AGI_NANDFS_RETRY; 02920 buf[0] = '\0'; 02921 02922 while (buflen < (len - 1)) { 02923 res = fgets(buf + buflen, len, readf); 02924 if (feof(readf)) 02925 break; 02926 if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN))) 02927 break; 02928 if (res != NULL && !agi->fast) 02929 break; 02930 buflen = strlen(buf); 02931 if (buflen && buf[buflen - 1] == '\n') 02932 break; 02933 len -= buflen; 02934 if (agidebug) 02935 ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno)); 02936 } 02937 02938 if (!buf[0]) { 02939 /* Program terminated */ 02940 if (returnstatus) { 02941 returnstatus = -1; 02942 } 02943 ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", chan->name, request, returnstatus); 02944 if (pid > 0) 02945 waitpid(pid, status, 0); 02946 /* No need to kill the pid anymore, since they closed us */ 02947 pid = -1; 02948 break; 02949 } 02950 02951 /* Special case for inability to execute child process */ 02952 if (*buf && strncasecmp(buf, "failure", 7) == 0) { 02953 returnstatus = AGI_RESULT_FAILURE; 02954 break; 02955 } 02956 02957 /* get rid of trailing newline, if any */ 02958 if (*buf && buf[strlen(buf) - 1] == '\n') 02959 buf[strlen(buf) - 1] = 0; 02960 if (agidebug) 02961 ast_verbose("<%s>AGI Rx << %s\n", chan->name, buf); 02962 returnstatus |= agi_handle_command(chan, agi, buf, dead); 02963 /* If the handle_command returns -1, we need to stop */ 02964 if (returnstatus < 0) { 02965 needhup = 1; 02966 continue; 02967 } 02968 } else { 02969 if (--retry <= 0) { 02970 ast_log(LOG_WARNING, "No channel, no fd?\n"); 02971 returnstatus = AGI_RESULT_FAILURE; 02972 break; 02973 } 02974 } 02975 } 02976 if (agi->speech) { 02977 ast_speech_destroy(agi->speech); 02978 } 02979 /* Notify process */ 02980 if (send_sighup) { 02981 if (pid > -1) { 02982 if (kill(pid, SIGHUP)) { 02983 ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno)); 02984 } else { /* Give the process a chance to die */ 02985 usleep(1); 02986 } 02987 waitpid(pid, status, WNOHANG); 02988 } else if (agi->fast) { 02989 send(agi->ctrl, "HANGUP\n", 7, MSG_OOB); 02990 } 02991 } 02992 fclose(readf); 02993 return returnstatus; 02994 }
| static void setup_env | ( | struct ast_channel * | chan, | |
| char * | request, | |||
| int | fd, | |||
| int | enhanced, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 981 of file res_agi.c.
References ast_channel::accountcode, ast_agi_send(), ast_get_version(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, ast_channel::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().
00982 { 00983 int count; 00984 00985 /* Print initial environment, with agi_request always being the first 00986 thing */ 00987 ast_agi_send(fd, chan, "agi_request: %s\n", request); 00988 ast_agi_send(fd, chan, "agi_channel: %s\n", chan->name); 00989 ast_agi_send(fd, chan, "agi_language: %s\n", chan->language); 00990 ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type); 00991 ast_agi_send(fd, chan, "agi_uniqueid: %s\n", chan->uniqueid); 00992 ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version()); 00993 00994 /* ANI/DNIS */ 00995 ast_agi_send(fd, chan, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown")); 00996 ast_agi_send(fd, chan, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown")); 00997 ast_agi_send(fd, chan, "agi_callingpres: %d\n", chan->cid.cid_pres); 00998 ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->cid.cid_ani2); 00999 ast_agi_send(fd, chan, "agi_callington: %d\n", chan->cid.cid_ton); 01000 ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->cid.cid_tns); 01001 ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown")); 01002 ast_agi_send(fd, chan, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown")); 01003 01004 /* Context information */ 01005 ast_agi_send(fd, chan, "agi_context: %s\n", chan->context); 01006 ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten); 01007 ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority); 01008 ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0"); 01009 01010 /* User information */ 01011 ast_agi_send(fd, chan, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : ""); 01012 ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self()); 01013 01014 /* Send any parameters to the fastagi server that have been passed via the agi application */ 01015 /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */ 01016 for(count = 1; count < argc; count++) 01017 ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]); 01018 01019 /* End with empty return */ 01020 ast_agi_send(fd, chan, "\n"); 01021 }
| static int speech_streamfile | ( | struct ast_channel * | chan, | |
| const char * | filename, | |||
| const char * | preflang, | |||
| int | offset | |||
| ) | [static] |
Definition at line 2118 of file res_agi.c.
References ast_applystream(), ast_openstream(), ast_playstream(), and ast_seekstream().
Referenced by handle_speechrecognize().
02119 { 02120 struct ast_filestream *fs = NULL; 02121 02122 if (!(fs = ast_openstream(chan, filename, preflang))) 02123 return -1; 02124 02125 if (offset) 02126 ast_seekstream(fs, offset, SEEK_SET); 02127 02128 if (ast_applystream(chan, fs)) 02129 return -1; 02130 02131 if (ast_playstream(fs)) 02132 return -1; 02133 02134 return 0; 02135 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 3322 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.
03323 { 03324 ast_cli_unregister_multiple(cli_agi, ARRAY_LEN(cli_agi)); 03325 /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as 03326 we know that these commands were registered by this module and are still registered 03327 */ 03328 (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands)); 03329 ast_unregister_application(eapp); 03330 ast_unregister_application(deadapp); 03331 ast_manager_unregister("AGI"); 03332 return ast_unregister_application(app); 03333 }
| static void write_html_escaped | ( | FILE * | htmlfile, | |
| char * | str | |||
| ) | [static] |
Convert string to use HTML escaped characters.
Definition at line 3102 of file res_agi.c.
Referenced by write_htmldump().
03103 { 03104 char *cur = str; 03105 03106 while(*cur) { 03107 switch (*cur) { 03108 case '<': 03109 fprintf(htmlfile, "%s", "<"); 03110 break; 03111 case '>': 03112 fprintf(htmlfile, "%s", ">"); 03113 break; 03114 case '&': 03115 fprintf(htmlfile, "%s", "&"); 03116 break; 03117 case '"': 03118 fprintf(htmlfile, "%s", """); 03119 break; 03120 default: 03121 fprintf(htmlfile, "%c", *cur); 03122 break; 03123 } 03124 cur++; 03125 } 03126 03127 return; 03128 }
| static int write_htmldump | ( | char * | filename | ) | [static] |
Definition at line 3130 of file res_agi.c.
References ast_free, ast_join(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_xmldoc_printable(), agi_command::cmda, agi_command::list, MAX_CMD_LEN, agi_command::summary, agi_command::usage, and write_html_escaped().
Referenced by handle_cli_agi_dump_html().
03131 { 03132 struct agi_command *command; 03133 char fullcmd[MAX_CMD_LEN]; 03134 FILE *htmlfile; 03135 03136 if (!(htmlfile = fopen(filename, "wt"))) 03137 return -1; 03138 03139 fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n"); 03140 fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n"); 03141 fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n"); 03142 03143 AST_RWLIST_RDLOCK(&agi_commands); 03144 AST_RWLIST_TRAVERSE(&agi_commands, command, list) { 03145 #ifdef AST_XML_DOCS 03146 char *stringptmp; 03147 #endif 03148 char *tempstr, *stringp; 03149 03150 if (!command->cmda[0]) /* end ? */ 03151 break; 03152 /* Hide commands that start with '_' */ 03153 if ((command->cmda[0])[0] == '_') 03154 continue; 03155 ast_join(fullcmd, sizeof(fullcmd), command->cmda); 03156 03157 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n"); 03158 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary); 03159 #ifdef AST_XML_DOCS 03160 stringptmp = ast_xmldoc_printable(command->usage, 0); 03161 stringp = stringptmp; 03162 #else 03163 stringp = command->usage; 03164 #endif 03165 tempstr = strsep(&stringp, "\n"); 03166 03167 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">"); 03168 write_html_escaped(htmlfile, tempstr); 03169 fprintf(htmlfile, "</TD></TR>\n"); 03170 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n"); 03171 03172 while ((tempstr = strsep(&stringp, "\n")) != NULL) { 03173 write_html_escaped(htmlfile, tempstr); 03174 fprintf(htmlfile, "<BR>\n"); 03175 } 03176 fprintf(htmlfile, "</TD></TR>\n"); 03177 fprintf(htmlfile, "</TABLE></TD></TR>\n\n"); 03178 #ifdef AST_XML_DOCS 03179 ast_free(stringptmp); 03180 #endif 03181 } 03182 AST_RWLIST_UNLOCK(&agi_commands); 03183 fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n"); 03184 fclose(htmlfile); 03185 return 0; 03186 }
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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } [static] |
struct ast_threadstorage agi_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_agi_buf , .custom_init = NULL , } [static] |
Definition at line 372 of file res_agi.c.
Referenced by ast_agi_send().
struct ast_datastore_info agi_commands_datastore_info [static] |
{
.type = "AsyncAGI",
.destroy = agi_destroy_commands_cb
}
Definition at line 433 of file res_agi.c.
Referenced by add_agi_cmd(), add_to_agi(), and get_agi_cmd().
struct ast_module_info* ast_module_info = &__mod_info [static] |
struct ast_cli_entry cli_agi[] [static] |
Definition at line 3315 of file res_agi.c.
Referenced by load_module(), and unload_module().
struct agi_command commands[] [static] |
AGI commands list.
Definition at line 2479 of file res_agi.c.
Referenced by aji_dinfo_handler(), dundi_showframe(), load_module(), and unload_module().
char* deadsynopsis = "Executes AGI on a hungup channel" [static] |
char* esynopsis = "Executes an EAGI compliant application" [static] |
const char mandescr_asyncagi[] [static] |
Definition at line 438 of file res_agi.c.
Referenced by load_module().
char usage_autohangup[] [static] |
" Usage: SET AUTOHANGUP <time>\n" " Cause the channel to automatically hangup at <time> seconds in the\n" " future. Of course it can be hungup before then as well. Setting to 0 will\n" " cause the autohangup feature to be disabled on this channel.\n"
char usage_controlstreamfile[] [static] |
char usage_recordfile[] [static] |
char usage_recvchar[] [static] |
char usage_recvtext[] [static] |
" Usage: RECEIVE TEXT <timeout>\n" " Receives a string of text on a channel. Specify timeout to be the\n" " maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n" " do not support the reception of text. Returns -1 for failure or 1 for success, and the string in parentheses.\n"
char usage_sayalpha[] [static] |
char usage_saydate[] [static] |
char usage_saydatetime[] [static] |
char usage_saydigits[] [static] |
char usage_saynumber[] [static] |
char usage_sayphonetic[] [static] |
char usage_saytime[] [static] |
char usage_sendimage[] [static] |
char usage_sendtext[] [static] |
char usage_setcallerid[] [static] |
char usage_setcontext[] [static] |
char usage_setextension[] [static] |
char usage_setpriority[] [static] |
char usage_setvariable[] [static] |
char usage_speechactivategrammar[] [static] |
char usage_speechcreate[] [static] |
char usage_speechdeactivategrammar[] [static] |
char usage_speechdestroy[] [static] |
char usage_speechloadgrammar[] [static] |
char usage_speechrecognize[] [static] |
char usage_speechset[] [static] |
char usage_speechunloadgrammar[] [static] |
char usage_streamfile[] [static] |
char usage_tddmode[] [static] |
char usage_verbose[] [static] |
char usage_waitfordigit[] [static] |
1.6.2