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
29 <support_level>core</support_level>
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
43 #include "asterisk/paths.h" /* use many ast_config_AST_*_DIR */
44 #include "asterisk/network.h"
45 #include "asterisk/file.h"
46 #include "asterisk/channel.h"
47 #include "asterisk/pbx.h"
48 #include "asterisk/module.h"
49 #include "asterisk/astdb.h"
50 #include "asterisk/callerid.h"
51 #include "asterisk/cli.h"
52 #include "asterisk/image.h"
53 #include "asterisk/say.h"
54 #include "asterisk/app.h"
55 #include "asterisk/dsp.h"
56 #include "asterisk/musiconhold.h"
57 #include "asterisk/utils.h"
58 #include "asterisk/lock.h"
59 #include "asterisk/strings.h"
60 #include "asterisk/manager.h"
61 #include "asterisk/ast_version.h"
62 #include "asterisk/speech.h"
63 #include "asterisk/manager.h"
64 #include "asterisk/features.h"
65 #include "asterisk/term.h"
66 #include "asterisk/xmldoc.h"
67 #include "asterisk/srv.h"
68 #include "asterisk/test.h"
70 #define AST_API_MODULE
71 #include "asterisk/agi.h"
74 <agi name="answer" language="en_US">
80 <para>Answers channel if not already in answer state. Returns <literal>-1</literal> on
81 channel failure, or <literal>0</literal> if successful.</para>
84 <ref type="agi">hangup</ref>
87 <agi name="asyncagi break" language="en_US">
93 <para>Interrupts expected flow of Async AGI commands and returns control to previous source
94 (typically, the PBX dialplan).</para>
97 <ref type="agi">hangup</ref>
100 <agi name="channel status" language="en_US">
102 Returns status of the connected channel.
105 <parameter name="channelname" />
108 <para>Returns the status of the specified <replaceable>channelname</replaceable>.
109 If no channel name is given then returns the status of the current channel.</para>
110 <para>Return values:</para>
113 <para>Channel is down and available.</para>
116 <para>Channel is down, but reserved.</para>
119 <para>Channel is off hook.</para>
122 <para>Digits (or equivalent) have been dialed.</para>
125 <para>Line is ringing.</para>
128 <para>Remote end is ringing.</para>
131 <para>Line is up.</para>
134 <para>Line is busy.</para>
139 <agi name="control stream file" language="en_US">
141 Sends audio file on channel and allows the listener to control the stream.
144 <parameter name="filename" required="true">
145 <para>The file extension must not be included in the filename.</para>
147 <parameter name="escape_digits" required="true" />
148 <parameter name="skipms" />
149 <parameter name="ffchar">
150 <para>Defaults to <literal>*</literal></para>
152 <parameter name="rewchr">
153 <para>Defaults to <literal>#</literal></para>
155 <parameter name="pausechr" />
158 <para>Send the given file, allowing playback to be controlled by the given
159 digits, if any. Use double quotes for the digits if you wish none to be
160 permitted. Returns <literal>0</literal> if playback completes without a digit
161 being pressed, or the ASCII numerical value of the digit if one was pressed,
162 or <literal>-1</literal> on error or if the channel was disconnected.</para>
165 <agi name="database del" language="en_US">
167 Removes database key/value
170 <parameter name="family" required="true" />
171 <parameter name="key" required="true" />
174 <para>Deletes an entry in the Asterisk database for a given
175 <replaceable>family</replaceable> and <replaceable>key</replaceable>.</para>
176 <para>Returns <literal>1</literal> if successful, <literal>0</literal>
180 <agi name="database deltree" language="en_US">
182 Removes database keytree/value
185 <parameter name="family" required="true" />
186 <parameter name="keytree" />
189 <para>Deletes a <replaceable>family</replaceable> or specific <replaceable>keytree</replaceable>
190 within a <replaceable>family</replaceable> in the Asterisk database.</para>
191 <para>Returns <literal>1</literal> if successful, <literal>0</literal> otherwise.</para>
194 <agi name="database get" language="en_US">
199 <parameter name="family" required="true" />
200 <parameter name="key" required="true" />
203 <para>Retrieves an entry in the Asterisk database for a given <replaceable>family</replaceable>
204 and <replaceable>key</replaceable>.</para>
205 <para>Returns <literal>0</literal> if <replaceable>key</replaceable> is not set.
206 Returns <literal>1</literal> if <replaceable>key</replaceable> is set and returns the variable
207 in parenthesis.</para>
208 <para>Example return code: 200 result=1 (testvariable)</para>
211 <agi name="database put" language="en_US">
213 Adds/updates database value
216 <parameter name="family" required="true" />
217 <parameter name="key" required="true" />
218 <parameter name="value" required="true" />
221 <para>Adds or updates an entry in the Asterisk database for a given
222 <replaceable>family</replaceable>, <replaceable>key</replaceable>, and
223 <replaceable>value</replaceable>.</para>
224 <para>Returns <literal>1</literal> if successful, <literal>0</literal> otherwise.</para>
227 <agi name="exec" language="en_US">
229 Executes a given Application
232 <parameter name="application" required="true" />
233 <parameter name="options" required="true" />
236 <para>Executes <replaceable>application</replaceable> with given
237 <replaceable>options</replaceable>.</para>
238 <para>Returns whatever the <replaceable>application</replaceable> returns, or
239 <literal>-2</literal> on failure to find <replaceable>application</replaceable>.</para>
242 <agi name="get data" language="en_US">
244 Prompts for DTMF on a channel
247 <parameter name="file" required="true" />
248 <parameter name="timeout" />
249 <parameter name="maxdigits" />
252 <para>Stream the given <replaceable>file</replaceable>, and receive DTMF data.</para>
253 <para>Returns the digits received from the channel at the other end.</para>
256 <agi name="get full variable" language="en_US">
258 Evaluates a channel expression
261 <parameter name="variablename" required="true" />
262 <parameter name="channel name" />
265 <para>Returns <literal>0</literal> if <replaceable>variablename</replaceable> is not set
266 or channel does not exist. Returns <literal>1</literal> if <replaceable>variablename</replaceable>
267 is set and returns the variable in parenthesis. Understands complex variable names and builtin
268 variables, unlike GET VARIABLE.</para>
269 <para>Example return code: 200 result=1 (testvariable)</para>
272 <agi name="get option" language="en_US">
274 Stream file, prompt for DTMF, with timeout.
277 <parameter name="filename" required="true" />
278 <parameter name="escape_digits" required="true" />
279 <parameter name="timeout" />
282 <para>Behaves similar to STREAM FILE but used with a timeout option.</para>
285 <ref type="agi">stream file</ref>
288 <agi name="get variable" language="en_US">
290 Gets a channel variable.
293 <parameter name="variablename" required="true" />
296 <para>Returns <literal>0</literal> if <replaceable>variablename</replaceable> is not set.
297 Returns <literal>1</literal> if <replaceable>variablename</replaceable> is set and returns
298 the variable in parentheses.</para>
299 <para>Example return code: 200 result=1 (testvariable)</para>
302 <agi name="hangup" language="en_US">
307 <parameter name="channelname" />
310 <para>Hangs up the specified channel. If no channel name is given, hangs
311 up the current channel</para>
314 <agi name="noop" language="en_US">
320 <para>Does nothing.</para>
323 <agi name="receive char" language="en_US">
325 Receives one character from channels supporting it.
328 <parameter name="timeout" required="true">
329 <para>The maximum time to wait for input in milliseconds, or <literal>0</literal>
330 for infinite. Most channels</para>
334 <para>Receives a character of text on a channel. Most channels do not support
335 the reception of text. Returns the decimal value of the character
336 if one is received, or <literal>0</literal> if the channel does not support
337 text reception. Returns <literal>-1</literal> only on error/hangup.</para>
340 <agi name="receive text" language="en_US">
342 Receives text from channels supporting it.
345 <parameter name="timeout" required="true">
346 <para>The timeout to be the maximum time to wait for input in
347 milliseconds, or <literal>0</literal> for infinite.</para>
351 <para>Receives a string of text on a channel. Most channels
352 do not support the reception of text. Returns <literal>-1</literal> for failure
353 or <literal>1</literal> for success, and the string in parenthesis.</para>
356 <agi name="record file" language="en_US">
358 Records to a given file.
361 <parameter name="filename" required="true" />
362 <parameter name="format" required="true" />
363 <parameter name="escape_digits" required="true" />
364 <parameter name="timeout" required="true" />
365 <parameter name="offset samples" />
366 <parameter name="BEEP" />
367 <parameter name="s=silence" />
370 <para>Record to a file until a given dtmf digit in the sequence is received.
371 Returns <literal>-1</literal> on hangup or error. The format will specify what kind of file
372 will be recorded. The <replaceable>timeout</replaceable> is the maximum record time in
373 milliseconds, or <literal>-1</literal> for no <replaceable>timeout</replaceable>.
374 <replaceable>offset samples</replaceable> is optional, and, if provided, will seek
375 to the offset without exceeding the end of the file. <replaceable>silence</replaceable> is
376 the number of seconds of silence allowed before the function returns despite the
377 lack of dtmf digits or reaching <replaceable>timeout</replaceable>. <replaceable>silence</replaceable>
378 value must be preceded by <literal>s=</literal> and is also optional.</para>
381 <agi name="say alpha" language="en_US">
383 Says a given character string.
386 <parameter name="number" required="true" />
387 <parameter name="escape_digits" required="true" />
390 <para>Say a given character string, returning early if any of the given DTMF digits
391 are received on the channel. Returns <literal>0</literal> if playback completes
392 without a digit being pressed, or the ASCII numerical value of the digit if one
393 was pressed or <literal>-1</literal> on error/hangup.</para>
396 <agi name="say digits" language="en_US">
398 Says a given digit string.
401 <parameter name="number" required="true" />
402 <parameter name="escape_digits" required="true" />
405 <para>Say a given digit string, returning early if any of the given DTMF digits
406 are received on the channel. Returns <literal>0</literal> if playback completes
407 without a digit being pressed, or the ASCII numerical value of the digit if one
408 was pressed or <literal>-1</literal> on error/hangup.</para>
411 <agi name="say number" language="en_US">
416 <parameter name="number" required="true" />
417 <parameter name="escape_digits" required="true" />
418 <parameter name="gender" />
421 <para>Say a given number, returning early if any of the given DTMF digits
422 are received on the channel. Returns <literal>0</literal> if playback
423 completes without a digit being pressed, or the ASCII numerical value of
424 the digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
427 <agi name="say phonetic" language="en_US">
429 Says a given character string with phonetics.
432 <parameter name="string" required="true" />
433 <parameter name="escape_digits" required="true" />
436 <para>Say a given character string with phonetics, returning early if any of the
437 given DTMF digits are received on the channel. Returns <literal>0</literal> if
438 playback completes without a digit pressed, the ASCII numerical value of the digit
439 if one was pressed, or <literal>-1</literal> on error/hangup.</para>
442 <agi name="say date" language="en_US">
447 <parameter name="date" required="true">
448 <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
449 Coordinated Universal Time (UTC).</para>
451 <parameter name="escape_digits" required="true" />
454 <para>Say a given date, returning early if any of the given DTMF digits are
455 received on the channel. Returns <literal>0</literal> if playback
456 completes without a digit being pressed, or the ASCII numerical value of the
457 digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
460 <agi name="say time" language="en_US">
465 <parameter name="time" required="true">
466 <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
467 Coordinated Universal Time (UTC).</para>
469 <parameter name="escape_digits" required="true" />
472 <para>Say a given time, returning early if any of the given DTMF digits are
473 received on the channel. Returns <literal>0</literal> if playback completes
474 without a digit being pressed, or the ASCII numerical value of the digit if
475 one was pressed or <literal>-1</literal> on error/hangup.</para>
478 <agi name="say datetime" language="en_US">
480 Says a given time as specified by the format given.
483 <parameter name="time" required="true">
484 <para>Is number of seconds elapsed since 00:00:00
485 on January 1, 1970, Coordinated Universal Time (UTC)</para>
487 <parameter name="escape_digits" required="true" />
488 <parameter name="format">
489 <para>Is the format the time should be said in. See
490 <filename>voicemail.conf</filename> (defaults to <literal>ABdY
491 'digits/at' IMp</literal>).</para>
493 <parameter name="timezone">
494 <para>Acceptable values can be found in <filename>/usr/share/zoneinfo</filename>
495 Defaults to machine default.</para>
499 <para>Say a given time, returning early if any of the given DTMF digits are
500 received on the channel. Returns <literal>0</literal> if playback
501 completes without a digit being pressed, or the ASCII numerical value of the
502 digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
505 <agi name="send image" language="en_US">
507 Sends images to channels supporting it.
510 <parameter name="image" required="true" />
513 <para>Sends the given image on a channel. Most channels do not support the
514 transmission of images. Returns <literal>0</literal> if image is sent, or if
515 the channel does not support image transmission. Returns <literal>-1</literal>
516 only on error/hangup. Image names should not include extensions.</para>
519 <agi name="send text" language="en_US">
521 Sends text to channels supporting it.
524 <parameter name="text to send" required="true">
525 <para>Text consisting of greater than one word should be placed
526 in quotes since the command only accepts a single argument.</para>
530 <para>Sends the given text on a channel. Most channels do not support the
531 transmission of text. Returns <literal>0</literal> if text is sent, or if the
532 channel does not support text transmission. Returns <literal>-1</literal> only
533 on error/hangup.</para>
536 <agi name="set autohangup" language="en_US">
538 Autohangup channel in some time.
541 <parameter name="time" required="true" />
544 <para>Cause the channel to automatically hangup at <replaceable>time</replaceable>
545 seconds in the future. Of course it can be hungup before then as well. Setting to
546 <literal>0</literal> will cause the autohangup feature to be disabled on this channel.</para>
549 <agi name="set callerid" language="en_US">
551 Sets callerid for the current channel.
554 <parameter name="number" required="true" />
557 <para>Changes the callerid of the current channel.</para>
560 <agi name="set context" language="en_US">
562 Sets channel context.
565 <parameter name="desired context" required="true" />
568 <para>Sets the context for continuation upon exiting the application.</para>
571 <agi name="set extension" language="en_US">
573 Changes channel extension.
576 <parameter name="new extension" required="true" />
579 <para>Changes the extension for continuation upon exiting the application.</para>
582 <agi name="set music" language="en_US">
584 Enable/Disable Music on hold generator
587 <parameter required="true">
590 <parameter name="on" literal="true" required="true" />
593 <parameter name="off" literal="true" required="true" />
597 <parameter name="class" required="true" />
600 <para>Enables/Disables the music on hold generator. If <replaceable>class</replaceable>
601 is not specified, then the <literal>default</literal> music on hold class will be
603 <para>Always returns <literal>0</literal>.</para>
606 <agi name="set priority" language="en_US">
608 Set channel dialplan priority.
611 <parameter name="priority" required="true" />
614 <para>Changes the priority for continuation upon exiting the application.
615 The priority must be a valid priority or label.</para>
618 <agi name="set variable" language="en_US">
620 Sets a channel variable.
623 <parameter name="variablename" required="true" />
624 <parameter name="value" required="true" />
627 <para>Sets a variable to the current channel.</para>
630 <agi name="stream file" language="en_US">
632 Sends audio file on channel.
635 <parameter name="filename" required="true">
636 <para>File name to play. The file extension must not be
637 included in the <replaceable>filename</replaceable>.</para>
639 <parameter name="escape_digits" required="true">
640 <para>Use double quotes for the digits if you wish none to be
643 <parameter name="sample offset">
644 <para>If sample offset is provided then the audio will seek to sample
645 offset before play starts.</para>
649 <para>Send the given file, allowing playback to be interrupted by the given
650 digits, if any. Returns <literal>0</literal> if playback completes without a digit
651 being pressed, or the ASCII numerical value of the digit if one was pressed,
652 or <literal>-1</literal> on error or if the channel was disconnected.</para>
655 <ref type="agi">control stream file</ref>
658 <agi name="tdd mode" language="en_US">
660 Toggles TDD mode (for the deaf).
663 <parameter name="boolean" required="true">
671 <para>Enable/Disable TDD transmission/reception on a channel. Returns <literal>1</literal> if
672 successful, or <literal>0</literal> if channel is not TDD-capable.</para>
675 <agi name="verbose" language="en_US">
677 Logs a message to the asterisk verbose log.
680 <parameter name="message" required="true" />
681 <parameter name="level" required="true" />
684 <para>Sends <replaceable>message</replaceable> to the console via verbose
685 message system. <replaceable>level</replaceable> is the verbose level (1-4).
686 Always returns <literal>1</literal></para>
689 <agi name="wait for digit" language="en_US">
691 Waits for a digit to be pressed.
694 <parameter name="timeout" required="true" />
697 <para>Waits up to <replaceable>timeout</replaceable> milliseconds for channel to
698 receive a DTMF digit. Returns <literal>-1</literal> on channel failure, <literal>0</literal>
699 if no digit is received in the timeout, or the numerical value of the ascii of the digit if
700 one is received. Use <literal>-1</literal> for the <replaceable>timeout</replaceable> value if
701 you desire the call to block indefinitely.</para>
704 <agi name="speech create" language="en_US">
706 Creates a speech object.
709 <parameter name="engine" required="true" />
712 <para>Create a speech object to be used by the other Speech AGI commands.</para>
715 <agi name="speech set" language="en_US">
717 Sets a speech engine setting.
720 <parameter name="name" required="true" />
721 <parameter name="value" required="true" />
724 <para>Set an engine-specific setting.</para>
727 <agi name="speech destroy" language="en_US">
729 Destroys a speech object.
734 <para>Destroy the speech object created by <literal>SPEECH CREATE</literal>.</para>
737 <ref type="agi">speech create</ref>
740 <agi name="speech load grammar" language="en_US">
745 <parameter name="grammar name" required="true" />
746 <parameter name="path to grammar" required="true" />
749 <para>Loads the specified grammar as the specified name.</para>
752 <agi name="speech unload grammar" language="en_US">
757 <parameter name="grammar name" required="true" />
760 <para>Unloads the specified grammar.</para>
763 <agi name="speech activate grammar" language="en_US">
768 <parameter name="grammar name" required="true" />
771 <para>Activates the specified grammar on the speech object.</para>
774 <agi name="speech deactivate grammar" language="en_US">
776 Deactivates a grammar.
779 <parameter name="grammar name" required="true" />
782 <para>Deactivates the specified grammar on the speech object.</para>
785 <agi name="speech recognize" language="en_US">
790 <parameter name="prompt" required="true" />
791 <parameter name="timeout" required="true" />
792 <parameter name="offset" />
795 <para>Plays back given <replaceable>prompt</replaceable> while listening for
796 speech and dtmf.</para>
799 <application name="AGI" language="en_US">
801 Executes an AGI compliant application.
804 <parameter name="command" required="true" />
805 <parameter name="args">
806 <argument name="arg1" required="true" />
807 <argument name="arg2" multiple="yes" />
811 <para>Executes an Asterisk Gateway Interface compliant
812 program on a channel. AGI allows Asterisk to launch external programs written
813 in any language to control a telephony channel, play audio, read DTMF digits,
814 etc. by communicating with the AGI protocol on <emphasis>stdin</emphasis> and
815 <emphasis>stdout</emphasis>. As of <literal>1.6.0</literal>, this channel will
816 not stop dialplan execution on hangup inside of this application. Dialplan
817 execution will continue normally, even upon hangup until the AGI application
818 signals a desire to stop (either by exiting or, in the case of a net script, by
819 closing the connection). A locally executed AGI script will receive SIGHUP on
820 hangup from the channel except when using DeadAGI. A fast AGI server will
821 correspondingly receive a HANGUP inline with the command dialog. Both of theses
822 signals may be disabled by setting the <variable>AGISIGHUP</variable> channel
823 variable to <literal>no</literal> before executing the AGI application.</para>
824 <para>Use the CLI command <literal>agi show commands</literal> to list available agi
826 <para>This application sets the following channel variable upon completion:</para>
828 <variable name="AGISTATUS">
829 <para>The status of the attempt to the run the AGI script
830 text string, one of:</para>
831 <value name="SUCCESS" />
832 <value name="FAILURE" />
833 <value name="NOTFOUND" />
834 <value name="HANGUP" />
839 <ref type="application">EAGI</ref>
840 <ref type="application">DeadAGI</ref>
843 <application name="EAGI" language="en_US">
845 Executes an EAGI compliant application.
848 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
849 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
852 <para>Using 'EAGI' provides enhanced AGI, with incoming audio available out of band
853 on file descriptor 3.</para>
854 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/para)" />
855 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
858 <ref type="application">AGI</ref>
859 <ref type="application">DeadAGI</ref>
862 <application name="DeadAGI" language="en_US">
864 Executes AGI on a hungup channel.
867 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
868 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
871 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/para)" />
872 <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
875 <ref type="application">AGI</ref>
876 <ref type="application">EAGI</ref>
879 <manager name="AGI" language="en_US">
881 Add an AGI command to execute by Async AGI.
884 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
885 <parameter name="Channel" required="true">
886 <para>Channel that is currently in Async AGI.</para>
888 <parameter name="Command" required="true">
889 <para>Application to execute.</para>
891 <parameter name="CommandID">
892 <para>This will be sent back in CommandID header of AsyncAGI exec
893 event notification.</para>
897 <para>Add an AGI command to the execute queue of the channel in Async AGI.</para>
903 #define MAX_CMD_LEN 80
904 #define AGI_NANDFS_RETRY 3
905 #define AGI_BUF_LEN 2048
906 #define SRV_PREFIX "_agi._tcp."
908 static char *app = "AGI";
910 static char *eapp = "EAGI";
912 static char *deadapp = "DeadAGI";
914 static int agidebug = 0;
916 #define TONE_BLOCK_SIZE 200
918 /* Max time to connect to an AGI remote host */
919 #define MAX_AGI_CONNECT 2000
921 #define AGI_PORT 4573
923 /*! Special return code for "asyncagi break" command. */
924 #define ASYNC_AGI_BREAK 3
927 AGI_RESULT_FAILURE = -1,
929 AGI_RESULT_SUCCESS_FAST,
930 AGI_RESULT_SUCCESS_ASYNC,
935 static agi_command *find_command(const char * const cmds[], int exact);
937 AST_THREADSTORAGE(agi_buf);
938 #define AGI_BUF_INITSIZE 256
940 int AST_OPTIONAL_API_NAME(ast_agi_send)(int fd, struct ast_channel *chan, char *fmt, ...)
946 if (!(buf = ast_str_thread_get(&agi_buf, AGI_BUF_INITSIZE)))
950 res = ast_str_set_va(&buf, 0, fmt, ap);
954 ast_log(LOG_ERROR, "Out of memory\n");
960 ast_verbose("<%s>AGI Tx >> %s", chan->name, ast_str_buffer(buf));
962 ast_verbose("AGI Tx >> %s", ast_str_buffer(buf));
966 return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
969 /* linked list of AGI commands ready to be executed by Async AGI */
973 AST_LIST_ENTRY(agi_cmd) entry;
976 static void free_agi_cmd(struct agi_cmd *cmd)
978 ast_free(cmd->cmd_buffer);
979 ast_free(cmd->cmd_id);
983 /* AGI datastore destructor */
984 static void agi_destroy_commands_cb(void *data)
987 AST_LIST_HEAD(, agi_cmd) *chan_cmds = data;
988 AST_LIST_LOCK(chan_cmds);
989 while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) {
992 AST_LIST_UNLOCK(chan_cmds);
993 AST_LIST_HEAD_DESTROY(chan_cmds);
997 /* channel datastore to keep the queue of AGI commands in the channel */
998 static const struct ast_datastore_info agi_commands_datastore_info = {
1000 .destroy = agi_destroy_commands_cb
1003 static struct agi_cmd *get_agi_cmd(struct ast_channel *chan)
1005 struct ast_datastore *store;
1006 struct agi_cmd *cmd;
1007 AST_LIST_HEAD(, agi_cmd) *agi_commands;
1009 ast_channel_lock(chan);
1010 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
1011 ast_channel_unlock(chan);
1013 ast_log(LOG_ERROR, "Huh? Async AGI datastore disappeared on Channel %s!\n",
1017 agi_commands = store->data;
1018 AST_LIST_LOCK(agi_commands);
1019 cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry);
1020 AST_LIST_UNLOCK(agi_commands);
1024 /* channel is locked when calling this one either from the CLI or manager thread */
1025 static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
1027 struct ast_datastore *store;
1028 struct agi_cmd *cmd;
1029 AST_LIST_HEAD(, agi_cmd) *agi_commands;
1031 store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
1033 ast_log(LOG_WARNING, "Channel %s is not setup for Async AGI.\n", chan->name);
1036 agi_commands = store->data;
1037 cmd = ast_calloc(1, sizeof(*cmd));
1041 cmd->cmd_buffer = ast_strdup(cmd_buff);
1042 if (!cmd->cmd_buffer) {
1046 cmd->cmd_id = ast_strdup(cmd_id);
1048 ast_free(cmd->cmd_buffer);
1052 AST_LIST_LOCK(agi_commands);
1053 AST_LIST_INSERT_TAIL(agi_commands, cmd, entry);
1054 AST_LIST_UNLOCK(agi_commands);
1058 static int add_to_agi(struct ast_channel *chan)
1060 struct ast_datastore *datastore;
1061 AST_LIST_HEAD(, agi_cmd) *agi_cmds_list;
1063 /* check if already on AGI */
1064 ast_channel_lock(chan);
1065 datastore = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
1066 ast_channel_unlock(chan);
1068 /* we already have an AGI datastore, let's just
1073 /* the channel has never been on Async AGI,
1074 let's allocate it's datastore */
1075 datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI");
1079 agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list));
1080 if (!agi_cmds_list) {
1081 ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n");
1082 ast_datastore_free(datastore);
1085 datastore->data = agi_cmds_list;
1086 AST_LIST_HEAD_INIT(agi_cmds_list);
1087 ast_channel_lock(chan);
1088 ast_channel_datastore_add(chan, datastore);
1089 ast_channel_unlock(chan);
1094 * \brief CLI command to add applications to execute in Async AGI
1099 * \retval CLI_SUCCESS on success
1100 * \retval NULL when init or tab completion is used
1102 static char *handle_cli_agi_add_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1104 struct ast_channel *chan;
1107 e->command = "agi exec";
1108 e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n"
1109 " Add AGI command to the execute queue of the specified channel in Async AGI\n";
1113 return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
1118 return CLI_SHOWUSAGE;
1121 if (!(chan = ast_channel_get_by_name(a->argv[2]))) {
1122 ast_cli(a->fd, "Channel %s does not exist.\n", a->argv[2]);
1126 ast_channel_lock(chan);
1128 if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) {
1129 ast_cli(a->fd, "Failed to add AGI command to queue of channel %s\n", chan->name);
1130 ast_channel_unlock(chan);
1131 chan = ast_channel_unref(chan);
1135 ast_debug(1, "Added AGI command to channel %s queue\n", chan->name);
1137 ast_channel_unlock(chan);
1138 chan = ast_channel_unref(chan);
1144 * \brief Add a new command to execute by the Async AGI application
1148 * It will append the application to the specified channel's queue
1149 * if the channel is not inside Async AGI application it will return an error
1150 * \retval 0 on success or incorrect use
1151 * \retval 1 on failure to add the command ( most likely because the channel
1152 * is not in Async AGI loop )
1154 static int action_add_agi_cmd(struct mansession *s, const struct message *m)
1156 const char *channel = astman_get_header(m, "Channel");
1157 const char *cmdbuff = astman_get_header(m, "Command");
1158 const char *cmdid = astman_get_header(m, "CommandID");
1159 struct ast_channel *chan;
1162 if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) {
1163 astman_send_error(s, m, "Both, Channel and Command are *required*");
1167 if (!(chan = ast_channel_get_by_name(channel))) {
1168 snprintf(buf, sizeof(buf), "Channel %s does not exist.", channel);
1169 astman_send_error(s, m, buf);
1173 ast_channel_lock(chan);
1175 if (add_agi_cmd(chan, cmdbuff, cmdid)) {
1176 snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", chan->name);
1177 astman_send_error(s, m, buf);
1178 ast_channel_unlock(chan);
1179 chan = ast_channel_unref(chan);
1183 ast_channel_unlock(chan);
1184 chan = ast_channel_unref(chan);
1186 astman_send_ack(s, m, "Added AGI command to queue");
1191 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead);
1192 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[]);
1196 * \brief Read and handle a channel frame for Async AGI.
1198 * \param chan Channel to read a frame from.
1200 * \retval AGI_RESULT_SUCCESS on success.
1201 * \retval AGI_RESULT_HANGUP on hangup.
1202 * \retval AGI_RESULT_FAILURE on error.
1204 static enum agi_result async_agi_read_frame(struct ast_channel *chan)
1206 struct ast_frame *f;
1210 ast_debug(3, "No frame read on channel %s, going out ...\n", chan->name);
1211 return AGI_RESULT_HANGUP;
1213 if (f->frametype == AST_FRAME_CONTROL) {
1215 * Is there any other frame we should care about besides
1216 * AST_CONTROL_HANGUP?
1218 switch (f->subclass.integer) {
1219 case AST_CONTROL_HANGUP:
1220 ast_debug(3, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
1222 return AGI_RESULT_HANGUP;
1229 return AGI_RESULT_SUCCESS;
1232 static enum agi_result launch_asyncagi(struct ast_channel *chan, char *argv[], int *efd)
1234 /* This buffer sizes might cause truncation if the AGI command writes more data
1235 than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command
1236 that writes a response larger than 1024 bytes?, I don't think so, most of
1237 them are just result=blah stuff. However probably if GET VARIABLE is called
1238 and the variable has large amount of data, that could be a problem. We could
1239 make this buffers dynamic, but let's leave that as a second step.
1241 AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe
1242 number. Some characters of AGI buf will be url encoded to be sent to manager
1243 clients. An URL encoded character will take 3 bytes, but again, to cause
1244 truncation more than about 70% of the AGI buffer should be URL encoded for
1245 that to happen. Not likely at all.
1247 On the other hand. I wonder if read() could eventually return less data than
1248 the amount already available in the pipe? If so, how to deal with that?
1249 So far, my tests on Linux have not had any problems.
1251 #define AGI_BUF_SIZE 1024
1252 #define AMI_BUF_SIZE 2048
1253 enum agi_result cmd_status;
1254 struct agi_cmd *cmd;
1259 char agi_buffer[AGI_BUF_SIZE + 1];
1260 char ami_buffer[AMI_BUF_SIZE];
1261 enum agi_result returnstatus = AGI_RESULT_SUCCESS;
1265 ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n");
1266 return AGI_RESULT_FAILURE;
1269 /* add AsyncAGI datastore to the channel */
1270 if (add_to_agi(chan)) {
1271 ast_log(LOG_ERROR, "Failed to start Async AGI on channel %s\n", chan->name);
1272 return AGI_RESULT_FAILURE;
1275 /* this pipe allows us to create a "fake" AGI struct to use
1279 ast_log(LOG_ERROR, "Failed to create Async AGI pipe\n");
1281 * Intentionally do not remove the datastore added with
1282 * add_to_agi() the from channel. It will be removed when the
1283 * channel is hung up anyway.
1285 return AGI_RESULT_FAILURE;
1288 /* handlers will get the pipe write fd and we read the AGI responses
1289 from the pipe read fd */
1290 async_agi.fd = fds[1];
1291 async_agi.ctrl = fds[1];
1292 async_agi.audio = -1; /* no audio support */
1294 async_agi.speech = NULL;
1296 /* notify possible manager users of a new channel ready to
1298 setup_env(chan, "async", fds[1], 0, 0, NULL);
1299 /* read the environment */
1300 res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1302 ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s\n",
1304 returnstatus = AGI_RESULT_FAILURE;
1305 goto async_agi_abort;
1307 agi_buffer[res] = '\0';
1308 /* encode it and send it thru the manager so whoever is going to take
1309 care of AGI commands on this channel can decide which AGI commands
1310 to execute based on the setup info */
1311 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
1312 manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1313 "SubEvent: Start\r\n"
1315 "Env: %s\r\n", chan->name, ami_buffer);
1316 hungup = ast_check_hangup(chan);
1319 * Process as many commands as we can. Commands are added via
1320 * the manager or the cli threads.
1322 while (!hungup && (cmd = get_agi_cmd(chan))) {
1323 /* OK, we have a command, let's call the command handler. */
1324 cmd_status = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0);
1327 * The command handler must have written to our fake AGI struct
1328 * fd (the pipe), let's read the response.
1330 res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1332 ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s\n",
1335 returnstatus = AGI_RESULT_FAILURE;
1336 goto async_agi_done;
1339 * We have a response, let's send the response thru the manager.
1340 * Include the CommandID if it was specified when the command
1343 agi_buffer[res] = '\0';
1344 ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
1345 if (ast_strlen_zero(cmd->cmd_id)) {
1346 manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1347 "SubEvent: Exec\r\n"
1349 "Result: %s\r\n", chan->name, ami_buffer);
1351 manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1352 "SubEvent: Exec\r\n"
1355 "Result: %s\r\n", chan->name, cmd->cmd_id, ami_buffer);
1360 * Check the command status to determine if we should continue
1361 * executing more commands.
1363 hungup = ast_check_hangup(chan);
1364 switch (cmd_status) {
1365 case AGI_RESULT_FAILURE:
1367 /* The failure was not because of a hangup. */
1368 returnstatus = AGI_RESULT_FAILURE;
1369 goto async_agi_done;
1372 case AGI_RESULT_SUCCESS_ASYNC:
1373 /* Only the "asyncagi break" command does this. */
1374 returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1375 goto async_agi_done;
1382 /* Wait a bit for a frame to read or to poll for a new command. */
1383 res = ast_waitfor(chan, timeout);
1385 ast_debug(1, "ast_waitfor returned <= 0 on chan %s\n", chan->name);
1386 returnstatus = AGI_RESULT_FAILURE;
1391 * Read the channel control queue until it is dry so we can
1398 cmd_status = async_agi_read_frame(chan);
1399 if (cmd_status != AGI_RESULT_SUCCESS) {
1400 returnstatus = cmd_status;
1401 goto async_agi_done;
1403 hungup = ast_check_hangup(chan);
1406 hungup = ast_check_hangup(chan);
1411 if (async_agi.speech) {
1412 ast_speech_destroy(async_agi.speech);
1414 /* notify manager users this channel cannot be
1415 controlled anymore by Async AGI */
1416 manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1418 "Channel: %s\r\n", chan->name);
1421 /* close the pipe */
1426 * Intentionally do not remove the datastore added with
1427 * add_to_agi() the from channel. There might be commands still
1428 * in the queue or in-flight to us and AsyncAGI may get called
1429 * again. The datastore destructor will be called on channel
1430 * destruction anyway.
1433 if (returnstatus == AGI_RESULT_SUCCESS) {
1434 returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1436 return returnstatus;
1442 /* launch_netscript: The fastagi handler.
1443 FastAGI defaults to port 4573 */
1444 static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
1446 int s, flags, res, port = AGI_PORT;
1447 struct pollfd pfds[1];
1448 char *host, *c, *script;
1449 struct sockaddr_in addr_in;
1451 struct ast_hostent ahp;
1453 /* agiurl is "agi://host.domain[:port][/script/name]" */
1454 host = ast_strdupa(agiurl + 6); /* Remove agi:// */
1455 /* Strip off any script name */
1456 if ((script = strchr(host, '/'))) {
1462 if ((c = strchr(host, ':'))) {
1466 if (!(hp = ast_gethostbyname(host, &ahp))) {
1467 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
1468 return AGI_RESULT_FAILURE;
1470 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1471 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
1472 return AGI_RESULT_FAILURE;
1474 if ((flags = fcntl(s, F_GETFL)) < 0) {
1475 ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
1477 return AGI_RESULT_FAILURE;
1479 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
1480 ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
1482 return AGI_RESULT_FAILURE;
1484 memset(&addr_in, 0, sizeof(addr_in));
1485 addr_in.sin_family = AF_INET;
1486 addr_in.sin_port = htons(port);
1487 memcpy(&addr_in.sin_addr, hp->h_addr, sizeof(addr_in.sin_addr));
1488 if (connect(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) && (errno != EINPROGRESS)) {
1489 ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
1491 return AGI_RESULT_FAILURE;
1495 pfds[0].events = POLLOUT;
1496 while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) {
1497 if (errno != EINTR) {
1499 ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n",
1500 agiurl, MAX_AGI_CONNECT);
1502 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
1504 return AGI_RESULT_FAILURE;
1508 if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) {
1509 if (errno != EINTR) {
1510 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
1512 return AGI_RESULT_FAILURE;
1516 /* If we have a script parameter, relay it to the fastagi server */
1517 /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */
1518 if (!ast_strlen_zero(script))
1519 ast_agi_send(s, NULL, "agi_network_script: %s\n", script);
1521 ast_debug(4, "Wow, connected!\n");
1524 return AGI_RESULT_SUCCESS_FAST;
1529 * \brief The HA fastagi handler.
1530 * \param agiurl The request URL as passed to Agi() in the dial plan
1531 * \param argv The parameters after the URL passed to Agi() in the dial plan
1532 * \param fds Input/output file descriptors
1534 * Uses SRV lookups to try to connect to a list of FastAGI servers. The hostname in
1535 * the URI is prefixed with _agi._tcp. prior to the DNS resolution. For
1536 * example, if you specify the URI \a hagi://agi.example.com/foo.agi the DNS
1537 * query would be for \a _agi._tcp.agi.example.com and you'll need to make sure
1540 * This function parses the URI, resolves the SRV service name, forms new URIs
1541 * with the results of the DNS lookup, and then calls launch_netscript on the
1542 * new URIs until one succeeds.
1544 * \return the result of the AGI operation.
1546 static enum agi_result launch_ha_netscript(char *agiurl, char *argv[], int *fds)
1548 char *host, *script;
1549 enum agi_result result;
1550 struct srv_context *context = NULL;
1553 char resolved_uri[1024];
1554 const char *srvhost;
1555 unsigned short srvport;
1557 /* format of agiurl is "hagi://host.domain[:port][/script/name]" */
1558 if (!(host = ast_strdupa(agiurl + 7))) { /* Remove hagi:// */
1559 ast_log(LOG_WARNING, "An error occurred parsing the AGI URI: %s", agiurl);
1560 return AGI_RESULT_FAILURE;
1563 /* Strip off any script name */
1564 if ((script = strchr(host, '/'))) {
1570 if (strchr(host, ':')) {
1571 ast_log(LOG_WARNING, "Specifying a port number disables SRV lookups: %s\n", agiurl);
1572 return launch_netscript(agiurl + 1, argv, fds); /* +1 to strip off leading h from hagi:// */
1575 snprintf(service, sizeof(service), "%s%s", SRV_PREFIX, host);
1577 while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) {
1578 snprintf(resolved_uri, sizeof(resolved_uri), "agi://%s:%d/%s", srvhost, srvport, script);
1579 result = launch_netscript(resolved_uri, argv, fds);
1580 if (result == AGI_RESULT_FAILURE || result == AGI_RESULT_NOTFOUND) {
1581 ast_log(LOG_WARNING, "AGI request failed for host '%s' (%s:%d)\n", host, srvhost, srvport);
1583 /* The script launched so we must cleanup the context. */
1584 ast_srv_cleanup(&context);
1589 * The DNS SRV lookup failed or we ran out of servers to check.
1590 * ast_srv_lookup() has already cleaned up the context for us.
1593 ast_log(LOG_WARNING, "SRV lookup failed for %s\n", agiurl);
1596 return AGI_RESULT_FAILURE;
1599 static enum agi_result launch_script(struct ast_channel *chan, char *script, char *argv[], int *fds, int *efd, int *opid)
1602 int pid, toast[2], fromast[2], audio[2], res;
1605 if (!strncasecmp(script, "agi://", 6)) {
1606 return (efd == NULL) ? launch_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
1608 if (!strncasecmp(script, "hagi://", 7)) {
1609 return (efd == NULL) ? launch_ha_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
1611 if (!strncasecmp(script, "agi:async", sizeof("agi:async") - 1)) {
1612 return launch_asyncagi(chan, argv, efd);
1615 if (script[0] != '/') {
1616 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script);
1620 /* Before even trying let's see if the file actually exists */
1621 if (stat(script, &st)) {
1622 ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script);
1623 return AGI_RESULT_NOTFOUND;
1627 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
1628 return AGI_RESULT_FAILURE;
1630 if (pipe(fromast)) {
1631 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
1634 return AGI_RESULT_FAILURE;
1638 ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
1643 return AGI_RESULT_FAILURE;
1645 res = fcntl(audio[1], F_GETFL);
1647 res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
1649 ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
1656 return AGI_RESULT_FAILURE;
1660 if ((pid = ast_safe_fork(1)) < 0) {
1661 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
1662 return AGI_RESULT_FAILURE;
1665 /* Pass paths to AGI via environmental variables */
1666 setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
1667 setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
1668 setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
1669 setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
1670 setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
1671 setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
1672 setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
1673 setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
1674 setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
1675 setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
1676 setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
1678 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
1679 ast_set_priority(0);
1681 /* Redirect stdin and out, provide enhanced audio channel if desired */
1682 dup2(fromast[0], STDIN_FILENO);
1683 dup2(toast[1], STDOUT_FILENO);
1685 dup2(audio[0], STDERR_FILENO + 1);
1687 close(STDERR_FILENO + 1);
1689 /* Close everything but stdin/out/error */
1690 ast_close_fds_above_n(STDERR_FILENO + 1);
1692 /* Execute script */
1693 /* XXX argv should be deprecated in favor of passing agi_argX paramaters */
1694 execv(script, argv);
1695 /* Can't use ast_log since FD's are closed */
1696 ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno));
1697 /* Special case to set status of AGI to failure */
1698 fprintf(stdout, "failure\n");
1702 ast_verb(3, "Launched AGI Script %s\n", script);
1704 fds[1] = fromast[1];
1707 /* close what we're not using in the parent */
1715 return AGI_RESULT_SUCCESS;
1718 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
1722 /* Print initial environment, with agi_request always being the first
1724 ast_agi_send(fd, chan, "agi_request: %s\n", request);
1725 ast_agi_send(fd, chan, "agi_channel: %s\n", chan->name);
1726 ast_agi_send(fd, chan, "agi_language: %s\n", chan->language);
1727 ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type);
1728 ast_agi_send(fd, chan, "agi_uniqueid: %s\n", chan->uniqueid);
1729 ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
1732 ast_agi_send(fd, chan, "agi_callerid: %s\n",
1733 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "unknown"));
1734 ast_agi_send(fd, chan, "agi_calleridname: %s\n",
1735 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "unknown"));
1736 ast_agi_send(fd, chan, "agi_callingpres: %d\n",
1737 ast_party_id_presentation(&chan->caller.id));
1738 ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->caller.ani2);
1739 ast_agi_send(fd, chan, "agi_callington: %d\n", chan->caller.id.number.plan);
1740 ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->dialed.transit_network_select);
1741 ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->dialed.number.str, "unknown"));
1742 ast_agi_send(fd, chan, "agi_rdnis: %s\n",
1743 S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "unknown"));
1745 /* Context information */
1746 ast_agi_send(fd, chan, "agi_context: %s\n", chan->context);
1747 ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten);
1748 ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority);
1749 ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
1751 /* User information */
1752 ast_agi_send(fd, chan, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
1753 ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
1755 /* Send any parameters to the fastagi server that have been passed via the agi application */
1756 /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
1757 for(count = 1; count < argc; count++)
1758 ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
1760 /* End with empty return */
1761 ast_agi_send(fd, chan, "\n");
1764 static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1768 /* Answer the channel */
1769 if (chan->_state != AST_STATE_UP)
1770 res = ast_answer(chan);
1772 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1773 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1776 static int handle_asyncagi_break(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1778 ast_agi_send(agi->fd, chan, "200 result=0\n");
1779 return ASYNC_AGI_BREAK;
1782 static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1787 return RESULT_SHOWUSAGE;
1788 if (sscanf(argv[3], "%30d", &to) != 1)
1789 return RESULT_SHOWUSAGE;
1790 res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
1791 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1792 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1795 static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1800 return RESULT_SHOWUSAGE;
1802 /* At the moment, the parser (perhaps broken) returns with
1803 the last argument PLUS the newline at the end of the input
1804 buffer. This probably needs to be fixed, but I wont do that
1805 because other stuff may break as a result. The right way
1806 would probably be to strip off the trailing newline before
1807 parsing, then here, add a newline at the end of the string
1808 before sending it to ast_sendtext --DUDE */
1809 res = ast_sendtext(chan, argv[2]);
1810 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1811 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1814 static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1819 return RESULT_SHOWUSAGE;
1821 res = ast_recvchar(chan,atoi(argv[2]));
1823 ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
1824 return RESULT_SUCCESS;
1827 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1828 return RESULT_SUCCESS;
1830 ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
1831 return RESULT_FAILURE;
1834 static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1839 return RESULT_SHOWUSAGE;
1841 buf = ast_recvtext(chan, atoi(argv[2]));
1843 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
1846 ast_agi_send(agi->fd, chan, "200 result=-1\n");
1848 return RESULT_SUCCESS;
1851 static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1856 return RESULT_SHOWUSAGE;
1858 if (!strncasecmp(argv[2],"on",2)) {
1863 if (!strncasecmp(argv[2],"mate",4)) {
1866 if (!strncasecmp(argv[2],"tdd",3)) {
1869 res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
1871 /* Set channel option failed */
1872 ast_agi_send(agi->fd, chan, "200 result=0\n");
1874 ast_agi_send(agi->fd, chan, "200 result=1\n");
1876 return RESULT_SUCCESS;
1879 static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1884 return RESULT_SHOWUSAGE;
1887 res = ast_send_image(chan, argv[2]);
1888 if (!ast_check_hangup(chan)) {
1891 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1892 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1895 static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1897 int res = 0, skipms = 3000;
1898 const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
1900 if (argc < 5 || argc > 9) {
1901 return RESULT_SHOWUSAGE;
1904 if (!ast_strlen_zero(argv[4])) {
1908 if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) {
1909 return RESULT_SHOWUSAGE;
1912 if (argc > 6 && !ast_strlen_zero(argv[6])) {
1916 if (argc > 7 && !ast_strlen_zero(argv[7])) {
1920 if (argc > 8 && !ast_strlen_zero(argv[8])) {
1924 res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL);
1926 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1928 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1931 static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1934 struct ast_filestream *fs, *vfs;
1935 long sample_offset = 0, max_length;
1936 const char *edigits = "";
1938 if (argc < 4 || argc > 5)
1939 return RESULT_SHOWUSAGE;
1944 if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1))
1945 return RESULT_SHOWUSAGE;
1947 if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
1948 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
1949 return RESULT_SUCCESS;
1952 if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
1953 ast_debug(1, "Ooh, found a video stream, too\n");
1955 ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset);
1957 ast_seekstream(fs, 0, SEEK_END);
1958 max_length = ast_tellstream(fs);
1959 ast_seekstream(fs, sample_offset, SEEK_SET);
1960 res = ast_applystream(chan, fs);
1962 ast_applystream(chan, vfs);
1965 ast_playstream(vfs);
1967 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
1968 /* this is to check for if ast_waitstream closed the stream, we probably are at
1969 * the end of the stream, return that amount, else check for the amount */
1970 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
1971 ast_stopstream(chan);
1973 /* Stop this command, don't print a result line, as there is a new command */
1974 return RESULT_SUCCESS;
1976 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
1977 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1980 /*! \brief get option - really similar to the handle_streamfile, but with a timeout */
1981 static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
1984 struct ast_filestream *fs, *vfs;
1985 long sample_offset = 0, max_length;
1987 const char *edigits = "";
1989 if ( argc < 4 || argc > 5 )
1990 return RESULT_SHOWUSAGE;
1996 timeout = atoi(argv[4]);
1997 else if (chan->pbx->dtimeoutms) {
1998 /* by default dtimeout is set to 5sec */
1999 timeout = chan->pbx->dtimeoutms; /* in msec */
2002 if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
2003 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
2004 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
2005 return RESULT_SUCCESS;
2008 if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
2009 ast_debug(1, "Ooh, found a video stream, too\n");
2011 ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
2013 ast_seekstream(fs, 0, SEEK_END);
2014 max_length = ast_tellstream(fs);
2015 ast_seekstream(fs, sample_offset, SEEK_SET);
2016 res = ast_applystream(chan, fs);
2018 ast_applystream(chan, vfs);
2021 ast_playstream(vfs);
2023 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
2024 /* this is to check for if ast_waitstream closed the stream, we probably are at
2025 * the end of the stream, return that amount, else check for the amount */
2026 sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
2027 ast_stopstream(chan);
2029 /* Stop this command, don't print a result line, as there is a new command */
2030 return RESULT_SUCCESS;
2033 /* If the user didnt press a key, wait for digitTimeout*/
2035 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
2036 /* Make sure the new result is in the escape digits of the GET OPTION */
2037 if ( !strchr(edigits,res) )
2041 ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
2042 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2048 /*! \brief Say number in various language syntaxes */
2049 /* While waiting, we're sending a NULL. */
2050 static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2054 if (argc < 4 || argc > 5)
2055 return RESULT_SHOWUSAGE;
2056 if (sscanf(argv[2], "%30d", &num) != 1)
2057 return RESULT_SHOWUSAGE;
2058 res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
2060 return RESULT_SUCCESS;
2061 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2062 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2065 static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2070 return RESULT_SHOWUSAGE;
2071 if (sscanf(argv[2], "%30d", &num) != 1)
2072 return RESULT_SHOWUSAGE;
2074 res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2075 if (res == 1) /* New command */
2076 return RESULT_SUCCESS;
2077 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2078 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2081 static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2086 return RESULT_SHOWUSAGE;
2088 res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2089 if (res == 1) /* New command */
2090 return RESULT_SUCCESS;
2091 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2092 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2095 static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2100 return RESULT_SHOWUSAGE;
2101 if (sscanf(argv[2], "%30d", &num) != 1)
2102 return RESULT_SHOWUSAGE;
2103 res = ast_say_date(chan, num, argv[3], chan->language);
2105 return RESULT_SUCCESS;
2106 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2107 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2110 static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2115 return RESULT_SHOWUSAGE;
2116 if (sscanf(argv[2], "%30d", &num) != 1)
2117 return RESULT_SHOWUSAGE;
2118 res = ast_say_time(chan, num, argv[3], chan->language);
2120 return RESULT_SUCCESS;
2121 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2122 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2125 static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2129 const char *format, *zone = NULL;
2132 return RESULT_SHOWUSAGE;
2137 /* XXX this doesn't belong here, but in the 'say' module */
2138 if (!strcasecmp(chan->language, "de")) {
2139 format = "A dBY HMS";
2141 format = "ABdY 'digits/at' IMp";
2145 if (argc > 5 && !ast_strlen_zero(argv[5]))
2148 if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
2149 return RESULT_SHOWUSAGE;
2151 res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone);
2153 return RESULT_SUCCESS;
2155 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2156 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2159 static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2164 return RESULT_SHOWUSAGE;
2166 res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2167 if (res == 1) /* New command */
2168 return RESULT_SUCCESS;
2169 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2170 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2173 static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2175 int res, max, timeout;
2179 return RESULT_SHOWUSAGE;
2181 timeout = atoi(argv[3]);
2185 max = atoi(argv[4]);
2188 res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
2189 if (res == 2) /* New command */
2190 return RESULT_SUCCESS;
2192 ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
2194 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2196 ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
2197 return RESULT_SUCCESS;
2200 static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2204 return RESULT_SHOWUSAGE;
2205 ast_copy_string(chan->context, argv[2], sizeof(chan->context));
2206 ast_agi_send(agi->fd, chan, "200 result=0\n");
2207 return RESULT_SUCCESS;
2210 static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2213 return RESULT_SHOWUSAGE;
2214 ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
2215 ast_agi_send(agi->fd, chan, "200 result=0\n");
2216 return RESULT_SUCCESS;
2219 static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2224 return RESULT_SHOWUSAGE;
2226 if (sscanf(argv[2], "%30d", &pri) != 1) {
2227 pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2],
2228 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
2230 return RESULT_SHOWUSAGE;
2233 ast_explicit_goto(chan, NULL, NULL, pri);
2234 ast_agi_send(agi->fd, chan, "200 result=0\n");
2235 return RESULT_SUCCESS;
2238 static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2240 struct ast_filestream *fs;
2241 struct ast_frame *f;
2242 struct timeval start;
2243 long sample_offset = 0;
2247 struct ast_dsp *sildet=NULL; /* silence detector dsp */
2248 int totalsilence = 0;
2250 int silence = 0; /* amount of silence to allow */
2251 int gotsilence = 0; /* did we timeout for silence? */
2252 char *silencestr = NULL;
2253 struct ast_format rfmt;
2254 ast_format_clear(&rfmt);
2256 /* XXX EAGI FIXME XXX */
2259 return RESULT_SHOWUSAGE;
2260 if (sscanf(argv[5], "%30d", &ms) != 1)
2261 return RESULT_SHOWUSAGE;
2264 silencestr = strchr(argv[6],'s');
2265 if ((argc > 7) && (!silencestr))
2266 silencestr = strchr(argv[7],'s');
2267 if ((argc > 8) && (!silencestr))
2268 silencestr = strchr(argv[8],'s');
2271 if (strlen(silencestr) > 2) {
2272 if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
2276 silence = atoi(silencestr);
2284 ast_format_copy(&rfmt, &chan->readformat);
2285 res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
2287 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
2288 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2289 return RESULT_FAILURE;
2291 sildet = ast_dsp_new();
2293 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
2294 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2295 return RESULT_FAILURE;
2297 ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
2300 /* backward compatibility, if no offset given, arg[6] would have been
2301 * caught below and taken to be a beep, else if it is a digit then it is a
2303 if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
2304 res = ast_streamfile(chan, "beep", chan->language);
2306 if ((argc > 7) && (!strchr(argv[7], '=')))
2307 res = ast_streamfile(chan, "beep", chan->language);
2310 res = ast_waitstream(chan, argv[4]);
2312 ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
2314 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE);
2317 ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res);
2319 ast_dsp_free(sildet);
2320 return RESULT_FAILURE;
2323 /* Request a video update */
2324 ast_indicate(chan, AST_CONTROL_VIDUPDATE);
2327 ast_applystream(chan,fs);
2328 /* really should have checks */
2329 ast_seekstream(fs, sample_offset, SEEK_SET);
2330 ast_truncstream(fs);
2332 start = ast_tvnow();
2333 while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
2334 res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
2336 ast_closestream(fs);
2337 ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
2339 ast_dsp_free(sildet);
2340 return RESULT_FAILURE;
2344 ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
2345 ast_closestream(fs);
2347 ast_dsp_free(sildet);
2348 return RESULT_FAILURE;
2350 switch(f->frametype) {
2351 case AST_FRAME_DTMF:
2352 if (strchr(argv[4], f->subclass.integer)) {
2353 /* This is an interrupting chracter, so rewind to chop off any small
2354 amount of DTMF that may have been recorded
2356 ast_stream_rewind(fs, 200);
2357 ast_truncstream(fs);
2358 sample_offset = ast_tellstream(fs);
2359 ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass.integer, sample_offset);
2360 ast_closestream(fs);
2363 ast_dsp_free(sildet);
2364 return RESULT_SUCCESS;
2367 case AST_FRAME_VOICE:
2368 ast_writestream(fs, f);
2369 /* this is a safe place to check progress since we know that fs
2370 * is valid after a write, and it will then have our current
2372 sample_offset = ast_tellstream(fs);
2375 ast_dsp_silence(sildet, f, &dspsilence);
2377 totalsilence = dspsilence;
2381 if (totalsilence > silence) {
2382 /* Ended happily with silence */
2388 case AST_FRAME_VIDEO:
2389 ast_writestream(fs, f);
2391 /* Ignore all other frames */
2400 ast_stream_rewind(fs, silence-1000);
2401 ast_truncstream(fs);
2402 sample_offset = ast_tellstream(fs);
2404 ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
2405 ast_closestream(fs);
2409 res = ast_set_read_format(chan, &rfmt);
2411 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
2412 ast_dsp_free(sildet);
2415 return RESULT_SUCCESS;
2418 static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2421 struct timeval whentohangup = { 0, 0 };
2424 return RESULT_SHOWUSAGE;
2425 if (sscanf(argv[2], "%30lf", &timeout) != 1)
2426 return RESULT_SHOWUSAGE;
2430 whentohangup.tv_sec = timeout;
2431 whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
2433 ast_channel_setwhentohangup_tv(chan, whentohangup);
2434 ast_agi_send(agi->fd, chan, "200 result=0\n");
2435 return RESULT_SUCCESS;
2438 static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2440 struct ast_channel *c;
2443 /* no argument: hangup the current channel */
2444 ast_set_hangupsource(chan, "dialplan/agi", 0);
2445 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
2446 ast_agi_send(agi->fd, chan, "200 result=1\n");
2447 return RESULT_SUCCESS;
2448 } else if (argc == 2) {
2449 /* one argument: look for info on the specified channel */
2450 if ((c = ast_channel_get_by_name(argv[1]))) {
2451 /* we have a matching channel */
2452 ast_set_hangupsource(c, "dialplan/agi", 0);
2453 ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
2454 c = ast_channel_unref(c);
2455 ast_agi_send(agi->fd, chan, "200 result=1\n");
2456 return RESULT_SUCCESS;
2458 /* if we get this far no channel name matched the argument given */
2459 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2460 return RESULT_SUCCESS;
2462 return RESULT_SHOWUSAGE;
2466 static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2468 int res, workaround;
2469 struct ast_app *app_to_exec;
2472 return RESULT_SHOWUSAGE;
2474 ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : "");
2476 if ((app_to_exec = pbx_findapp(argv[1]))) {
2477 if(!strcasecmp(argv[1], PARK_APP_NAME)) {
2478 ast_masq_park_call(chan, NULL, 0, NULL);
2480 if (!(workaround = ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS))) {
2481 ast_set_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS);
2483 if (ast_compat_res_agi && argc >= 3 && !ast_strlen_zero(argv[2])) {
2484 char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr;
2486 for (cptr = compat, vptr = argv[2]; *vptr; vptr++) {
2490 } else if (*vptr == '|') {
2497 res = pbx_exec(chan, app_to_exec, compat);
2499 res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]);
2502 ast_clear_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS);
2505 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
2508 ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2510 /* Even though this is wrong, users are depending upon this result. */
2514 static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2517 char *l = NULL, *n = NULL;
2520 ast_copy_string(tmp, argv[2], sizeof(tmp));
2521 ast_callerid_parse(tmp, &n, &l);
2523 ast_shrink_phone_number(l);
2528 ast_set_callerid(chan, l, n, NULL);
2531 ast_agi_send(agi->fd, chan, "200 result=1\n");
2532 return RESULT_SUCCESS;
2535 static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2537 struct ast_channel *c;
2539 /* no argument: supply info on the current channel */
2540 ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state);
2541 return RESULT_SUCCESS;
2542 } else if (argc == 3) {
2543 /* one argument: look for info on the specified channel */
2544 if ((c = ast_channel_get_by_name(argv[2]))) {
2545 ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state);
2546 c = ast_channel_unref(c);
2547 return RESULT_SUCCESS;
2549 /* if we get this far no channel name matched the argument given */
2550 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2551 return RESULT_SUCCESS;
2553 return RESULT_SHOWUSAGE;
2557 static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2560 pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
2562 ast_agi_send(agi->fd, chan, "200 result=1\n");
2563 return RESULT_SUCCESS;
2566 static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2569 char tempstr[1024] = "";
2572 return RESULT_SHOWUSAGE;
2574 /* check if we want to execute an ast_custom_function */
2575 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
2576 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
2578 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
2582 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
2584 ast_agi_send(agi->fd, chan, "200 result=0\n");
2586 return RESULT_SUCCESS;
2589 static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2591 struct ast_channel *chan2 = NULL;
2593 if (argc != 4 && argc != 5) {
2594 return RESULT_SHOWUSAGE;
2598 chan2 = ast_channel_get_by_name(argv[4]);
2600 chan2 = ast_channel_ref(chan);
2604 struct ast_str *str = ast_str_create(16);
2606 ast_agi_send(agi->fd, chan, "200 result=0\n");
2607 return RESULT_SUCCESS;
2609 ast_str_substitute_variables(&str, 0, chan2, argv[3]);
2610 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(str));
2613 ast_agi_send(agi->fd, chan, "200 result=0\n");
2617 chan2 = ast_channel_unref(chan2);
2620 return RESULT_SUCCESS;
2623 static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2628 return RESULT_SHOWUSAGE;
2631 sscanf(argv[2], "%30d", &level);
2633 ast_verb(level, "%s: %s\n", chan->data, argv[1]);
2635 ast_agi_send(agi->fd, chan, "200 result=1\n");
2637 return RESULT_SUCCESS;
2640 static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2643 struct ast_str *buf;
2646 return RESULT_SHOWUSAGE;
2648 if (!(buf = ast_str_create(16))) {
2649 ast_agi_send(agi->fd, chan, "200 result=-1\n");
2650 return RESULT_SUCCESS;
2654 res = ast_db_get(argv[2], argv[3], ast_str_buffer(buf), ast_str_size(buf));
2655 ast_str_update(buf);
2656 if (ast_str_strlen(buf) < ast_str_size(buf) - 1) {
2659 if (ast_str_make_space(&buf, ast_str_size(buf) * 2)) {
2665 ast_agi_send(agi->fd, chan, "200 result=0\n");
2667 ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(buf));
2670 return RESULT_SUCCESS;
2673 static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2678 return RESULT_SHOWUSAGE;
2679 res = ast_db_put(argv[2], argv[3], argv[4]);
2680 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
2681 return RESULT_SUCCESS;
2684 static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2689 return RESULT_SHOWUSAGE;
2690 res = ast_db_del(argv[2], argv[3]);
2691 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
2692 return RESULT_SUCCESS;
2695 static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2699 if ((argc < 3) || (argc > 4))
2700 return RESULT_SHOWUSAGE;
2702 res = ast_db_deltree(argv[2], argv[3]);
2704 res = ast_db_deltree(argv[2], NULL);
2706 ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
2707 return RESULT_SUCCESS;
2710 static char *handle_cli_agi_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2714 e->command = "agi set debug [on|off]";
2716 "Usage: agi set debug [on|off]\n"
2717 " Enables/disables dumping of AGI transactions for\n"
2718 " debugging purposes.\n";
2725 if (a->argc != e->args)
2726 return CLI_SHOWUSAGE;
2728 if (strncasecmp(a->argv[3], "off", 3) == 0) {
2730 } else if (strncasecmp(a->argv[3], "on", 2) == 0) {
2733 return CLI_SHOWUSAGE;
2735 ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis");
2739 static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char * const argv[])
2741 ast_agi_send(agi->fd, chan, "200 result=0\n");
2742 return RESULT_SUCCESS;
2745 static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2748 return RESULT_SHOWUSAGE;
2750 if (!strncasecmp(argv[2], "on", 2))
2751 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
2752 else if (!strncasecmp(argv[2], "off", 3))
2754 ast_agi_send(agi->fd, chan, "200 result=0\n");
2755 return RESULT_SUCCESS;
2758 static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2760 struct ast_format_cap *cap;
2761 struct ast_format tmpfmt;
2763 /* If a structure already exists, return an error */
2765 ast_agi_send(agi->fd, chan, "200 result=0\n");
2766 return RESULT_SUCCESS;
2769 if (!(cap = ast_format_cap_alloc_nolock())) {
2770 return RESULT_FAILURE;
2772 ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
2773 if ((agi->speech = ast_speech_new(argv[2], cap))) {
2774 ast_agi_send(agi->fd, chan, "200 result=1\n");
2776 ast_agi_send(agi->fd, chan, "200 result=0\n");
2778 cap = ast_format_cap_destroy(cap);
2780 return RESULT_SUCCESS;
2783 static int handle_speechset(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2785 /* Check for minimum arguments */
2787 return RESULT_SHOWUSAGE;
2789 /* Check to make sure speech structure exists */
2791 ast_agi_send(agi->fd, chan, "200 result=0\n");
2792 return RESULT_SUCCESS;
2795 ast_speech_change(agi->speech, argv[2], argv[3]);
2796 ast_agi_send(agi->fd, chan, "200 result=1\n");
2798 return RESULT_SUCCESS;
2801 static int handle_speechdestroy(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2804 ast_speech_destroy(agi->speech);
2806 ast_agi_send(agi->fd, chan, "200 result=1\n");
2808 ast_agi_send(agi->fd, chan, "200 result=0\n");
2811 return RESULT_SUCCESS;
2814 static int handle_speechloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2817 return RESULT_SHOWUSAGE;
2820 ast_agi_send(agi->fd, chan, "200 result=0\n");
2821 return RESULT_SUCCESS;
2824 if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
2825 ast_agi_send(agi->fd, chan, "200 result=0\n");
2827 ast_agi_send(agi->fd, chan, "200 result=1\n");
2829 return RESULT_SUCCESS;
2832 static int handle_speechunloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2835 return RESULT_SHOWUSAGE;
2838 ast_agi_send(agi->fd, chan, "200 result=0\n");
2839 return RESULT_SUCCESS;
2842 if (ast_speech_grammar_unload(agi->speech, argv[3]))
2843 ast_agi_send(agi->fd, chan, "200 result=0\n");
2845 ast_agi_send(agi->fd, chan, "200 result=1\n");
2847 return RESULT_SUCCESS;
2850 static int handle_speechactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2853 return RESULT_SHOWUSAGE;
2856 ast_agi_send(agi->fd, chan, "200 result=0\n");
2857 return RESULT_SUCCESS;
2860 if (ast_speech_grammar_activate(agi->speech, argv[3]))
2861 ast_agi_send(agi->fd, chan, "200 result=0\n");
2863 ast_agi_send(agi->fd, chan, "200 result=1\n");
2865 return RESULT_SUCCESS;
2868 static int handle_speechdeactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2871 return RESULT_SHOWUSAGE;
2874 ast_agi_send(agi->fd, chan, "200 result=0\n");
2875 return RESULT_SUCCESS;
2878 if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
2879 ast_agi_send(agi->fd, chan, "200 result=0\n");
2881 ast_agi_send(agi->fd, chan, "200 result=1\n");
2883 return RESULT_SUCCESS;
2886 static int speech_streamfile(struct ast_channel *chan, const char *filename, const char *preflang, int offset)
2888 struct ast_filestream *fs = NULL;
2890 if (!(fs = ast_openstream(chan, filename, preflang)))
2894 ast_seekstream(fs, offset, SEEK_SET);
2896 if (ast_applystream(chan, fs))
2899 if (ast_playstream(fs))
2905 static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2907 struct ast_speech *speech = agi->speech;
2909 char dtmf = 0, tmp[4096] = "", *buf = tmp;
2910 int timeout = 0, offset = 0, res = 0, i = 0;
2911 struct ast_format old_read_format;
2912 long current_offset = 0;
2913 const char *reason = NULL;
2914 struct ast_frame *fr = NULL;
2915 struct ast_speech_result *result = NULL;
2916 size_t left = sizeof(tmp);
2917 time_t start = 0, current;
2920 return RESULT_SHOWUSAGE;
2923 ast_agi_send(agi->fd, chan, "200 result=0\n");
2924 return RESULT_SUCCESS;
2928 timeout = atoi(argv[3]);
2930 /* If offset is specified then convert from text to integer */
2932 offset = atoi(argv[4]);
2934 /* We want frames coming in signed linear */
2935 ast_format_copy(&old_read_format, &chan->readformat);
2936 if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
2937 ast_agi_send(agi->fd, chan, "200 result=0\n");
2938 return RESULT_SUCCESS;
2941 /* Setup speech structure */
2942 if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
2943 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
2944 ast_speech_start(speech);
2947 /* Start playing prompt */
2948 speech_streamfile(chan, prompt, chan->language, offset);
2950 /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */
2951 while (ast_strlen_zero(reason)) {
2952 /* Run scheduled items */
2953 ast_sched_runq(chan->sched);
2955 /* See maximum time of waiting */
2956 if ((res = ast_sched_wait(chan->sched)) < 0)
2959 /* Wait for frame */
2960 if (ast_waitfor(chan, res) > 0) {
2961 if (!(fr = ast_read(chan))) {
2967 /* Perform timeout check */
2968 if ((timeout > 0) && (start > 0)) {
2970 if ((current - start) >= timeout) {
2978 /* Check the speech structure for any changes */
2979 ast_mutex_lock(&speech->lock);
2981 /* See if we need to quiet the audio stream playback */
2982 if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) {
2983 current_offset = ast_tellstream(chan->stream);
2984 ast_stopstream(chan);
2985 ast_clear_flag(speech, AST_SPEECH_QUIET);
2988 /* Check each state */
2989 switch (speech->state) {
2990 case AST_SPEECH_STATE_READY:
2991 /* If the stream is done, start timeout calculation */
2992 if ((timeout > 0) && start == 0 && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) {
2993 ast_stopstream(chan);
2996 /* Write audio frame data into speech engine if possible */
2997 if (fr && fr->frametype == AST_FRAME_VOICE)
2998 ast_speech_write(speech, fr->data.ptr, fr->datalen);
3000 case AST_SPEECH_STATE_WAIT:
3001 /* Cue waiting sound if not already playing */
3002 if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) {
3003 ast_stopstream(chan);
3004 /* If a processing sound exists, or is not none - play it */
3005 if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none"))
3006 speech_streamfile(chan, speech->processing_sound, chan->language, 0);
3009 case AST_SPEECH_STATE_DONE:
3010 /* Get the results */
3011 speech->results = ast_speech_results_get(speech);
3012 /* Change state to not ready */
3013 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
3019 ast_mutex_unlock(&speech->lock);
3021 /* Check frame for DTMF or hangup */
3023 if (fr->frametype == AST_FRAME_DTMF) {
3025 dtmf = fr->subclass.integer;
3026 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_HANGUP) {
3033 if (!strcasecmp(reason, "speech")) {
3034 /* Build string containing speech results */
3035 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) {
3036 /* Build result string */
3037 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);
3038 /* Increment result count */
3042 ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
3043 } else if (!strcasecmp(reason, "dtmf")) {
3044 ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
3045 } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
3046 ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
3048 ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset);
3051 return RESULT_SUCCESS;
3055 * \brief AGI commands list
3057 static struct agi_command commands[] = {
3058 { { "answer", NULL }, handle_answer, NULL, NULL, 0 },
3059 { { "asyncagi", "break", NULL }, handle_asyncagi_break, NULL, NULL, 1 },
3060 { { "channel", "status", NULL }, handle_channelstatus, NULL, NULL, 0 },
3061 { { "database", "del", NULL }, handle_dbdel, NULL, NULL, 1 },
3062 { { "database", "deltree", NULL }, handle_dbdeltree, NULL, NULL, 1 },
3063 { { "database", "get", NULL }, handle_dbget, NULL, NULL, 1 },
3064 { { "database", "put", NULL }, handle_dbput, NULL, NULL, 1 },
3065 { { "exec", NULL }, handle_exec, NULL, NULL, 1 },
3066 { { "get", "data", NULL }, handle_getdata, NULL, NULL, 0 },
3067 { { "get", "full", "variable", NULL }, handle_getvariablefull, NULL, NULL, 1 },
3068 { { "get", "option", NULL }, handle_getoption, NULL, NULL, 0 },
3069 { { "get", "variable", NULL }, handle_getvariable, NULL, NULL, 1 },
3070 { { "hangup", NULL }, handle_hangup, NULL, NULL, 0 },
3071 { { "noop", NULL }, handle_noop, NULL, NULL, 1 },
3072 { { "receive", "char", NULL }, handle_recvchar, NULL, NULL, 0 },
3073 { { "receive", "text", NULL }, handle_recvtext, NULL, NULL, 0 },
3074 { { "record", "file", NULL }, handle_recordfile, NULL, NULL, 0 },
3075 { { "say", "alpha", NULL }, handle_sayalpha, NULL, NULL, 0},
3076 { { "say", "digits", NULL }, handle_saydigits, NULL, NULL, 0 },
3077 { { "say", "number", NULL }, handle_saynumber, NULL, NULL, 0 },
3078 { { "say", "phonetic", NULL }, handle_sayphonetic, NULL, NULL, 0},
3079 { { "say", "date", NULL }, handle_saydate, NULL, NULL, 0},
3080 { { "say", "time", NULL }, handle_saytime, NULL, NULL, 0},
3081 { { "say", "datetime", NULL }, handle_saydatetime, NULL, NULL, 0},
3082 { { "send", "image", NULL }, handle_sendimage, NULL, NULL, 0},
3083 { { "send", "text", NULL }, handle_sendtext, NULL, NULL, 0},
3084 { { "set", "autohangup", NULL }, handle_autohangup, NULL, NULL, 0},
3085 { { "set", "callerid", NULL }, handle_setcallerid, NULL, NULL, 0},
3086 { { "set", "context", NULL }, handle_setcontext, NULL, NULL, 0},
3087 { { "set", "extension", NULL }, handle_setextension, NULL, NULL, 0},
3088 { { "set", "music", NULL }, handle_setmusic, NULL, NULL, 0 },
3089 { { "set", "priority", NULL }, handle_setpriority, NULL, NULL, 0 },
3090 { { "set", "variable", NULL }, handle_setvariable, NULL, NULL, 1 },
3091 { { "stream", "file", NULL }, handle_streamfile, NULL, NULL, 0 },
3092 { { "control", "stream", "file", NULL }, handle_controlstreamfile, NULL, NULL, 0 },
3093 { { "tdd", "mode", NULL }, handle_tddmode, NULL, NULL, 0 },
3094 { { "verbose", NULL }, handle_verbose, NULL, NULL, 1 },
3095 { { "wait", "for", "digit", NULL }, handle_waitfordigit, NULL, NULL, 0 },
3096 { { "speech", "create", NULL }, handle_speechcreate, NULL, NULL, 0 },
3097 { { "speech", "set", NULL }, handle_speechset, NULL, NULL, 0 },
3098 { { "speech", "destroy", NULL }, handle_speechdestroy, NULL, NULL, 1 },
3099 { { "speech", "load", "grammar", NULL }, handle_speechloadgrammar, NULL, NULL, 0 },
3100 { { "speech", "unload", "grammar", NULL }, handle_speechunloadgrammar, NULL, NULL, 1 },
3101 { { "speech", "activate", "grammar", NULL }, handle_speechactivategrammar, NULL, NULL, 0 },
3102 { { "speech", "deactivate", "grammar", NULL }, handle_speechdeactivategrammar, NULL, NULL, 0 },
3103 { { "speech", "recognize", NULL }, handle_speechrecognize, NULL, NULL, 0 },
3106 static AST_RWLIST_HEAD_STATIC(agi_commands, agi_command);
3108 static char *help_workhorse(int fd, const char * const match[])
3110 char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN];
3111 struct agi_command *e;
3114 ast_join(matchstr, sizeof(matchstr), match);
3116 ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description");
3117 AST_RWLIST_RDLOCK(&agi_commands);
3118 AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
3121 /* Hide commands that start with '_' */
3122 if ((e->cmda[0])[0] == '_')
3124 ast_join(fullcmd, sizeof(fullcmd), e->cmda);
3125 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
3127 ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, S_OR(e->summary, "Not available"));
3129 AST_RWLIST_UNLOCK(&agi_commands);
3134 int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command *cmd)
3136 char fullcmd[MAX_CMD_LEN];
3138 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3140 if (!find_command(cmd->cmda, 1)) {
3141 *((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC;
3142 if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
3144 *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd);
3145 *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd);
3146 *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd);
3147 *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd);
3148 *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
3150 #ifndef HAVE_NULLSAFE_PRINTF
3151 if (!cmd->summary) {
3152 *((char **) &cmd->summary) = ast_strdup("");
3155 *((char **) &cmd->usage) = ast_strdup("");
3158 *((char **) &cmd->syntax) = ast_strdup("");
3160 if (!cmd->seealso) {
3161 *((char **) &cmd->seealso) = ast_strdup("");
3167 AST_RWLIST_WRLOCK(&agi_commands);
3168 AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
3169 AST_RWLIST_UNLOCK(&agi_commands);
3170 if (mod != ast_module_info->self)
3171 ast_module_ref(ast_module_info->self);
3172 ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
3175 ast_log(LOG_WARNING, "Command already registered!\n");
3180 int AST_OPTIONAL_API_NAME(ast_agi_unregister)(struct ast_module *mod, agi_command *cmd)
3182 struct agi_command *e;
3183 int unregistered = 0;
3184 char fullcmd[MAX_CMD_LEN];
3186 ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3188 AST_RWLIST_WRLOCK(&agi_commands);
3189 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) {
3191 AST_RWLIST_REMOVE_CURRENT(list);
3192 if (mod != ast_module_info->self)
3193 ast_module_unref(ast_module_info->self);
3195 if (e->docsrc == AST_XML_DOC) {
3196 ast_free((char *) e->summary);
3197 ast_free((char *) e->usage);
3198 ast_free((char *) e->syntax);
3199 ast_free((char *) e->seealso);
3200 *((char **) &e->summary) = NULL;
3201 *((char **) &e->usage) = NULL;
3202 *((char **) &e->syntax) = NULL;
3203 *((char **) &e->seealso) = NULL;
3210 AST_RWLIST_TRAVERSE_SAFE_END;
3211 AST_RWLIST_UNLOCK(&agi_commands);
3213 ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd);
3215 ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd);
3216 return unregistered;
3219 int AST_OPTIONAL_API_NAME(ast_agi_register_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
3221 unsigned int i, x = 0;
3223 for (i = 0; i < len; i++) {
3224 if (ast_agi_register(mod, cmd + i) == 1) {
3229 /* registration failed, unregister everything
3230 that had been registered up to that point
3232 for (; x > 0; x--) {
3233 /* we are intentionally ignoring the
3234 result of ast_agi_unregister() here,
3235 but it should be safe to do so since
3236 we just registered these commands and
3237 the only possible way for unregistration
3238 to fail is if the command is not
3241 (void) ast_agi_unregister(mod, cmd + x - 1);
3249 int AST_OPTIONAL_API_NAME(ast_agi_unregister_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
3254 for (i = 0; i < len; i++) {
3255 /* remember whether any of the unregistration
3256 attempts failed... there is no recourse if
3259 res |= ast_agi_unregister(mod, cmd + i);
3265 static agi_command *find_command(const char * const cmds[], int exact)
3268 struct agi_command *e;
3270 AST_RWLIST_RDLOCK(&agi_commands);
3271 AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
3274 /* start optimistic */
3276 for (y = 0; match && cmds[y]; y++) {
3277 /* If there are no more words in the command (and we're looking for
3278 an exact match) or there is a difference between the two words,
3279 then this is not a match */
3280 if (!e->cmda[y] && !exact)
3282 /* don't segfault if the next part of a command doesn't exist */
3284 AST_RWLIST_UNLOCK(&agi_commands);
3287 if (strcasecmp(e->cmda[y], cmds[y]))
3290 /* If more words are needed to complete the command then this is not
3291 a candidate (unless we're looking for a really inexact answer */
3292 if ((exact > -1) && e->cmda[y])
3295 AST_RWLIST_UNLOCK(&agi_commands);
3299 AST_RWLIST_UNLOCK(&agi_commands);
3303 static int parse_args(char *s, int *max, const char *argv[])
3305 int x = 0, quoted = 0, escaped = 0, whitespace = 1;
3312 /* If it's escaped, put a literal quote */
3317 if (quoted && whitespace) {
3318 /* If we're starting a quote, coming off white space start a new word, too */
3326 if (!quoted && !escaped) {
3327 /* If we're not quoted, mark this as whitespace, and
3328 end the previous argument */
3332 /* Otherwise, just treat it as anything else */
3336 /* If we're escaped, print a literal, otherwise enable escaping */
3346 if (x >= MAX_ARGS -1) {
3347 ast_log(LOG_WARNING, "Too many arguments, truncating\n");
3350 /* Coming off of whitespace, start the next argument */
3359 /* Null terminate */
3366 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
3368 const char *argv[MAX_ARGS];
3369 int argc = MAX_ARGS;
3372 const char *ami_res;
3373 char *ami_cmd = ast_strdupa(buf);
3374 int command_id = ast_random();
3377 manager_event(EVENT_FLAG_AGI, "AGIExec",
3378 "SubEvent: Start\r\n"
3381 "Command: %s\r\n", chan->name, command_id, ami_cmd);
3382 parse_args(buf, &argc, argv);
3383 c = find_command(argv, 0);
3384 if (c && (!dead || (dead && c->dead))) {
3385 /* if this command wasn't registered by res_agi, be sure to usecount
3386 the module we are using */
3387 if (c->mod != ast_module_info->self)
3388 ast_module_ref(c->mod);
3389 /* If the AGI command being executed is an actual application (using agi exec)
3390 the app field will be updated in pbx_exec via handle_exec */
3391 if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC"))
3392 ast_cdr_setapp(chan->cdr, "AGI", buf);
3394 res = c->handler(chan, agi, argc, argv);
3395 if (c->mod != ast_module_info->self)
3396 ast_module_unref(c->mod);
3398 case RESULT_SHOWUSAGE:
3402 case RESULT_FAILURE:
3403 ami_res = "Failure";
3406 case ASYNC_AGI_BREAK:
3407 case RESULT_SUCCESS:
3408 ami_res = "Success";
3412 ami_res = "Unknown Result";
3416 manager_event(EVENT_FLAG_AGI, "AGIExec",
3421 "ResultCode: %d\r\n"
3422 "Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res);
3424 case RESULT_SHOWUSAGE:
3425 if (ast_strlen_zero(c->usage)) {
3426 ast_agi_send(agi->fd, chan, "520 Invalid command syntax. Proper usage not available.\n");
3428 ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n");
3429 ast_agi_send(agi->fd, chan, "%s", c->usage);
3430 ast_agi_send(agi->fd, chan, "520 End of proper usage.\n");
3433 case ASYNC_AGI_BREAK:
3434 return AGI_RESULT_SUCCESS_ASYNC;
3435 case RESULT_FAILURE:
3436 /* The RESULT_FAILURE code is usually because the channel hungup. */
3437 return AGI_RESULT_FAILURE;
3442 ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n");
3443 manager_event(EVENT_FLAG_AGI, "AGIExec",
3448 "ResultCode: 511\r\n"
3449 "Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd);
3451 ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n");
3452 manager_event(EVENT_FLAG_AGI, "AGIExec",
3457 "ResultCode: 510\r\n"
3458 "Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd);
3460 return AGI_RESULT_SUCCESS;
3462 static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
3464 struct ast_channel *c;
3468 enum agi_result returnstatus = AGI_RESULT_SUCCESS;
3469 struct ast_frame *f;
3470 char buf[AGI_BUF_LEN];
3473 /* how many times we'll retry if ast_waitfor_nandfs will return without either
3474 channel or file descriptor in case select is interrupted by a system call (EINTR) */
3475 int retry = AGI_NANDFS_RETRY;
3477 const char *sighup_str;
3479 ast_channel_lock(chan);
3480 sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
3481 send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str);
3482 ast_channel_unlock(chan);
3484 if (!(readf = fdopen(agi->ctrl, "r"))) {
3485 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
3486 if (send_sighup && pid > -1)
3489 return AGI_RESULT_FAILURE;
3493 setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv);
3501 } else if (agi->fast) {
3502 send(agi->ctrl, "HANGUP\n", 7, 0);