2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief AGI - the Asterisk Gateway Interface
23 * \author Mark Spencer <markster@digium.com>
25 * \todo Convert the rest of the AGI commands over to XML documentation
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39 #include "asterisk/paths.h" /* use many ast_config_AST_*_DIR */
40 #include "asterisk/network.h"
41 #include "asterisk/file.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/pbx.h"
44 #include "asterisk/module.h"
45 #include "asterisk/astdb.h"
46 #include "asterisk/callerid.h"
47 #include "asterisk/cli.h"
48 #include "asterisk/image.h"
49 #include "asterisk/say.h"
50 #include "asterisk/app.h"
51 #include "asterisk/dsp.h"
52 #include "asterisk/musiconhold.h"
53 #include "asterisk/utils.h"
54 #include "asterisk/lock.h"
55 #include "asterisk/strings.h"
56 #include "asterisk/manager.h"
57 #include "asterisk/ast_version.h"
58 #include "asterisk/speech.h"
59 #include "asterisk/manager.h"
60 #include "asterisk/features.h"
61 #include "asterisk/term.h"
62 #include "asterisk/xmldoc.h"
63 #include "asterisk/srv.h"
64 #include "asterisk/test.h"
66 #define AST_API_MODULE
67 #include "asterisk/agi.h"
70 <agi name="answer" language="en_US">
76 <para>Answers channel if not already in answer state. Returns <literal>-1</literal> on
77 channel failure, or <literal>0</literal> if successful.</para>
80 <ref type="agi">hangup</ref>
83 <agi name="asyncagi break" language="en_US">
89 <para>Interrupts expected flow of Async AGI commands and returns control to previous source
90 (typically, the PBX dialplan).</para>
93 <ref type="agi">hangup</ref>
96 <agi name="channel status" language="en_US">
98 Returns status of the connected channel.
101 <parameter name="channelname" />
104 <para>Returns the status of the specified <replaceable>channelname</replaceable>.
105 If no channel name is given then returns the status of the current channel.</para>
106 <para>Return values:</para>
109 <para>Channel is down and available.</para>
112 <para>Channel is down, but reserved.</para>
115 <para>Channel is off hook.</para>
118 <para>Digits (or equivalent) have been dialed.</para>
121 <para>Line is ringing.</para>
124 <para>Remote end is ringing.</para>
127 <para>Line is up.</para>
130 <para>Line is busy.</para>
135 <agi name="control stream file" language="en_US">
137 Sends audio file on channel and allows the listener to control the stream.
140 <parameter name="filename" required="true">
141 <para>The file extension must not be included in the filename.</para>
143 <parameter name="escape_digits" required="true" />
144 <parameter name="skipms" />
145 <parameter name="ffchar">
146 <para>Defaults to <literal>*</literal></para>
148 <parameter name="rewchr">
149 <para>Defaults to <literal>#</literal></para>
151 <parameter name="pausechr" />
154 <para>Send the given file, allowing playback to be controlled by the given
155 digits, if any. Use double quotes for the digits if you wish none to be
156 permitted. Returns <literal>0</literal> if playback completes without a digit
157 being pressed, or the ASCII numerical value of the digit if one was pressed,
158 or <literal>-1</literal> on error or if the channel was disconnected.</para>
161 <agi name="database del" language="en_US">
163 Removes database key/value
166 <parameter name="family" required="true" />
167 <parameter name="key" required="true" />
170 <para>Deletes an entry in the Asterisk database for a given
171 <replaceable>family</replaceable> and <replaceable>key</replaceable>.</para>
172 <para>Returns <literal>1</literal> if successful, <literal>0</literal>
176 <agi name="database deltree" language="en_US">
178 Removes database keytree/value
181 <parameter name="family" required="true" />
182 <parameter name="keytree" />
185 <para>Deletes a <replaceable>family</replaceable> or specific <replaceable>keytree</replaceable>
186 within a <replaceable>family</replaceable> in the Asterisk database.</para>
187 <para>Returns <literal>1</literal> if successful, <literal>0</literal> otherwise.</para>
190 <agi name="database get" language="en_US">
195 <parameter name="family" required="true" />
196 <parameter name="key" required="true" />
199 <para>Retrieves an entry in the Asterisk database for a given <replaceable>family</replaceable>
200 and <replaceable>key</replaceable>.</para>
201 <para>Returns <literal>0</literal> if <replaceable>key</replaceable> is not set.
202 Returns <literal>1</literal> if <replaceable>key</replaceable> is set and returns the variable
203 in parenthesis.</para>
204 <para>Example return code: 200 result=1 (testvariable)</para>
207 <agi name="database put" language="en_US">
209 Adds/updates database value
212 <parameter name="family" required="true" />
213 <parameter name="key" required="true" />
214 <parameter name="value" required="true" />
217 <para>Adds or updates an entry in the Asterisk database for a given
218 <replaceable>family</replaceable>, <replaceable>key</replaceable>, and
219 <replaceable>value</replaceable>.</para>
220 <para>Returns <literal>1</literal> if successful, <literal>0</literal> otherwise.</para>
223 <agi name="exec" language="en_US">
225 Executes a given Application
228 <parameter name="application" required="true" />
229 <parameter name="options" required="true" />
232 <para>Executes <replaceable>application</replaceable> with given
233 <replaceable>options</replaceable>.</para>
234 <para>Returns whatever the <replaceable>application</replaceable> returns, or
235 <literal>-2</literal> on failure to find <replaceable>application</replaceable>.</para>
238 <agi name="get data" language="en_US">
240 Prompts for DTMF on a channel
243 <parameter name="file" required="true" />
244 <parameter name="timeout" />
245 <parameter name="maxdigits" />
248 <para>Stream the given <replaceable>file</replaceable>, and receive DTMF data.</para>
249 <para>Returns the digits received from the channel at the other end.</para>
252 <agi name="get full variable" language="en_US">
254 Evaluates a channel expression
257 <parameter name="variablename" required="true" />
258 <parameter name="channel name" />
261 <para>Returns <literal>0</literal> if <replaceable>variablename</replaceable> is not set
262 or channel does not exist. Returns <literal>1</literal> if <replaceable>variablename</replaceable>
263 is set and returns the variable in parenthesis. Understands complex variable names and builtin
264 variables, unlike GET VARIABLE.</para>
265 <para>Example return code: 200 result=1 (testvariable)</para>
268 <agi name="get option" language="en_US">
270 Stream file, prompt for DTMF, with timeout.
273 <parameter name="filename" required="true" />
274 <parameter name="escape_digits" required="true" />
275 <parameter name="timeout" />
278 <para>Behaves similar to STREAM FILE but used with a timeout option.</para>
281 <ref type="agi">stream file</ref>
284 <agi name="get variable" language="en_US">
286 Gets a channel variable.
289 <parameter name="variablename" required="true" />
292 <para>Returns <literal>0</literal> if <replaceable>variablename</replaceable> is not set.
293 Returns <literal>1</literal> if <replaceable>variablename</replaceable> is set and returns
294 the variable in parentheses.</para>
295 <para>Example return code: 200 result=1 (testvariable)</para>
298 <agi name="hangup" language="en_US">
300 Hangup the current channel.
303 <parameter name="channelname" />
306 <para>Hangs up the specified channel. If no channel name is given, hangs
307 up the current channel</para>
310 <agi name="noop" language="en_US">
316 <para>Does nothing.</para>
319 <agi name="receive char" language="en_US">
321 Receives one character from channels supporting it.
324 <parameter name="timeout" required="true">
325 <para>The maximum time to wait for input in milliseconds, or <literal>0</literal>
326 for infinite. Most channels</para>
330 <para>Receives a character of text on a channel. Most channels do not support
331 the reception of text. Returns the decimal value of the character
332 if one is received, or <literal>0</literal> if the channel does not support
333 text reception. Returns <literal>-1</literal> only on error/hangup.</para>
336 <agi name="receive text" language="en_US">
338 Receives text from channels supporting it.
341 <parameter name="timeout" required="true">
342 <para>The timeout to be the maximum time to wait for input in
343 milliseconds, or <literal>0</literal> for infinite.</para>
347 <para>Receives a string of text on a channel. Most channels
348 do not support the reception of text. Returns <literal>-1</literal> for failure
349 or <literal>1</literal> for success, and the string in parenthesis.</para>
352 <agi name="record file" language="en_US">
354 Records to a given file.
357 <parameter name="filename" required="true" />
358 <parameter name="format" required="true" />
359 <parameter name="escape_digits" required="true" />
360 <parameter name="timeout" required="true" />
361 <parameter name="offset samples" />
362 <parameter name="BEEP" />
363 <parameter name="s=silence" />
366 <para>Record to a file until a given dtmf digit in the sequence is received.
367 Returns <literal>-1</literal> on hangup or error. The format will specify what kind of file
368 will be recorded. The <replaceable>timeout</replaceable> is the maximum record time in
369 milliseconds, or <literal>-1</literal> for no <replaceable>timeout</replaceable>.
370 <replaceable>offset samples</replaceable> is optional, and, if provided, will seek
371 to the offset without exceeding the end of the file. <replaceable>silence</replaceable> is
372 the number of seconds of silence allowed before the function returns despite the
373 lack of dtmf digits or reaching <replaceable>timeout</replaceable>. <replaceable>silence</replaceable>
374 value must be preceded by <literal>s=</literal> and is also optional.</para>
377 <agi name="say alpha" language="en_US">
379 Says a given character string.
382 <parameter name="number" required="true" />
383 <parameter name="escape_digits" required="true" />
386 <para>Say a given character string, returning early if any of the given DTMF digits
387 are received on the channel. Returns <literal>0</literal> if playback completes
388 without a digit being pressed, or the ASCII numerical value of the digit if one
389 was pressed or <literal>-1</literal> on error/hangup.</para>
392 <agi name="say digits" language="en_US">
394 Says a given digit string.
397 <parameter name="number" required="true" />
398 <parameter name="escape_digits" required="true" />
401 <para>Say a given digit string, returning early if any of the given DTMF digits
402 are received on the channel. Returns <literal>0</literal> if playback completes
403 without a digit being pressed, or the ASCII numerical value of the digit if one
404 was pressed or <literal>-1</literal> on error/hangup.</para>
407 <agi name="say number" language="en_US">
412 <parameter name="number" required="true" />
413 <parameter name="escape_digits" required="true" />
414 <parameter name="gender" />
417 <para>Say a given number, returning early if any of the given DTMF digits
418 are received on the channel. Returns <literal>0</literal> if playback
419 completes without a digit being pressed, or the ASCII numerical value of
420 the digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
423 <agi name="say phonetic" language="en_US">
425 Says a given character string with phonetics.
428 <parameter name="string" required="true" />
429 <parameter name="escape_digits" required="true" />
432 <para>Say a given character string with phonetics, returning early if any of the
433 given DTMF digits are received on the channel. Returns <literal>0</literal> if
434 playback completes without a digit pressed, the ASCII numerical value of the digit
435 if one was pressed, or <literal>-1</literal> on error/hangup.</para>
438 <agi name="say date" language="en_US">
443 <parameter name="date" required="true">
444 <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
445 Coordinated Universal Time (UTC).</para>
447 <parameter name="escape_digits" required="true" />
450 <para>Say a given date, returning early if any of the given DTMF digits are
451 received on the channel. Returns <literal>0</literal> if playback
452 completes without a digit being pressed, or the ASCII numerical value of the
453 digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
456 <agi name="say time" language="en_US">
461 <parameter name="time" required="true">
462 <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
463 Coordinated Universal Time (UTC).</para>
465 <parameter name="escape_digits" required="true" />
468 <para>Say a given time, returning early if any of the given DTMF digits are
469 received on the channel. Returns <literal>0</literal> if playback completes
470 without a digit being pressed, or the ASCII numerical value of the digit if
471 one was pressed or <literal>-1</literal> on error/hangup.</para>
474 <agi name="say datetime" language="en_US">
476 Says a given time as specified by the format given.
479 <parameter name="time" required="true">
480 <para>Is number of seconds elapsed since 00:00:00
481 on January 1, 1970, Coordinated Universal Time (UTC)</para>
483 <parameter name="escape_digits" required="true" />
484 <parameter name="format">
485 <para>Is the format the time should be said in. See
486 <filename>voicemail.conf</filename> (defaults to <literal>ABdY
487 'digits/at' IMp</literal>).</para>
489 <parameter name="timezone">
490 <para>Acceptable values can be found in <filename>/usr/share/zoneinfo</filename>
491 Defaults to machine default.</para>
495 <para>Say a given time, returning early if any of the given DTMF digits are
496 received on the channel. Returns <literal>0</literal> if playback
497 completes without a digit being pressed, or the ASCII numerical value of the
498 digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
501 <agi name="send image" language="en_US">
503 Sends images to channels supporting it.
506 <parameter name="image" required="true" />
509 <para>Sends the given image on a channel. Most channels do not support the
510 transmission of images. Returns <literal>0</literal> if image is sent, or if
511 the channel does not support image transmission. Returns <literal>-1</literal>
512 only on error/hangup. Image names should not include extensions.</para>
515 <agi name="send text" language="en_US">
517 Sends text to channels supporting it.
520 <parameter name="text to send" required="true">
521 <para>Text consisting of greater than one word should be placed
522 in quotes since the command only accepts a single argument.</para>
526 <para>Sends the given text on a channel. Most channels do not support the
527 transmission of text. Returns <literal>0</literal> if text is sent, or if the
528 channel does not support text transmission. Returns <literal>-1</literal> only
529 on error/hangup.</para>
532 <agi name="set autohangup" language="en_US">
534 Autohangup channel in some time.
537 <parameter name="time" required="true" />
540 <para>Cause the channel to automatically hangup at <replaceable>time</replaceable>
541 seconds in the future. Of course it can be hungup before then as well. Setting to
542 <literal>0</literal> will cause the autohangup feature to be disabled on this channel.</para>
545 <agi name="set callerid" language="en_US">
547 Sets callerid for the current channel.
550 <parameter name="number" required="true" />
553 <para>Changes the callerid of the current channel.</para>
556 <agi name="set context" language="en_US">
558 Sets channel context.
561 <parameter name="desired context" required="true" />
564 <para>Sets the context for continuation upon exiting the application.</para>
567 <agi name="set extension" language="en_US">
569 Changes channel extension.
572 <parameter name="new extension" required="true" />
575 <para>Changes the extension for continuation upon exiting the application.</para>
578 <agi name="set music" language="en_US">
580 Enable/Disable Music on hold generator
583 <parameter required="true">
586 <parameter name="on" literal="true" required="true" />
589 <parameter name="off" literal="true" required="true" />
593 <parameter name="class" required="true" />
596 <para>Enables/Disables the music on hold generator. If <replaceable>class</replaceable>
597 is not specified, then the <literal>default</literal> music on hold class will be
599 <para>Always returns <literal>0</literal>.</para>
602 <agi name="set priority" language="en_US">
604 Set channel dialplan priority.
607 <parameter name="priority" required="true" />
610 <para>Changes the priority for continuation upon exiting the application.
611 The priority must be a valid priority or label.</para>
614 <agi name="set variable" language="en_US">
616 Sets a channel variable.
619 <parameter name="variablename" required="true" />
620 <parameter name="value" required="true" />
623 <para>Sets a variable to the current channel.</para>
626 <agi name="stream file" language="en_US">
628 Sends audio file on channel.
631 <parameter name="filename" required="true">
632 <para>File name to play. The file extension must not be
633 included in the <replaceable>filename</replaceable>.</para>
635 <parameter name="escape_digits" required="true">
636 <para>Use double quotes for the digits if you wish none to be
639 <parameter name="sample offset">
640 <para>If sample offset is provided then the audio will seek to sample
641 offset before play starts.</para>
645 <para>Send the given file, allowing playback to be interrupted by the given
646 digits, if any. Returns <literal>0</literal> if playback completes without a digit
647 being pressed, or the ASCII numerical value of the digit if one was pressed,
648 or <literal>-1</literal> on error or if the channel was disconnected.</para>
651 <ref type="agi">control stream file</ref>
654 <agi name="tdd mode" language="en_US">
656 Toggles TDD mode (for the deaf).
659 <parameter name="boolean" required="true">
667 <para>Enable/Disable TDD transmission/reception on a channel. Returns <literal>1</literal> if
668 successful, or <literal>0</literal> if channel is not TDD-capable.</para>
671 <agi name="verbose" language="en_US">
673 Logs a message to the asterisk verbose log.
676 <parameter name="message" required="true" />
677 <parameter name="level" required="true" />
680 <para>Sends <replaceable>message</replaceable> to the console via verbose
681 message system. <replaceable>level</replaceable> is the verbose level (1-4).
682 Always returns <literal>1</literal></para>
685 <agi name="wait for digit" language="en_US">
687 Waits for a digit to be pressed.
690 <parameter name="timeout" required="true" />
693 <para>Waits up to <replaceable>timeout</replaceable> milliseconds for channel to
694 receive a DTMF digit. Returns <literal>-1</literal> on channel failure, <literal>0</literal>
695 if no digit is received in the timeout, or the numerical value of the ascii of the digit if
696 one is received. Use <literal>-1</literal> for the <replaceable>timeout</replaceable> value if
697 you desire the call to block indefinitely.</para>
700 <agi name="speech create" language="en_US">
702 Creates a speech object.
705 <parameter name="engine" required="true" />
708 <para>Create a speech object to be used by the other Speech AGI commands.</para>
711 <agi name="speech set" language="en_US">
713 Sets a speech engine setting.
716 <parameter name="name" required="true" />
717 <parameter name="value" required="true" />
720 <para>Set an engine-specific setting.</para>
723 <agi name="speech destroy" language="en_US">
725 Destroys a speech object.
730 <para>Destroy the speech object created by <literal>SPEECH CREATE</literal>.</para>
733 <ref type="agi">speech create</ref>
736 <agi name="speech load grammar" language="en_US">
741 <parameter name="grammar name" required="true" />
742 <parameter name="path to grammar" required="true" />
745 <para>Loads the specified grammar as the specified name.</para>
748 <agi name="speech unload grammar" language="en_US">
753 <parameter name="grammar name" required="true" />
756 <para>Unloads the specified grammar.</para>
759 <agi name="speech activate grammar" language="en_US">
764 <parameter name="grammar name" required="true" />
767 <para>Activates the specified grammar on the speech object.</para>
770 <agi name="speech deactivate grammar" language="en_US">
772 Deactivates a grammar.
775 <parameter name="grammar name" required="true" />
778 <para>Deactivates the specified grammar on the speech object.</para>
781 <agi name="speech recognize" language="en_US">
786 <parameter name="prompt" required="true" />
787 <parameter name="timeout" required="true" />
788 <parameter name="offset" />
791 <para>Plays back given <replaceable>prompt</replaceable> while listening for
792 speech and dtmf.</para>
795 <application name="AGI" language="en_US">
797 Executes an AGI compliant application.
800 <parameter name="command" required="true" />
801 <parameter name="args">
802 <argument name="arg1" required="true" />
803 <argument name="arg2" multiple="yes" />
807 <para>Executes an Asterisk Gateway Interface compliant
808 program on a channel. AGI allows Asterisk to launch external programs written
809 in any language to control a telephony channel, play audio, read DTMF digits,
810 etc. by communicating with the AGI protocol on <emphasis>stdin</emphasis> and
811 <emphasis>stdout</emphasis>. As of <literal>1.6.0</literal>, this channel will
812 not stop dialplan execution on hangup inside of this application. Dialplan
813 execution will continue normally, even upon hangup until the AGI application
814 signals a desire to stop (either by exiting or, in the case of a net script, by
815 closing the connection). A locally executed AGI script will receive SIGHUP on
816 hangup from the channel except when using DeadAGI. A fast AGI server will
817 correspondingly receive a HANGUP inline with the command dialog. Both of theses
818 signals may be disabled by setting the <variable>AGISIGHUP</variable> channel
819 variable to <literal>no</literal> before executing the AGI application.</para>
820 <para>Use the CLI command <literal>agi show commands</literal> to list available agi
822 <para>This application sets the following channel variable upon completion:</para>
824 <variable name="AGISTATUS">
825 <para>The status of the attempt to the run the AGI script
826 text string, one of:</para>
827 <value name="SUCCESS" />
828 <value name="FAILURE" />
829 <value name="NOTFOUND" />
830 <value name="HANGUP" />
835 <ref type="application">EAGI</ref>
836 <ref type="application">DeadAGI</ref>
839 <application name="EAGI" language="en_US">
841 Executes an EAGI compliant application.
844 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
845 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
848 <para>Using 'EAGI' provides enhanced AGI, with incoming audio available out of band
849 on file descriptor 3.</para>
850 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/para)" />
851 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
854 <ref type="application">AGI</ref>
855 <ref type="application">DeadAGI</ref>
858 <application name="DeadAGI" language="en_US">
860 Executes AGI on a hungup channel.
863 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
864 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
867 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/para)" />
868 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
871 <ref type="application">AGI</ref>
872 <ref type="application">EAGI</ref>
875 <manager name="AGI" language="en_US">
877 Add an AGI command to execute by Async AGI.
880 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
881 <parameter name="Channel" required="true">
882 <para>Channel that is currently in Async AGI.</para>
884 <parameter name="Command" required="true">
885 <para>Application to execute.</para>
887 <parameter name="CommandID">
888 <para>This will be sent back in CommandID header of AsyncAGI exec
889 event notification.</para>
893 <para>Add an AGI command to the execute queue of the channel in Async AGI.</para>
899 #define MAX_CMD_LEN 80
900 #define AGI_NANDFS_RETRY 3
901 #define AGI_BUF_LEN 2048
902 #define SRV_PREFIX "_agi._tcp."
904 static char *app = "AGI";
906 static char *eapp = "EAGI";
908 static char *deadapp = "DeadAGI";
910 static int agidebug = 0;
912 #define TONE_BLOCK_SIZE 200
914 /* Max time to connect to an AGI remote host */
915 #define MAX_AGI_CONNECT 2000
917 #define AGI_PORT 4573
919 /*! Special return code for "asyncagi break" command. */
920 #define ASYNC_AGI_BREAK 3
923 AGI_RESULT_FAILURE = -1,
925 AGI_RESULT_SUCCESS_FAST,
926 AGI_RESULT_SUCCESS_ASYNC,
931 static agi_command *find_command(const char * const cmds[], int exact);
933 AST_THREADSTORAGE(agi_buf);
934 #define AGI_BUF_INITSIZE 256
936 int AST_OPTIONAL_API_NAME(ast_agi_send)(int fd, struct ast_channel *chan, char *fmt, ...)
942 if (!(buf = ast_str_thread_get(&agi_buf, AGI_BUF_INITSIZE)))
946 res = ast_str_set_va(&buf, 0, fmt, ap);
950 ast_log(LOG_ERROR, "Out of memory\n");
956 ast_verbose("<%s>AGI Tx >> %s", chan->name, ast_str_buffer(buf));
958 ast_verbose("AGI Tx >> %s", ast_str_buffer(buf));
962 return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
965 /* linked list of AGI commands ready to be executed by Async AGI */
969 AST_LIST_ENTRY(agi_cmd) entry;
972 static void free_agi_cmd(struct agi_cmd *cmd)
974 ast_free(cmd->cmd_buffer);
975 ast_free(cmd->cmd_id);
979 /* AGI datastore destructor */
980 static void agi_destroy_commands_cb(void *data)
983 AST_LIST_HEAD(, agi_cmd) *chan_cmds = data;
984 AST_LIST_LOCK(chan_cmds);
985 while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) {
988 AST_LIST_UNLOCK(chan_cmds);
989 AST_LIST_HEAD_DESTROY(chan_cmds);
993 /* channel datastore to keep the queue of AGI commands in the channel */
994 static const struct ast_datastore_info agi_commands_datastore_info = {
996 .destroy = agi_destroy_commands_cb
999 static struct agi_cmd *get_agi_cmd(struct ast_channel *chan)
1001 struct ast_datastore *store;
1002 struct agi_cmd *cmd;
1003 AST_LIST_HEAD(, agi_cmd) *agi_commands;
1005 ast_channel_lock(chan);
1006 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
1007 ast_channel_unlock(chan);
1009 ast_log(LOG_ERROR, "Huh? Async AGI datastore disappeared on Channel %s!\n",
1013 agi_commands = store->data;
1014 AST_LIST_LOCK(agi_commands);
1015 cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry);
1016 AST_LIST_UNLOCK(agi_commands);
1020 /* channel is locked when calling this one either from the CLI or manager thread */
1021 static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
1023 struct ast_datastore *store;
1024 struct agi_cmd *cmd;
1025 AST_LIST_HEAD(, agi_cmd) *agi_commands;
1027 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
1029 ast_log(LOG_WARNING, "Channel %s is not setup for Async AGI.\n", chan->name);
1032 agi_commands = store->data;
1033 cmd = ast_calloc(1, sizeof(*cmd));
1037 cmd->cmd_buffer = ast_strdup(cmd_buff);
1038 if (!cmd->cmd_buffer) {
1042 cmd->cmd_id = ast_strdup(cmd_id);
1044 ast_free(cmd->cmd_buffer);
1048 AST_LIST_LOCK(agi_commands);
1049 AST_LIST_INSERT_TAIL(agi_commands, cmd, entry);
1050 AST_LIST_UNLOCK(agi_commands);
1054 static int add_to_agi(struct ast_channel *chan)
1056 struct ast_datastore *datastore;
1057 AST_LIST_HEAD(, agi_cmd) *agi_cmds_list;
1059 /* check if already on AGI */
1060 ast_channel_lock(chan);
1061 datastore = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
1062 ast_channel_unlock(chan);
1064 /* we already have an AGI datastore, let's just
1069 /* the channel has never been on Async AGI,
1070 let's allocate it's datastore */
1071 datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI");
1075 agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list));
1076 if (!agi_cmds_list) {
1077 ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n");
1078 ast_datastore_free(datastore);
1081 datastore->data = agi_cmds_list;
1082 AST_LIST_HEAD_INIT(agi_cmds_list);
1083 ast_channel_lock(chan);
1084 ast_channel_datastore_add(chan, datastore);
1085 ast_channel_unlock(chan);
1090 * \brief CLI command to add applications to execute in Async AGI
1095 * \retval CLI_SUCCESS on success
1096 * \retval NULL when init or tab completion is used
1098 static char *handle_cli_agi_add_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1100 struct ast_channel *chan;
1103 e->command = "agi exec";
1104 e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n"
1105 " Add AGI command to the execute queue of the specified channel in Async AGI\n";
1109 return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
1114 return CLI_SHOWUSAGE;
1117 if (!(chan = ast_channel_get_by_name(a->argv[2]))) {
1118 ast_cli(a->fd, "Channel %s does not exist.\n", a->argv[2]);
1122 ast_channel_lock(chan);
1124 if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) {
1125 ast_cli(a->fd, "Failed to add AGI command to queue of channel %s\n", chan->name);
1126 ast_channel_unlock(chan);
1127 chan = ast_channel_unref(chan);
1131 ast_debug(1, "Added AGI command to channel %s queue\n", chan->name);
1133 ast_channel_unlock(chan);
1134 chan = ast_channel_unref(chan);
1140 * \brief Add a new command to execute by the Async AGI application
1144 * It will append the application to the specified channel's queue
1145 * if the channel is not inside Async AGI application it will return an error
1146 * \retval 0 on success or incorrect use
1147 * \retval 1 on failure to add the command ( most likely because the channel
1148 * is not in Async AGI loop )
1150 static int action_add_agi_cmd(struct mansession *s, const struct message *m)
1152 const char *channel = astman_get_header(m, "Channel");
1153 const char *cmdbuff = astman_get_header(m, "Command");
1154 const char *cmdid = astman_get_header(m, "CommandID");
1155 struct ast_channel *chan;
1158 if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) {
1159 astman_send_error(s, m, "Both, Channel and Command are *required*");
1163 if (!(chan = ast_channel_get_by_name(channel))) {
1164 snprintf(buf, sizeof(buf), "Channel %s does not exist.", channel);
1165 astman_send_error(s, m, buf);
1169 ast_channel_lock(chan);
1171 if (add_agi_cmd(chan, cmdbuff, cmdid)) {
1172 snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", chan->name);
1173 astman_send_error(s, m, buf);
1174 ast_channel_unlock(chan);
1175 chan = ast_channel_unref(chan);
1179 ast_channel_unlock(chan);
1180 chan = ast_channel_unref(chan);
1182 astman_send_ack(s, m, "Added AGI command to queue");
1187 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead);
1188 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[]);
1192 * \brief Read and handle a channel frame for Async AGI.
1194 * \param chan Channel to read a frame from.
1196 * \retval AGI_RESULT_SUCCESS on success.
1197 * \retval AGI_RESULT_HANGUP on hangup.
1198 * \retval AGI_RESULT_FAILURE on error.
1200 static enum agi_result async_agi_read_frame(struct ast_channel *chan)
1202 struct ast_frame *f;
1206 ast_debug(3, "No frame read on channel %s, going out ...\n", chan->name);
1207 return AGI_RESULT_HANGUP;
1209 if (f->frametype == AST_FRAME_CONTROL) {
1211 * Is there any other frame we should care about besides
1212 * AST_CONTROL_HANGUP?
1214 switch (f->subclass.integer) {
1215 case AST_CONTROL_HANGUP:
1216 ast_debug(3, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
1218 return AGI_RESULT_HANGUP;
1225 return AGI_RESULT_SUCCESS;
1228 static enum agi_result launch_asyncagi(struct ast_channel *chan, char *argv[], int *efd)
1230 /* This buffer sizes might cause truncation if the AGI command writes more data
1231 than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command
1232 that writes a response larger than 1024 bytes?, I don't think so, most of
1233 them are just result=blah stuff. However probably if GET VARIABLE is called
1234 and the variable has large amount of data, that could be a problem. We could
1235 make this buffers dynamic, but let's leave that as a second step.
1237 AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe
1238 number. Some characters of AGI buf will be url encoded to be sent to manager
1239 clients. An URL encoded character will take 3 bytes, but again, to cause
1240 truncation more than about 70% of the AGI buffer should be URL encoded for
1241 that to happen. Not likely at all.
1243 On the other hand. I wonder if read() could eventually return less data than
1244 the amount already available in the pipe? If so, how to deal with that?
1245 So far, my tests on Linux have not had any problems.
1247 #define AGI_BUF_SIZE 1024
1248 #define AMI_BUF_SIZE 2048
1249 enum agi_result cmd_status;
1250 struct agi_cmd *cmd;
1255 char agi_buffer[AGI_BUF_SIZE + 1];
1256 char ami_buffer[AMI_BUF_SIZE];
1257 enum agi_result returnstatus = AGI_RESULT_SUCCESS;
1261 ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n");
1262 return AGI_RESULT_FAILURE;
1265 /* add AsyncAGI datastore to the channel */
1266 if (add_to_agi(chan)) {
1267 ast_log(LOG_ERROR, "Failed to start Async AGI on channel %s\n", chan->name);
1268 return AGI_RESULT_FAILURE;
1271 /* this pipe allows us to create a "fake" AGI struct to use
1275 ast_log(LOG_ERROR, "Failed to create Async AGI pipe\n");
1277 * Intentionally do not remove the datastore added with
1278 * add_to_agi() the from channel. It will be removed when the
1279 * channel is hung up anyway.
1281 return AGI_RESULT_FAILURE;
1284 /* handlers will get the pipe write fd and we read the AGI responses
1285 from the pipe read fd */
1286 async_agi.fd = fds[1];
1287 async_agi.ctrl = fds[1];
1288 async_agi.audio = -1; /* no audio support */
1290 async_agi.speech = NULL;
1292 /* notify possible manager users of a new channel ready to
1294 setup_env(chan, "async", fds[1], 0, 0, NULL);
1295 /* read the environment */
1296 res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1298 ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s\n",
1300 returnstatus = AGI_RESULT_FAILURE;
1301 goto async_agi_abort;
1303 agi_buffer[res] = '\0';
1304 /* encode it and send it thru the manager so whoever is going to take
1305 care of AGI commands on this channel can decide which AGI commands
1306 to execute based on the setup info */
1307 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
1308 manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1309 "SubEvent: Start\r\n"
1311 "Env: %s\r\n", chan->name, ami_buffer);
1312 hungup = ast_check_hangup(chan);
1315 * Process as many commands as we can. Commands are added via
1316 * the manager or the cli threads.
1318 while (!hungup && (cmd = get_agi_cmd(chan))) {
1319 /* OK, we have a command, let's call the command handler. */
1320 cmd_status = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0);
1323 * The command handler must have written to our fake AGI struct
1324 * fd (the pipe), let's read the response.
1326 res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1328 ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s\n",
1331 returnstatus = AGI_RESULT_FAILURE;
1332 goto async_agi_done;
1335 * We have a response, let's send the response thru the manager.
1336 * Include the CommandID if it was specified when the command
1339 agi_buffer[res] = '\0';
1340 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
1341 if (ast_strlen_zero(cmd->cmd_id)) {
1342 manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1343 "SubEvent: Exec\r\n"
1345 "Result: %s\r\n", chan->name, ami_buffer);
1347 manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1348 "SubEvent: Exec\r\n"
1351 "Result: %s\r\n", chan->name, cmd->cmd_id, ami_buffer);
1356 * Check the command status to determine if we should continue
1357 * executing more commands.
1359 hungup = ast_check_hangup(chan);
1360 switch (cmd_status) {
1361 case AGI_RESULT_FAILURE:
1363 /* The failure was not because of a hangup. */
1364 returnstatus = AGI_RESULT_FAILURE;
1365 goto async_agi_done;
1368 case AGI_RESULT_SUCCESS_ASYNC:
1369 /* Only the "asyncagi break" command does this. */
1370 returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1371 goto async_agi_done;
1378 /* Wait a bit for a frame to read or to poll for a new command. */
1379 res = ast_waitfor(chan, timeout);
1381 ast_debug(1, "ast_waitfor returned <= 0 on chan %s\n", chan->name);
1382 returnstatus = AGI_RESULT_FAILURE;
1387 * Read the channel control queue until it is dry so we can
1394 cmd_status = async_agi_read_frame(chan);
1395 if (cmd_status != AGI_RESULT_SUCCESS) {
1396 returnstatus = cmd_status;
1397 goto async_agi_done;
1399 hungup = ast_check_hangup(chan);
1402 hungup = ast_check_hangup(chan);
1407 if (async_agi.speech) {
1408 ast_speech_destroy(async_agi.speech);
1410 /* notify manager users this channel cannot be
1411 controlled anymore by Async AGI */
1412 manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1414 "Channel: %s\r\n", chan->name);
1417 /* close the pipe */
1422 * Intentionally do not remove the datastore added with
1423 * add_to_agi() the from channel. There might be commands still
1424 * in the queue or in-flight to us and AsyncAGI may get called
1425 * again. The datastore destructor will be called on channel
1426 * destruction anyway.
1429 if (returnstatus == AGI_RESULT_SUCCESS) {
1430 returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1432 return returnstatus;
1438 /* launch_netscript: The fastagi handler.
1439 FastAGI defaults to port 4573 */
1440 static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
1442 int s, flags, res, port = AGI_PORT;
1443 struct pollfd pfds[1];
1444 char *host, *c, *script;
1445 struct sockaddr_in addr_in;
1447 struct ast_hostent ahp;
1449 /* agiurl is "agi://host.domain[:port][/script/name]" */
1450 host = ast_strdupa(agiurl + 6); /* Remove agi:// */
1451 /* Strip off any script name */
1452 if ((script = strchr(host, '/'))) {
1458 if ((c = strchr(host, ':'))) {
1462 if (!(hp = ast_gethostbyname(host, &ahp))) {
1463 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
1466 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1467 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
1470 if ((flags = fcntl(s, F_GETFL)) < 0) {
1471 ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
1475 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
1476 ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
1480 memset(&addr_in, 0, sizeof(addr_in));
1481 addr_in.sin_family = AF_INET;
1482 addr_in.sin_port = htons(port);
1483 memcpy(&addr_in.sin_addr, hp->h_addr, sizeof(addr_in.sin_addr));
1484 if (connect(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) && (errno != EINPROGRESS)) {
1485 ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
1487 return AGI_RESULT_FAILURE;
1491 pfds[0].events = POLLOUT;
1492 while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) {
1493 if (errno != EINTR) {
1495 ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n",
1496 agiurl, MAX_AGI_CONNECT);
1498 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
1500 return AGI_RESULT_FAILURE;
1504 if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) {
1505 if (errno != EINTR) {
1506 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
1508 return AGI_RESULT_FAILURE;
1512 /* If we have a script parameter, relay it to the fastagi server */
1513 /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */
1514 if (!ast_strlen_zero(script))
1515 ast_agi_send(s, NULL, "agi_network_script: %s\n", script);
1517 ast_debug(4, "Wow, connected!\n");
1520 return AGI_RESULT_SUCCESS_FAST;
1525 * \brief The HA fastagi handler.
1526 * \param agiurl The request URL as passed to Agi() in the dial plan
1527 * \param argv The parameters after the URL passed to Agi() in the dial plan
1528 * \param fds Input/output file descriptors
1530 * Uses SRV lookups to try to connect to a list of FastAGI servers. The hostname in
1531 * the URI is prefixed with _agi._tcp. prior to the DNS resolution. For
1532 * example, if you specify the URI \a hagi://agi.example.com/foo.agi the DNS
1533 * query would be for \a _agi._tcp.agi.example.com and you'll need to make sure
1536 * This function parses the URI, resolves the SRV service name, forms new URIs
1537 * with the results of the DNS lookup, and then calls launch_netscript on the
1538 * new URIs until one succeeds.
1540 * \return the result of the AGI operation.
1542 static enum agi_result launch_ha_netscript(char *agiurl, char *argv[], int *fds)
1544 char *host, *script;
1545 enum agi_result result = AGI_RESULT_FAILURE;
1546 struct srv_context *context = NULL;
1549 char resolved_uri[1024];
1550 const char *srvhost;
1551 unsigned short srvport;
1553 /* format of agiurl is "hagi://host.domain[:port][/script/name]" */
1554 if (!(host = ast_strdupa(agiurl + 7))) { /* Remove hagi:// */
1555 ast_log(LOG_WARNING, "An error occurred parsing the AGI URI: %s", agiurl);
1556 return AGI_RESULT_FAILURE;
1559 /* Strip off any script name */
1560 if ((script = strchr(host, '/'))) {
1566 if (strchr(host, ':')) {
1567 ast_log(LOG_WARNING, "Specifying a port number disables SRV lookups: %s\n", agiurl);
1568 return launch_netscript(agiurl + 1, argv, fds); /* +1 to strip off leading h from hagi:// */
1571 snprintf(service, sizeof(service), "%s%s", SRV_PREFIX, host);
1573 while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) {
1574 snprintf(resolved_uri, sizeof(resolved_uri), "agi://%s:%d/%s", srvhost, srvport, script);
1575 result = launch_netscript(resolved_uri, argv, fds);
1576 if (result == AGI_RESULT_FAILURE || result == AGI_RESULT_NOTFOUND) {
1577 ast_log(LOG_WARNING, "AGI request failed for host '%s' (%s:%d)\n", host, srvhost, srvport);
1583 ast_log(LOG_WARNING, "SRV lookup failed for %s\n", agiurl);
1585 ast_srv_cleanup(&context);
1591 static enum agi_result launch_script(struct ast_channel *chan, char *script, char *argv[], int *fds, int *efd, int *opid)
1594 int pid, toast[2], fromast[2], audio[2], res;
1597 if (!strncasecmp(script, "agi://", 6)) {
1598 return (efd == NULL) ? launch_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
1600 if (!strncasecmp(script, "hagi://", 7)) {
1601 return (efd == NULL) ? launch_ha_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
1603 if (!strncasecmp(script, "agi:async", sizeof("agi:async") - 1)) {
1604 return launch_asyncagi(chan, argv, efd);
1607 if (script[0] != '/') {
1608 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script);
1612 /* Before even trying let's see if the file actually exists */
1613 if (stat(script, &st)) {
1614 ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script);
1615 return AGI_RESULT_NOTFOUND;
1619 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
1620 return AGI_RESULT_FAILURE;
1622 if (pipe(fromast)) {
1623 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
1626 return AGI_RESULT_FAILURE;
1630 ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
1635 return AGI_RESULT_FAILURE;
1637 res = fcntl(audio[1], F_GETFL);
1639 res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
1641 ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
1648 return AGI_RESULT_FAILURE;
1652 if ((pid = ast_safe_fork(1)) < 0) {
1653 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
1654 return AGI_RESULT_FAILURE;
1657 /* Pass paths to AGI via environmental variables */
1658 setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
1659 setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
1660 setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
1661 setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
1662 setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
1663 setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
1664 setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
1665 setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
1666 setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
1667 setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
1668 setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
1670 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
1671 ast_set_priority(0);
1673 /* Redirect stdin and out, provide enhanced audio channel if desired */
1674 dup2(fromast[0], STDIN_FILENO);
1675 dup2(toast[1], STDOUT_FILENO);
1677 dup2(audio[0], STDERR_FILENO + 1);
1679 close(STDERR_FILENO + 1);
1681 /* Close everything but stdin/out/error */
1682 ast_close_fds_above_n(STDERR_FILENO + 1);
1684 /* Execute script */
1685 /* XXX argv should be deprecated in favor of passing agi_argX paramaters */
1686 execv(script, argv);
1687 /* Can't use ast_log since FD's are closed */
1688 ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno));
1689 /* Special case to set status of AGI to failure */
1690 fprintf(stdout, "failure\n");
1694 ast_verb(3, "Launched AGI Script %s\n", script);
1696 fds[1] = fromast[1];
1699 /* close what we're not using in the parent */
1707 return AGI_RESULT_SUCCESS;
1710 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
1714 /* Print initial environment, with agi_request always being the first
1716 ast_agi_send(fd, chan, "agi_request: %s\n", request);
1717 ast_agi_send(fd, chan, "agi_channel: %s\n", chan->name);
1718 ast_agi_send(fd, chan, "agi_language: %s\n", chan->language);
1719 ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type);
1720 ast_agi_send(fd, chan, "agi_uniqueid: %s\n", chan->uniqueid);
1721 ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
1724 ast_agi_send(fd, chan, "agi_callerid: %s\n",
1725 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "unknown"));
1726 ast_agi_send(fd, chan, "agi_calleridname: %s\n",
1727 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "unknown"));
1728 ast_agi_send(fd, chan, "agi_callingpres: %d\n",
1729 ast_party_id_presentation(&chan->caller.id));
1730 ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->caller.ani2);
1731 ast_agi_send(fd, chan, "agi_callington: %d\n", chan->caller.id.number.plan);
1732 ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->dialed.transit_network_select);
1733 ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->dialed.number.str, "unknown"));
1734 ast_agi_send(fd, chan, "agi_rdnis: %s\n",
1735 S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "unknown"));
1737 /* Context information */
1738 ast_agi_send(fd, chan, "agi_context: %s\n", chan->context);
1739 ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten);
1740 ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority);
1741 ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
1743 /* User information */
1744 ast_agi_send(fd, chan, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
1745 ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
1747 /* Send any parameters to the fastagi server that have been passed via the agi application */
1748 /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
1749 for(count = 1; count < argc; count++)
1750 ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
1752 /* End with empty return */
1753 ast_agi_send(fd, chan, "\n");
1756 static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1760 /* Answer the channel */
1761 if (chan->_state != AST_STATE_UP)
1762 res = ast_answer(chan);
1764 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1765 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1768 static int handle_asyncagi_break(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1770 ast_agi_send(agi->fd, chan, "200 result=0\n");
1771 return ASYNC_AGI_BREAK;
1774 static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1779 return RESULT_SHOWUSAGE;
1780 if (sscanf(argv[3], "%30d", &to) != 1)
1781 return RESULT_SHOWUSAGE;
1782 res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
1783 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1784 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1787 static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1792 return RESULT_SHOWUSAGE;
1794 /* At the moment, the parser (perhaps broken) returns with
1795 the last argument PLUS the newline at the end of the input
1796 buffer. This probably needs to be fixed, but I wont do that
1797 because other stuff may break as a result. The right way
1798 would probably be to strip off the trailing newline before
1799 parsing, then here, add a newline at the end of the string
1800 before sending it to ast_sendtext --DUDE */
1801 res = ast_sendtext(chan, argv[2]);
1802 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1803 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1806 static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1811 return RESULT_SHOWUSAGE;
1813 res = ast_recvchar(chan,atoi(argv[2]));
1815 ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
1816 return RESULT_SUCCESS;
1819 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1820 return RESULT_SUCCESS;
1822 ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
1823 return RESULT_FAILURE;
1826 static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1831 return RESULT_SHOWUSAGE;
1833 buf = ast_recvtext(chan, atoi(argv[2]));
1835 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
1838 ast_agi_send(agi->fd, chan, "200 result=-1\n");
1840 return RESULT_SUCCESS;
1843 static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1848 return RESULT_SHOWUSAGE;
1850 if (!strncasecmp(argv[2],"on",2)) {
1855 if (!strncasecmp(argv[2],"mate",4)) {
1858 if (!strncasecmp(argv[2],"tdd",3)) {
1861 res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
1863 /* Set channel option failed */
1864 ast_agi_send(agi->fd, chan, "200 result=0\n");
1866 ast_agi_send(agi->fd, chan, "200 result=1\n");
1868 return RESULT_SUCCESS;
1871 static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1876 return RESULT_SHOWUSAGE;
1879 res = ast_send_image(chan, argv[2]);
1880 if (!ast_check_hangup(chan)) {
1883 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1884 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1887 static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1889 int res = 0, skipms = 3000;
1890 const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
1892 if (argc < 5 || argc > 9) {
1893 return RESULT_SHOWUSAGE;
1896 if (!ast_strlen_zero(argv[4])) {
1900 if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) {
1901 return RESULT_SHOWUSAGE;
1904 if (argc > 6 && !ast_strlen_zero(argv[6])) {
1908 if (argc > 7 && !ast_strlen_zero(argv[7])) {
1912 if (argc > 8 && !ast_strlen_zero(argv[8])) {
1916 res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL);
1918 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1920 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1923 static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1926 struct ast_filestream *fs, *vfs;
1927 long sample_offset = 0, max_length;
1928 const char *edigits = "";
1930 if (argc < 4 || argc > 5)
1931 return RESULT_SHOWUSAGE;
1936 if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1))
1937 return RESULT_SHOWUSAGE;
1939 if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
1940 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
1941 return RESULT_SUCCESS;
1944 if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
1945 ast_debug(1, "Ooh, found a video stream, too\n");
1947 ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset);
1949 ast_seekstream(fs, 0, SEEK_END);
1950 max_length = ast_tellstream(fs);
1951 ast_seekstream(fs, sample_offset, SEEK_SET);
1952 res = ast_applystream(chan, fs);
1954 ast_applystream(chan, vfs);
1957 ast_playstream(vfs);
1959 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
1960 /* this is to check for if ast_waitstream closed the stream, we probably are at
1961 * the end of the stream, return that amount, else check for the amount */
1962 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
1963 ast_stopstream(chan);
1965 /* Stop this command, don't print a result line, as there is a new command */
1966 return RESULT_SUCCESS;
1968 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
1969 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1972 /*! \brief get option - really similar to the handle_streamfile, but with a timeout */
1973 static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1976 struct ast_filestream *fs, *vfs;
1977 long sample_offset = 0, max_length;
1979 const char *edigits = "";
1981 if ( argc < 4 || argc > 5 )
1982 return RESULT_SHOWUSAGE;
1988 timeout = atoi(argv[4]);
1989 else if (chan->pbx->dtimeoutms) {
1990 /* by default dtimeout is set to 5sec */
1991 timeout = chan->pbx->dtimeoutms; /* in msec */
1994 if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
1995 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
1996 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
1997 return RESULT_SUCCESS;
2000 if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
2001 ast_debug(1, "Ooh, found a video stream, too\n");
2003 ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
2005 ast_seekstream(fs, 0, SEEK_END);
2006 max_length = ast_tellstream(fs);
2007 ast_seekstream(fs, sample_offset, SEEK_SET);
2008 res = ast_applystream(chan, fs);
2010 ast_applystream(chan, vfs);
2013 ast_playstream(vfs);
2015 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
2016 /* this is to check for if ast_waitstream closed the stream, we probably are at
2017 * the end of the stream, return that amount, else check for the amount */
2018 sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
2019 ast_stopstream(chan);
2021 /* Stop this command, don't print a result line, as there is a new command */
2022 return RESULT_SUCCESS;
2025 /* If the user didnt press a key, wait for digitTimeout*/
2027 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
2028 /* Make sure the new result is in the escape digits of the GET OPTION */
2029 if ( !strchr(edigits,res) )
2033 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
2034 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2040 /*! \brief Say number in various language syntaxes */
2041 /* While waiting, we're sending a NULL. */
2042 static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2046 if (argc < 4 || argc > 5)
2047 return RESULT_SHOWUSAGE;
2048 if (sscanf(argv[2], "%30d", &num) != 1)
2049 return RESULT_SHOWUSAGE;
2050 res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
2052 return RESULT_SUCCESS;
2053 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2054 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2057 static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2062 return RESULT_SHOWUSAGE;
2063 if (sscanf(argv[2], "%30d", &num) != 1)
2064 return RESULT_SHOWUSAGE;
2066 res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2067 if (res == 1) /* New command */
2068 return RESULT_SUCCESS;
2069 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2070 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2073 static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2078 return RESULT_SHOWUSAGE;
2080 res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2081 if (res == 1) /* New command */
2082 return RESULT_SUCCESS;
2083 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2084 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2087 static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2092 return RESULT_SHOWUSAGE;
2093 if (sscanf(argv[2], "%30d", &num) != 1)
2094 return RESULT_SHOWUSAGE;
2095 res = ast_say_date(chan, num, argv[3], chan->language);
2097 return RESULT_SUCCESS;
2098 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2099 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2102 static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2107 return RESULT_SHOWUSAGE;
2108 if (sscanf(argv[2], "%30d", &num) != 1)
2109 return RESULT_SHOWUSAGE;
2110 res = ast_say_time(chan, num, argv[3], chan->language);
2112 return RESULT_SUCCESS;
2113 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2114 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2117 static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2121 const char *format, *zone = NULL;
2124 return RESULT_SHOWUSAGE;
2129 /* XXX this doesn't belong here, but in the 'say' module */
2130 if (!strcasecmp(chan->language, "de")) {
2131 format = "A dBY HMS";
2133 format = "ABdY 'digits/at' IMp";
2137 if (argc > 5 && !ast_strlen_zero(argv[5]))
2140 if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
2141 return RESULT_SHOWUSAGE;
2143 res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone);
2145 return RESULT_SUCCESS;
2147 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2148 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2151 static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2156 return RESULT_SHOWUSAGE;
2158 res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2159 if (res == 1) /* New command */
2160 return RESULT_SUCCESS;
2161 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2162 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2165 static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2167 int res, max, timeout;
2171 return RESULT_SHOWUSAGE;
2173 timeout = atoi(argv[3]);
2177 max = atoi(argv[4]);
2180 res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
2181 if (res == 2) /* New command */
2182 return RESULT_SUCCESS;
2184 ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
2186 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2188 ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
2189 return RESULT_SUCCESS;
2192 static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2196 return RESULT_SHOWUSAGE;
2197 ast_copy_string(chan->context, argv[2], sizeof(chan->context));
2198 ast_agi_send(agi->fd, chan, "200 result=0\n");
2199 return RESULT_SUCCESS;
2202 static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2205 return RESULT_SHOWUSAGE;
2206 ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
2207 ast_agi_send(agi->fd, chan, "200 result=0\n");
2208 return RESULT_SUCCESS;
2211 static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2216 return RESULT_SHOWUSAGE;
2218 if (sscanf(argv[2], "%30d", &pri) != 1) {
2219 pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2],
2220 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
2222 return RESULT_SHOWUSAGE;
2225 ast_explicit_goto(chan, NULL, NULL, pri);
2226 ast_agi_send(agi->fd, chan, "200 result=0\n");
2227 return RESULT_SUCCESS;
2230 static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2232 struct ast_filestream *fs;
2233 struct ast_frame *f;
2234 struct timeval start;
2235 long sample_offset = 0;
2239 struct ast_dsp *sildet=NULL; /* silence detector dsp */
2240 int totalsilence = 0;
2242 int silence = 0; /* amount of silence to allow */
2243 int gotsilence = 0; /* did we timeout for silence? */
2244 char *silencestr = NULL;
2245 struct ast_format rfmt;
2246 ast_format_clear(&rfmt);
2248 /* XXX EAGI FIXME XXX */
2251 return RESULT_SHOWUSAGE;
2252 if (sscanf(argv[5], "%30d", &ms) != 1)
2253 return RESULT_SHOWUSAGE;
2256 silencestr = strchr(argv[6],'s');
2257 if ((argc > 7) && (!silencestr))
2258 silencestr = strchr(argv[7],'s');
2259 if ((argc > 8) && (!silencestr))
2260 silencestr = strchr(argv[8],'s');
2263 if (strlen(silencestr) > 2) {
2264 if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
2268 silence = atoi(silencestr);
2276 ast_format_copy(&rfmt, &chan->readformat);
2277 res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
2279 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
2280 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2281 return RESULT_FAILURE;
2283 sildet = ast_dsp_new();
2285 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
2286 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2287 return RESULT_FAILURE;
2289 ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
2292 /* backward compatibility, if no offset given, arg[6] would have been
2293 * caught below and taken to be a beep, else if it is a digit then it is a
2295 if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
2296 res = ast_streamfile(chan, "beep", chan->language);
2298 if ((argc > 7) && (!strchr(argv[7], '=')))
2299 res = ast_streamfile(chan, "beep", chan->language);
2302 res = ast_waitstream(chan, argv[4]);
2304 ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
2306 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE);
2309 ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res);
2311 ast_dsp_free(sildet);
2312 return RESULT_FAILURE;
2315 /* Request a video update */
2316 ast_indicate(chan, AST_CONTROL_VIDUPDATE);
2319 ast_applystream(chan,fs);
2320 /* really should have checks */
2321 ast_seekstream(fs, sample_offset, SEEK_SET);
2322 ast_truncstream(fs);
2324 start = ast_tvnow();
2325 while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
2326 res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
2328 ast_closestream(fs);
2329 ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
2331 ast_dsp_free(sildet);
2332 return RESULT_FAILURE;
2336 ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
2337 ast_closestream(fs);
2339 ast_dsp_free(sildet);
2340 return RESULT_FAILURE;
2342 switch(f->frametype) {
2343 case AST_FRAME_DTMF:
2344 if (strchr(argv[4], f->subclass.integer)) {
2345 /* This is an interrupting chracter, so rewind to chop off any small
2346 amount of DTMF that may have been recorded
2348 ast_stream_rewind(fs, 200);
2349 ast_truncstream(fs);
2350 sample_offset = ast_tellstream(fs);
2351 ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass.integer, sample_offset);
2352 ast_closestream(fs);
2355 ast_dsp_free(sildet);
2356 return RESULT_SUCCESS;
2359 case AST_FRAME_VOICE:
2360 ast_writestream(fs, f);
2361 /* this is a safe place to check progress since we know that fs
2362 * is valid after a write, and it will then have our current
2364 sample_offset = ast_tellstream(fs);
2367 ast_dsp_silence(sildet, f, &dspsilence);
2369 totalsilence = dspsilence;
2373 if (totalsilence > silence) {
2374 /* Ended happily with silence */
2380 case AST_FRAME_VIDEO:
2381 ast_writestream(fs, f);
2383 /* Ignore all other frames */
2392 ast_stream_rewind(fs, silence-1000);
2393 ast_truncstream(fs);
2394 sample_offset = ast_tellstream(fs);
2396 ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
2397 ast_closestream(fs);
2401 res = ast_set_read_format(chan, &rfmt);
2403 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
2404 ast_dsp_free(sildet);
2407 return RESULT_SUCCESS;
2410 static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2413 struct timeval whentohangup = { 0, 0 };
2416 return RESULT_SHOWUSAGE;
2417 if (sscanf(argv[2], "%30lf", &timeout) != 1)
2418 return RESULT_SHOWUSAGE;
2422 whentohangup.tv_sec = timeout;
2423 whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
2425 ast_channel_setwhentohangup_tv(chan, whentohangup);
2426 ast_agi_send(agi->fd, chan, "200 result=0\n");
2427 return RESULT_SUCCESS;
2430 static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2432 struct ast_channel *c;
2435 /* no argument: hangup the current channel */
2436 ast_set_hangupsource(chan, "dialplan/agi", 0);
2437 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
2438 ast_agi_send(agi->fd, chan, "200 result=1\n");
2439 return RESULT_SUCCESS;
2440 } else if (argc == 2) {
2441 /* one argument: look for info on the specified channel */
2442 if ((c = ast_channel_get_by_name(argv[1]))) {
2443 /* we have a matching channel */
2444 ast_set_hangupsource(c, "dialplan/agi", 0);
2445 ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
2446 c = ast_channel_unref(c);
2447 ast_agi_send(agi->fd, chan, "200 result=1\n");
2448 return RESULT_SUCCESS;
2450 /* if we get this far no channel name matched the argument given */
2451 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2452 return RESULT_SUCCESS;
2454 return RESULT_SHOWUSAGE;
2458 static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2460 int res, workaround;
2461 struct ast_app *app_to_exec;
2464 return RESULT_SHOWUSAGE;
2466 ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : "");
2468 if ((app_to_exec = pbx_findapp(argv[1]))) {
2469 if(!strcasecmp(argv[1], PARK_APP_NAME)) {
2470 ast_masq_park_call(chan, NULL, 0, NULL);
2472 if (!(workaround = ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS))) {
2473 ast_set_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS);
2475 if (ast_compat_res_agi && argc >= 3 && !ast_strlen_zero(argv[2])) {
2476 char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr;
2478 for (cptr = compat, vptr = argv[2]; *vptr; vptr++) {
2482 } else if (*vptr == '|') {
2489 res = pbx_exec(chan, app_to_exec, compat);
2491 res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]);
2494 ast_clear_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS);
2497 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
2500 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2502 /* Even though this is wrong, users are depending upon this result. */
2506 static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2509 char *l = NULL, *n = NULL;
2512 ast_copy_string(tmp, argv[2], sizeof(tmp));
2513 ast_callerid_parse(tmp, &n, &l);
2515 ast_shrink_phone_number(l);
2520 ast_set_callerid(chan, l, n, NULL);
2523 ast_agi_send(agi->fd, chan, "200 result=1\n");
2524 return RESULT_SUCCESS;
2527 static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2529 struct ast_channel *c;
2531 /* no argument: supply info on the current channel */
2532 ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state);
2533 return RESULT_SUCCESS;
2534 } else if (argc == 3) {
2535 /* one argument: look for info on the specified channel */
2536 if ((c = ast_channel_get_by_name(argv[2]))) {
2537 ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state);
2538 c = ast_channel_unref(c);
2539 return RESULT_SUCCESS;
2541 /* if we get this far no channel name matched the argument given */
2542 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2543 return RESULT_SUCCESS;
2545 return RESULT_SHOWUSAGE;
2549 static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2552 pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
2554 ast_agi_send(agi->fd, chan, "200 result=1\n");
2555 return RESULT_SUCCESS;
2558 static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2561 char tempstr[1024] = "";
2564 return RESULT_SHOWUSAGE;
2566 /* check if we want to execute an ast_custom_function */
2567 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
2568 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
2570 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
2574 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
2576 ast_agi_send(agi->fd, chan, "200 result=0\n");
2578 return RESULT_SUCCESS;
2581 static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2583 struct ast_channel *chan2 = NULL;
2585 if (argc != 4 && argc != 5) {
2586 return RESULT_SHOWUSAGE;
2590 chan2 = ast_channel_get_by_name(argv[4]);
2592 chan2 = ast_channel_ref(chan);
2596 struct ast_str *str = ast_str_create(16);
2598 ast_agi_send(agi->fd, chan, "200 result=0\n");
2599 return RESULT_SUCCESS;
2601 ast_str_substitute_variables(&str, 0, chan2, argv[3]);
2602 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(str));
2605 ast_agi_send(agi->fd, chan, "200 result=0\n");
2609 chan2 = ast_channel_unref(chan2);
2612 return RESULT_SUCCESS;
2615 static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2620 return RESULT_SHOWUSAGE;
2623 sscanf(argv[2], "%30d", &level);
2625 ast_verb(level, "%s: %s\n", chan->data, argv[1]);
2627 ast_agi_send(agi->fd, chan, "200 result=1\n");
2629 return RESULT_SUCCESS;
2632 static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2635 struct ast_str *buf;
2638 return RESULT_SHOWUSAGE;
2640 if (!(buf = ast_str_create(16))) {
2641 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2642 return RESULT_SUCCESS;
2646 res = ast_db_get(argv[2], argv[3], ast_str_buffer(buf), ast_str_size(buf));
2647 ast_str_update(buf);
2648 if (ast_str_strlen(buf) < ast_str_size(buf) - 1) {
2651 if (ast_str_make_space(&buf, ast_str_size(buf) * 2)) {
2657 ast_agi_send(agi->fd, chan, "200 result=0\n");
2659 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(buf));
2662 return RESULT_SUCCESS;
2665 static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2670 return RESULT_SHOWUSAGE;
2671 res = ast_db_put(argv[2], argv[3], argv[4]);
2672 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
2673 return RESULT_SUCCESS;
2676 static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2681 return RESULT_SHOWUSAGE;
2682 res = ast_db_del(argv[2], argv[3]);
2683 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
2684 return RESULT_SUCCESS;
2687 static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2691 if ((argc < 3) || (argc > 4))
2692 return RESULT_SHOWUSAGE;
2694 res = ast_db_deltree(argv[2], argv[3]);
2696 res = ast_db_deltree(argv[2], NULL);
2698 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
2699 return RESULT_SUCCESS;
2702 static char *handle_cli_agi_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2706 e->command = "agi set debug [on|off]";
2708 "Usage: agi set debug [on|off]\n"
2709 " Enables/disables dumping of AGI transactions for\n"
2710 " debugging purposes.\n";
2717 if (a->argc != e->args)
2718 return CLI_SHOWUSAGE;
2720 if (strncasecmp(a->argv[3], "off", 3) == 0) {
2722 } else if (strncasecmp(a->argv[3], "on", 2) == 0) {
2725 return CLI_SHOWUSAGE;
2727 ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis");
2731 static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char * const argv[])
2733 ast_agi_send(agi->fd, chan, "200 result=0\n");
2734 return RESULT_SUCCESS;
2737 static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2740 return RESULT_SHOWUSAGE;
2742 if (!strncasecmp(argv[2], "on", 2))
2743 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
2744 else if (!strncasecmp(argv[2], "off", 3))
2746 ast_agi_send(agi->fd, chan, "200 result=0\n");
2747 return RESULT_SUCCESS;
2750 static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2752 struct ast_format_cap *cap;
2753 struct ast_format tmpfmt;
2755 /* If a structure already exists, return an error */
2757 ast_agi_send(agi->fd, chan, "200 result=0\n");
2758 return RESULT_SUCCESS;
2761 if (!(cap = ast_format_cap_alloc_nolock())) {
2762 return RESULT_FAILURE;
2764 ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
2765 if ((agi->speech = ast_speech_new(argv[2], cap))) {
2766 ast_agi_send(agi->fd, chan, "200 result=1\n");
2768 ast_agi_send(agi->fd, chan, "200 result=0\n");
2770 cap = ast_format_cap_destroy(cap);
2772 return RESULT_SUCCESS;
2775 static int handle_speechset(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2777 /* Check for minimum arguments */
2779 return RESULT_SHOWUSAGE;
2781 /* Check to make sure speech structure exists */
2783 ast_agi_send(agi->fd, chan, "200 result=0\n");
2784 return RESULT_SUCCESS;
2787 ast_speech_change(agi->speech, argv[2], argv[3]);
2788 ast_agi_send(agi->fd, chan, "200 result=1\n");
2790 return RESULT_SUCCESS;
2793 static int handle_speechdestroy(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2796 ast_speech_destroy(agi->speech);
2798 ast_agi_send(agi->fd, chan, "200 result=1\n");
2800 ast_agi_send(agi->fd, chan, "200 result=0\n");
2803 return RESULT_SUCCESS;
2806 static int handle_speechloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2809 return RESULT_SHOWUSAGE;
2812 ast_agi_send(agi->fd, chan, "200 result=0\n");
2813 return RESULT_SUCCESS;
2816 if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
2817 ast_agi_send(agi->fd, chan, "200 result=0\n");
2819 ast_agi_send(agi->fd, chan, "200 result=1\n");
2821 return RESULT_SUCCESS;
2824 static int handle_speechunloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2827 return RESULT_SHOWUSAGE;
2830 ast_agi_send(agi->fd, chan, "200 result=0\n");
2831 return RESULT_SUCCESS;
2834 if (ast_speech_grammar_unload(agi->speech, argv[3]))
2835 ast_agi_send(agi->fd, chan, "200 result=0\n");
2837 ast_agi_send(agi->fd, chan, "200 result=1\n");
2839 return RESULT_SUCCESS;
2842 static int handle_speechactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2845 return RESULT_SHOWUSAGE;
2848 ast_agi_send(agi->fd, chan, "200 result=0\n");
2849 return RESULT_SUCCESS;
2852 if (ast_speech_grammar_activate(agi->speech, argv[3]))
2853 ast_agi_send(agi->fd, chan, "200 result=0\n");
2855 ast_agi_send(agi->fd, chan, "200 result=1\n");
2857 return RESULT_SUCCESS;
2860 static int handle_speechdeactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2863 return RESULT_SHOWUSAGE;
2866 ast_agi_send(agi->fd, chan, "200 result=0\n");
2867 return RESULT_SUCCESS;
2870 if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
2871 ast_agi_send(agi->fd, chan, "200 result=0\n");
2873 ast_agi_send(agi->fd, chan, "200 result=1\n");
2875 return RESULT_SUCCESS;
2878 static int speech_streamfile(struct ast_channel *chan, const char *filename, const char *preflang, int offset)
2880 struct ast_filestream *fs = NULL;
2882 if (!(fs = ast_openstream(chan, filename, preflang)))
2886 ast_seekstream(fs, offset, SEEK_SET);
2888 if (ast_applystream(chan, fs))
2891 if (ast_playstream(fs))
2897 static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2899 struct ast_speech *speech = agi->speech;
2901 char dtmf = 0, tmp[4096] = "", *buf = tmp;
2902 int timeout = 0, offset = 0, res = 0, i = 0;
2903 struct ast_format old_read_format;
2904 long current_offset = 0;
2905 const char *reason = NULL;
2906 struct ast_frame *fr = NULL;
2907 struct ast_speech_result *result = NULL;
2908 size_t left = sizeof(tmp);
2909 time_t start = 0, current;
2912 return RESULT_SHOWUSAGE;
2915 ast_agi_send(agi->fd, chan, "200 result=0\n");
2916 return RESULT_SUCCESS;
2920 timeout = atoi(argv[3]);
2922 /* If offset is specified then convert from text to integer */
2924 offset = atoi(argv[4]);
2926 /* We want frames coming in signed linear */
2927 ast_format_copy(&old_read_format, &chan->readformat);
2928 if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
2929 ast_agi_send(agi->fd, chan, "200 result=0\n");
2930 return RESULT_SUCCESS;
2933 /* Setup speech structure */
2934 if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
2935 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
2936 ast_speech_start(speech);
2939 /* Start playing prompt */
2940 speech_streamfile(chan, prompt, chan->language, offset);
2942 /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */
2943 while (ast_strlen_zero(reason)) {
2944 /* Run scheduled items */
2945 ast_sched_runq(chan->sched);
2947 /* See maximum time of waiting */
2948 if ((res = ast_sched_wait(chan->sched)) < 0)
2951 /* Wait for frame */
2952 if (ast_waitfor(chan, res) > 0) {
2953 if (!(fr = ast_read(chan))) {
2959 /* Perform timeout check */
2960 if ((timeout > 0) && (start > 0)) {
2962 if ((current - start) >= timeout) {
2970 /* Check the speech structure for any changes */
2971 ast_mutex_lock(&speech->lock);
2973 /* See if we need to quiet the audio stream playback */
2974 if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) {
2975 current_offset = ast_tellstream(chan->stream);
2976 ast_stopstream(chan);
2977 ast_clear_flag(speech, AST_SPEECH_QUIET);
2980 /* Check each state */
2981 switch (speech->state) {
2982 case AST_SPEECH_STATE_READY:
2983 /* If the stream is done, start timeout calculation */
2984 if ((timeout > 0) && start == 0 && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) {
2985 ast_stopstream(chan);
2988 /* Write audio frame data into speech engine if possible */
2989 if (fr && fr->frametype == AST_FRAME_VOICE)
2990 ast_speech_write(speech, fr->data.ptr, fr->datalen);
2992 case AST_SPEECH_STATE_WAIT:
2993 /* Cue waiting sound if not already playing */
2994 if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) {
2995 ast_stopstream(chan);
2996 /* If a processing sound exists, or is not none - play it */
2997 if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none"))
2998 speech_streamfile(chan, speech->processing_sound, chan->language, 0);
3001 case AST_SPEECH_STATE_DONE:
3002 /* Get the results */
3003 speech->results = ast_speech_results_get(speech);
3004 /* Change state to not ready */
3005 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
3011 ast_mutex_unlock(&speech->lock);
3013 /* Check frame for DTMF or hangup */
3015 if (fr->frametype == AST_FRAME_DTMF) {
3017 dtmf = fr->subclass.integer;
3018 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_HANGUP) {
3025 if (!strcasecmp(reason, "speech")) {
3026 /* Build string containing speech results */
3027 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) {
3028 /* Build result string */
3029 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);
3030 /* Increment result count */
3034 ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
3035 } else if (!strcasecmp(reason, "dtmf")) {
3036 ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
3037 } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
3038 ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
3040 ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset);
3043 return RESULT_SUCCESS;
3047 * \brief AGI commands list
3049 static struct agi_command commands[] = {
3050 { { "answer", NULL }, handle_answer, NULL, NULL, 0 },
3051 { { "asyncagi", "break", NULL }, handle_asyncagi_break, NULL, NULL, 1 },
3052 { { "channel", "status", NULL }, handle_channelstatus, NULL, NULL, 0 },
3053 { { "database", "del", NULL }, handle_dbdel, NULL, NULL, 1 },
3054 { { "database", "deltree", NULL }, handle_dbdeltree, NULL, NULL, 1 },
3055 { { "database", "get", NULL }, handle_dbget, NULL, NULL, 1 },
3056 { { "database", "put", NULL }, handle_dbput, NULL, NULL, 1 },
3057 { { "exec", NULL }, handle_exec, NULL, NULL, 1 },
3058 { { "get", "data", NULL }, handle_getdata, NULL, NULL, 0 },
3059 { { "get", "full", "variable", NULL }, handle_getvariablefull, NULL, NULL, 1 },
3060 { { "get", "option", NULL }, handle_getoption, NULL, NULL, 0 },
3061 { { "get", "variable", NULL }, handle_getvariable, NULL, NULL, 1 },
3062 { { "hangup", NULL }, handle_hangup, NULL, NULL, 0 },
3063 { { "noop", NULL }, handle_noop, NULL, NULL, 1 },
3064 { { "receive", "char", NULL }, handle_recvchar, NULL, NULL, 0 },
3065 { { "receive", "text", NULL }, handle_recvtext, NULL, NULL, 0 },
3066 { { "record", "file", NULL }, handle_recordfile, NULL, NULL, 0 },
3067 { { "say", "alpha", NULL }, handle_sayalpha, NULL, NULL, 0},
3068 { { "say", "digits", NULL }, handle_saydigits, NULL, NULL, 0 },
3069 { { "say", "number", NULL }, handle_saynumber, NULL, NULL, 0 },
3070 { { "say", "phonetic", NULL }, handle_sayphonetic, NULL, NULL, 0},
3071 { { "say", "date", NULL }, handle_saydate, NULL, NULL, 0},
3072 { { "say", "time", NULL }, handle_saytime, NULL, NULL, 0},
3073 { { "say", "datetime", NULL }, handle_saydatetime, NULL, NULL, 0},
3074 { { "send", "image", NULL }, handle_sendimage, NULL, NULL, 0},
3075 { { "send", "text", NULL }, handle_sendtext, NULL, NULL, 0},
3076 { { "set", "autohangup", NULL }, handle_autohangup, NULL, NULL, 0},
3077 { { "set", "callerid", NULL }, handle_setcallerid, NULL, NULL, 0},
3078 { { "set", "context", NULL }, handle_setcontext, NULL, NULL, 0},
3079 { { "set", "extension", NULL }, handle_setextension, NULL, NULL, 0},
3080 { { "set", "music", NULL }, handle_setmusic, NULL, NULL, 0 },
3081 { { "set", "priority", NULL }, handle_setpriority, NULL, NULL, 0 },
3082 { { "set", "variable", NULL }, handle_setvariable, NULL, NULL, 1 },
3083 { { "stream", "file", NULL }, handle_streamfile, NULL, NULL, 0 },
3084 { { "control", "stream", "file", NULL }, handle_controlstreamfile, NULL, NULL, 0 },
3085 { { "tdd", "mode", NULL }, handle_tddmode, NULL, NULL, 0 },
3086 { { "verbose", NULL }, handle_verbose, NULL, NULL, 1 },
3087 { { "wait", "for", "digit", NULL }, handle_waitfordigit, NULL, NULL, 0 },
3088 { { "speech", "create", NULL }, handle_speechcreate, NULL, NULL, 0 },
3089 { { "speech", "set", NULL }, handle_speechset, NULL, NULL, 0 },
3090 { { "speech", "destroy", NULL }, handle_speechdestroy, NULL, NULL, 1 },
3091 { { "speech", "load", "grammar", NULL }, handle_speechloadgrammar, NULL, NULL, 0 },
3092 { { "speech", "unload", "grammar", NULL }, handle_speechunloadgrammar, NULL, NULL, 1 },
3093 { { "speech", "activate", "grammar", NULL }, handle_speechactivategrammar, NULL, NULL, 0 },
3094 { { "speech", "deactivate", "grammar", NULL }, handle_speechdeactivategrammar, NULL, NULL, 0 },
3095 { { "speech", "recognize", NULL }, handle_speechrecognize, NULL, NULL, 0 },
3098 static AST_RWLIST_HEAD_STATIC(agi_commands, agi_command);
3100 static char *help_workhorse(int fd, const char * const match[])
3102 char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN];
3103 struct agi_command *e;
3106 ast_join(matchstr, sizeof(matchstr), match);
3108 ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description");
3109 AST_RWLIST_RDLOCK(&agi_commands);
3110 AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
3113 /* Hide commands that start with '_' */
3114 if ((e->cmda[0])[0] == '_')
3116 ast_join(fullcmd, sizeof(fullcmd), e->cmda);
3117 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
3119 ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, S_OR(e->summary, "Not available"));
3121 AST_RWLIST_UNLOCK(&agi_commands);
3126 int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command *cmd)
3128 char fullcmd[MAX_CMD_LEN];
3130 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3132 if (!find_command(cmd->cmda, 1)) {
3133 *((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC;
3134 if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
3136 *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd);
3137 *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd);
3138 *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd);
3139 *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd);
3140 *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
3142 #ifndef HAVE_NULLSAFE_PRINTF
3143 if (!cmd->summary) {
3144 *((char **) &cmd->summary) = ast_strdup("");
3147 *((char **) &cmd->usage) = ast_strdup("");
3150 *((char **) &cmd->syntax) = ast_strdup("");
3152 if (!cmd->seealso) {
3153 *((char **) &cmd->seealso) = ast_strdup("");
3159 AST_RWLIST_WRLOCK(&agi_commands);
3160 AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
3161 AST_RWLIST_UNLOCK(&agi_commands);
3162 if (mod != ast_module_info->self)
3163 ast_module_ref(ast_module_info->self);
3164 ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
3167 ast_log(LOG_WARNING, "Command already registered!\n");
3172 int AST_OPTIONAL_API_NAME(ast_agi_unregister)(struct ast_module *mod, agi_command *cmd)
3174 struct agi_command *e;
3175 int unregistered = 0;
3176 char fullcmd[MAX_CMD_LEN];
3178 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3180 AST_RWLIST_WRLOCK(&agi_commands);
3181 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) {
3183 AST_RWLIST_REMOVE_CURRENT(list);
3184 if (mod != ast_module_info->self)
3185 ast_module_unref(ast_module_info->self);
3187 if (e->docsrc == AST_XML_DOC) {
3188 ast_free((char *) e->summary);
3189 ast_free((char *) e->usage);
3190 ast_free((char *) e->syntax);
3191 ast_free((char *) e->seealso);
3192 *((char **) &e->summary) = NULL;
3193 *((char **) &e->usage) = NULL;
3194 *((char **) &e->syntax) = NULL;
3195 *((char **) &e->seealso) = NULL;
3202 AST_RWLIST_TRAVERSE_SAFE_END;
3203 AST_RWLIST_UNLOCK(&agi_commands);
3205 ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd);
3207 ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd);
3208 return unregistered;
3211 int AST_OPTIONAL_API_NAME(ast_agi_register_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
3213 unsigned int i, x = 0;
3215 for (i = 0; i < len; i++) {
3216 if (ast_agi_register(mod, cmd + i) == 1) {
3221 /* registration failed, unregister everything
3222 that had been registered up to that point
3224 for (; x > 0; x--) {
3225 /* we are intentionally ignoring the
3226 result of ast_agi_unregister() here,
3227 but it should be safe to do so since
3228 we just registered these commands and
3229 the only possible way for unregistration
3230 to fail is if the command is not
3233 (void) ast_agi_unregister(mod, cmd + x - 1);
3241 int AST_OPTIONAL_API_NAME(ast_agi_unregister_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
3246 for (i = 0; i < len; i++) {
3247 /* remember whether any of the unregistration
3248 attempts failed... there is no recourse if
3251 res |= ast_agi_unregister(mod, cmd + i);
3257 static agi_command *find_command(const char * const cmds[], int exact)
3260 struct agi_command *e;
3262 AST_RWLIST_RDLOCK(&agi_commands);
3263 AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
3266 /* start optimistic */
3268 for (y = 0; match && cmds[y]; y++) {
3269 /* If there are no more words in the command (and we're looking for
3270 an exact match) or there is a difference between the two words,
3271 then this is not a match */
3272 if (!e->cmda[y] && !exact)
3274 /* don't segfault if the next part of a command doesn't exist */
3276 AST_RWLIST_UNLOCK(&agi_commands);
3279 if (strcasecmp(e->cmda[y], cmds[y]))
3282 /* If more words are needed to complete the command then this is not
3283 a candidate (unless we're looking for a really inexact answer */
3284 if ((exact > -1) && e->cmda[y])
3287 AST_RWLIST_UNLOCK(&agi_commands);
3291 AST_RWLIST_UNLOCK(&agi_commands);
3295 static int parse_args(char *s, int *max, const char *argv[])
3297 int x = 0, quoted = 0, escaped = 0, whitespace = 1;
3304 /* If it's escaped, put a literal quote */
3309 if (quoted && whitespace) {
3310 /* If we're starting a quote, coming off white space start a new word, too */
3318 if (!quoted && !escaped) {
3319 /* If we're not quoted, mark this as whitespace, and
3320 end the previous argument */
3324 /* Otherwise, just treat it as anything else */
3328 /* If we're escaped, print a literal, otherwise enable escaping */
3338 if (x >= MAX_ARGS -1) {
3339 ast_log(LOG_WARNING, "Too many arguments, truncating\n");
3342 /* Coming off of whitespace, start the next argument */
3351 /* Null terminate */
3358 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
3360 const char *argv[MAX_ARGS];
3361 int argc = MAX_ARGS;
3364 const char *ami_res;
3365 char *ami_cmd = ast_strdupa(buf);
3366 int command_id = ast_random();
3369 manager_event(EVENT_FLAG_AGI, "AGIExec",
3370 "SubEvent: Start\r\n"
3373 "Command: %s\r\n", chan->name, command_id, ami_cmd);
3374 parse_args(buf, &argc, argv);
3375 c = find_command(argv, 0);
3376 if (c && (!dead || (dead && c->dead))) {
3377 /* if this command wasn't registered by res_agi, be sure to usecount
3378 the module we are using */
3379 if (c->mod != ast_module_info->self)
3380 ast_module_ref(c->mod);
3381 /* If the AGI command being executed is an actual application (using agi exec)
3382 the app field will be updated in pbx_exec via handle_exec */
3383 if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC"))
3384 ast_cdr_setapp(chan->cdr, "AGI", buf);
3386 res = c->handler(chan, agi, argc, argv);
3387 if (c->mod != ast_module_info->self)
3388 ast_module_unref(c->mod);
3390 case RESULT_SHOWUSAGE:
3394 case RESULT_FAILURE:
3395 ami_res = "Failure";
3398 case ASYNC_AGI_BREAK:
3399 case RESULT_SUCCESS:
3400 ami_res = "Success";
3404 ami_res = "Unknown Result";
3408 manager_event(EVENT_FLAG_AGI, "AGIExec",
3413 "ResultCode: %d\r\n"
3414 "Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res);
3416 case RESULT_SHOWUSAGE:
3417 if (ast_strlen_zero(c->usage)) {
3418 ast_agi_send(agi->fd, chan, "520 Invalid command syntax. Proper usage not available.\n");
3420 ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n");
3421 ast_agi_send(agi->fd, chan, "%s", c->usage);
3422 ast_agi_send(agi->fd, chan, "520 End of proper usage.\n");
3425 case ASYNC_AGI_BREAK:
3426 return AGI_RESULT_SUCCESS_ASYNC;
3427 case RESULT_FAILURE:
3428 /* The RESULT_FAILURE code is usually because the channel hungup. */
3429 return AGI_RESULT_FAILURE;
3434 ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n");
3435 manager_event(EVENT_FLAG_AGI, "AGIExec",
3440 "ResultCode: 511\r\n"
3441 "Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd);
3443 ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n");
3444 manager_event(EVENT_FLAG_AGI, "AGIExec",
3449 "ResultCode: 510\r\n"
3450 "Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd);
3452 return AGI_RESULT_SUCCESS;
3454 static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
3456 struct ast_channel *c;
3460 enum agi_result returnstatus = AGI_RESULT_SUCCESS;
3461 struct ast_frame *f;
3462 char buf[AGI_BUF_LEN];
3465 /* how many times we'll retry if ast_waitfor_nandfs will return without either
3466 channel or file descriptor in case select is interrupted by a system call (EINTR) */
3467 int retry = AGI_NANDFS_RETRY;
3469 const char *sighup_str;
3471 ast_channel_lock(chan);
3472 sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
3473 send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str);
3474 ast_channel_unlock(chan);
3476 if (!(readf = fdopen(agi->ctrl, "r"))) {
3477 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
3478 if (send_sighup && pid > -1)
3481 return AGI_RESULT_FAILURE;
3485 setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv);
3493 } else if (agi->fast) {
3494 send(agi->ctrl, "HANGUP\n", 7, 0);
3500 c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
3501 } else if (!ast_check_hangup(chan)) {
3502 c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);