Asterisk - The Open Source Telephony Project  GIT-master-a24979a
res_agi.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
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.
13  *
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.
17  */
18 
19 /*! \file
20  *
21  * \brief AGI - the Asterisk Gateway Interface
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  */
26 
27 /*** MODULEINFO
28  <depend>res_speech</depend>
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include <math.h>
35 #include <signal.h>
36 #include <sys/time.h>
37 #include <sys/wait.h>
38 #include <sys/stat.h>
39 #include <pthread.h>
40 
41 #include "asterisk/paths.h" /* use many ast_config_AST_*_DIR */
42 #include "asterisk/network.h"
43 #include "asterisk/file.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/module.h"
47 #include "asterisk/astdb.h"
48 #include "asterisk/callerid.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/image.h"
51 #include "asterisk/say.h"
52 #include "asterisk/app.h"
53 #include "asterisk/dsp.h"
54 #include "asterisk/musiconhold.h"
55 #include "asterisk/utils.h"
56 #include "asterisk/lock.h"
57 #include "asterisk/strings.h"
58 #include "asterisk/manager.h"
59 #include "asterisk/ast_version.h"
60 #include "asterisk/speech.h"
61 #include "asterisk/manager.h"
62 #include "asterisk/term.h"
63 #include "asterisk/xmldoc.h"
64 #include "asterisk/srv.h"
65 #include "asterisk/test.h"
66 #include "asterisk/netsock2.h"
69 #include "asterisk/format_cache.h"
70 
71 #define AST_API_MODULE
72 #include "asterisk/agi.h"
73 
74 /*** DOCUMENTATION
75  <agi name="answer" language="en_US">
76  <synopsis>
77  Answer channel
78  </synopsis>
79  <syntax />
80  <description>
81  <para>Answers channel if not already in answer state. Returns <literal>-1</literal> on
82  channel failure, or <literal>0</literal> if successful.</para>
83  </description>
84  <see-also>
85  <ref type="agi">hangup</ref>
86  <ref type="application">AGI</ref>
87  </see-also>
88  </agi>
89  <agi name="asyncagi break" language="en_US">
90  <synopsis>
91  Interrupts Async AGI
92  </synopsis>
93  <syntax />
94  <description>
95  <para>Interrupts expected flow of Async AGI commands and returns control to previous source
96  (typically, the PBX dialplan).</para>
97  </description>
98  <see-also>
99  <ref type="agi">hangup</ref>
100  <ref type="application">AGI</ref>
101  </see-also>
102  </agi>
103  <agi name="channel status" language="en_US">
104  <synopsis>
105  Returns status of the connected channel.
106  </synopsis>
107  <syntax>
108  <parameter name="channelname" />
109  </syntax>
110  <description>
111  <para>Returns the status of the specified <replaceable>channelname</replaceable>.
112  If no channel name is given then returns the status of the current channel.</para>
113  <para>Return values:</para>
114  <enumlist>
115  <enum name="0">
116  <para>Channel is down and available.</para>
117  </enum>
118  <enum name="1">
119  <para>Channel is down, but reserved.</para>
120  </enum>
121  <enum name="2">
122  <para>Channel is off hook.</para>
123  </enum>
124  <enum name="3">
125  <para>Digits (or equivalent) have been dialed.</para>
126  </enum>
127  <enum name="4">
128  <para>Line is ringing.</para>
129  </enum>
130  <enum name="5">
131  <para>Remote end is ringing.</para>
132  </enum>
133  <enum name="6">
134  <para>Line is up.</para>
135  </enum>
136  <enum name="7">
137  <para>Line is busy.</para>
138  </enum>
139  </enumlist>
140  </description>
141  <see-also>
142  <ref type="application">AGI</ref>
143  </see-also>
144  </agi>
145  <agi name="control stream file" language="en_US">
146  <synopsis>
147  Sends audio file on channel and allows the listener to control the stream.
148  </synopsis>
149  <syntax>
150  <parameter name="filename" required="true">
151  <para>The file extension must not be included in the filename.</para>
152  </parameter>
153  <parameter name="escape_digits" required="true" />
154  <parameter name="skipms" />
155  <parameter name="ffchar">
156  <para>Defaults to <literal>#</literal></para>
157  </parameter>
158  <parameter name="rewchr">
159  <para>Defaults to <literal>*</literal></para>
160  </parameter>
161  <parameter name="pausechr" />
162  <parameter name="offsetms">
163  <para>Offset, in milliseconds, to start the audio playback</para>
164  </parameter>
165  </syntax>
166  <description>
167  <para>Send the given file, allowing playback to be controlled by the given
168  digits, if any. Use double quotes for the digits if you wish none to be
169  permitted. If offsetms is provided then the audio will seek to offsetms
170  before play starts. Returns <literal>0</literal> if playback completes without a digit
171  being pressed, or the ASCII numerical value of the digit if one was pressed,
172  or <literal>-1</literal> on error or if the channel was disconnected. Returns the
173  position where playback was terminated as endpos.</para>
174 
175  <para>It sets the following channel variables upon completion:</para>
176  <variablelist>
177  <variable name="CPLAYBACKSTATUS">
178  <para>Contains the status of the attempt as a text string</para>
179  <value name="SUCCESS" />
180  <value name="USERSTOPPED" />
181  <value name="REMOTESTOPPED" />
182  <value name="ERROR" />
183  </variable>
184  <variable name="CPLAYBACKOFFSET">
185  <para>Contains the offset in ms into the file where playback
186  was at when it stopped. <literal>-1</literal> is end of file.</para>
187  </variable>
188  <variable name="CPLAYBACKSTOPKEY">
189  <para>If the playback is stopped by the user this variable contains
190  the key that was pressed.</para>
191  </variable>
192  </variablelist>
193  </description>
194  <see-also>
195  <ref type="agi">get option</ref>
196  <ref type="agi">control stream file</ref>
197  <ref type="application">AGI</ref>
198  </see-also>
199  </agi>
200  <agi name="database del" language="en_US">
201  <synopsis>
202  Removes database key/value
203  </synopsis>
204  <syntax>
205  <parameter name="family" required="true" />
206  <parameter name="key" required="true" />
207  </syntax>
208  <description>
209  <para>Deletes an entry in the Asterisk database for a given
210  <replaceable>family</replaceable> and <replaceable>key</replaceable>.</para>
211  <para>Returns <literal>1</literal> if successful, <literal>0</literal>
212  otherwise.</para>
213  </description>
214  <see-also>
215  <ref type="agi">database get</ref>
216  <ref type="agi">database put</ref>
217  <ref type="agi">database deltree</ref>
218  <ref type="application">AGI</ref>
219  </see-also>
220  </agi>
221  <agi name="database deltree" language="en_US">
222  <synopsis>
223  Removes database keytree/value
224  </synopsis>
225  <syntax>
226  <parameter name="family" required="true" />
227  <parameter name="keytree" />
228  </syntax>
229  <description>
230  <para>Deletes a <replaceable>family</replaceable> or specific <replaceable>keytree</replaceable>
231  within a <replaceable>family</replaceable> in the Asterisk database.</para>
232  <para>Returns <literal>1</literal> if successful, <literal>0</literal> otherwise.</para>
233  </description>
234  <see-also>
235  <ref type="agi">database get</ref>
236  <ref type="agi">database put</ref>
237  <ref type="agi">database del</ref>
238  <ref type="application">AGI</ref>
239  </see-also>
240  </agi>
241  <agi name="database get" language="en_US">
242  <synopsis>
243  Gets database value
244  </synopsis>
245  <syntax>
246  <parameter name="family" required="true" />
247  <parameter name="key" required="true" />
248  </syntax>
249  <description>
250  <para>Retrieves an entry in the Asterisk database for a given <replaceable>family</replaceable>
251  and <replaceable>key</replaceable>.</para>
252  <para>Returns <literal>0</literal> if <replaceable>key</replaceable> is not set.
253  Returns <literal>1</literal> if <replaceable>key</replaceable> is set and returns the variable
254  in parenthesis.</para>
255  <para>Example return code: 200 result=1 (testvariable)</para>
256  </description>
257  <see-also>
258  <ref type="agi">database put</ref>
259  <ref type="agi">database del</ref>
260  <ref type="agi">database deltree</ref>
261  <ref type="application">AGI</ref>
262  </see-also>
263  </agi>
264  <agi name="database put" language="en_US">
265  <synopsis>
266  Adds/updates database value
267  </synopsis>
268  <syntax>
269  <parameter name="family" required="true" />
270  <parameter name="key" required="true" />
271  <parameter name="value" required="true" />
272  </syntax>
273  <description>
274  <para>Adds or updates an entry in the Asterisk database for a given
275  <replaceable>family</replaceable>, <replaceable>key</replaceable>, and
276  <replaceable>value</replaceable>.</para>
277  <para>Returns <literal>1</literal> if successful, <literal>0</literal> otherwise.</para>
278  </description>
279  <see-also>
280  <ref type="agi">database get</ref>
281  <ref type="agi">database del</ref>
282  <ref type="agi">database deltree</ref>
283  <ref type="application">AGI</ref>
284  </see-also>
285  </agi>
286  <agi name="exec" language="en_US">
287  <synopsis>
288  Executes a given Application
289  </synopsis>
290  <syntax>
291  <parameter name="application" required="true" />
292  <parameter name="options" required="true" />
293  </syntax>
294  <description>
295  <para>Executes <replaceable>application</replaceable> with given
296  <replaceable>options</replaceable>.</para>
297  <para>Returns whatever the <replaceable>application</replaceable> returns, or
298  <literal>-2</literal> on failure to find <replaceable>application</replaceable>.</para>
299  </description>
300  <see-also>
301  <ref type="application">AGI</ref>
302  </see-also>
303  </agi>
304  <agi name="get data" language="en_US">
305  <synopsis>
306  Prompts for DTMF on a channel
307  </synopsis>
308  <syntax>
309  <parameter name="file" required="true" />
310  <parameter name="timeout" />
311  <parameter name="maxdigits" />
312  </syntax>
313  <description>
314  <para>Stream the given <replaceable>file</replaceable>, and receive DTMF data.</para>
315  <para>Returns the digits received from the channel at the other end.</para>
316  </description>
317  <see-also>
318  <ref type="application">AGI</ref>
319  </see-also>
320  </agi>
321  <agi name="get full variable" language="en_US">
322  <synopsis>
323  Evaluates a channel expression
324  </synopsis>
325  <syntax>
326  <parameter name="expression" required="true" />
327  <parameter name="channelname" />
328  </syntax>
329  <description>
330  <para>Evaluates the given <replaceable>expression</replaceable> against the
331  channel specified by <replaceable>channelname</replaceable>, or the current
332  channel if <replaceable>channelname</replaceable> is not provided.</para>
333  <para>Unlike GET VARIABLE, the <replaceable>expression</replaceable> is
334  processed in a manner similar to dialplan evaluation, allowing complex
335  and built-in variables to be accessed, e.g. <literal>The time is
336  ${EPOCH}</literal></para>
337  <para>Returns <literal>0</literal> if no channel matching
338  <replaceable>channelname</replaceable> exists, <literal>1</literal>
339  otherwise.</para>
340  <para>Example return code: 200 result=1 (The time is 1578493800)</para>
341  </description>
342  <see-also>
343  <ref type="agi">get variable</ref>
344  <ref type="agi">set variable</ref>
345  <ref type="application">AGI</ref>
346  </see-also>
347  </agi>
348  <agi name="get option" language="en_US">
349  <synopsis>
350  Stream file, prompt for DTMF, with timeout.
351  </synopsis>
352  <syntax>
353  <parameter name="filename" required="true" />
354  <parameter name="escape_digits" required="true" />
355  <parameter name="timeout" />
356  </syntax>
357  <description>
358  <para>Behaves similar to STREAM FILE but used with a timeout option.</para>
359  </description>
360  <see-also>
361  <ref type="agi">stream file</ref>
362  <ref type="agi">control stream file</ref>
363  <ref type="application">AGI</ref>
364  </see-also>
365  </agi>
366  <agi name="get variable" language="en_US">
367  <synopsis>
368  Gets a channel variable.
369  </synopsis>
370  <syntax>
371  <parameter name="variablename" required="true" />
372  </syntax>
373  <description>
374  <para>Returns <literal>0</literal> if <replaceable>variablename</replaceable> is not set.
375  Returns <literal>1</literal> if <replaceable>variablename</replaceable> is set and returns
376  the variable in parentheses.</para>
377  <para>Example return code: 200 result=1 (testvariable)</para>
378  </description>
379  <see-also>
380  <ref type="agi">get full variable</ref>
381  <ref type="agi">set variable</ref>
382  <ref type="application">AGI</ref>
383  </see-also>
384  </agi>
385  <agi name="hangup" language="en_US">
386  <synopsis>
387  Hangup a channel.
388  </synopsis>
389  <syntax>
390  <parameter name="channelname" />
391  </syntax>
392  <description>
393  <para>Hangs up the specified channel. If no channel name is given, hangs
394  up the current channel</para>
395  </description>
396  <see-also>
397  <ref type="application">AGI</ref>
398  </see-also>
399  </agi>
400  <agi name="noop" language="en_US">
401  <synopsis>
402  Does nothing.
403  </synopsis>
404  <syntax />
405  <description>
406  <para>Does nothing.</para>
407  </description>
408  <see-also>
409  <ref type="application">AGI</ref>
410  </see-also>
411  </agi>
412  <agi name="receive char" language="en_US">
413  <synopsis>
414  Receives one character from channels supporting it.
415  </synopsis>
416  <syntax>
417  <parameter name="timeout" required="true">
418  <para>The maximum time to wait for input in milliseconds, or <literal>0</literal>
419  for infinite. Most channels</para>
420  </parameter>
421  </syntax>
422  <description>
423  <para>Receives a character of text on a channel. Most channels do not support
424  the reception of text. Returns the decimal value of the character
425  if one is received, or <literal>0</literal> if the channel does not support
426  text reception. Returns <literal>-1</literal> only on error/hangup.</para>
427  </description>
428  <see-also>
429  <ref type="agi">receive text</ref>
430  <ref type="application">AGI</ref>
431  </see-also>
432  </agi>
433  <agi name="receive text" language="en_US">
434  <synopsis>
435  Receives text from channels supporting it.
436  </synopsis>
437  <syntax>
438  <parameter name="timeout" required="true">
439  <para>The timeout to be the maximum time to wait for input in
440  milliseconds, or <literal>0</literal> for infinite.</para>
441  </parameter>
442  </syntax>
443  <description>
444  <para>Receives a string of text on a channel. Most channels
445  do not support the reception of text. Returns <literal>-1</literal> for failure
446  or <literal>1</literal> for success, and the string in parenthesis.</para>
447  </description>
448  <see-also>
449  <ref type="agi">receive char</ref>
450  <ref type="agi">send text</ref>
451  <ref type="application">AGI</ref>
452  </see-also>
453  </agi>
454  <agi name="record file" language="en_US">
455  <synopsis>
456  Records to a given file.
457  </synopsis>
458  <syntax>
459  <parameter name="filename" required="true">
460  <para>The destination filename of the recorded audio.</para>
461  </parameter>
462  <parameter name="format" required="true">
463  <para>The audio format in which to save the resulting file.</para>
464  </parameter>
465  <parameter name="escape_digits" required="true">
466  <para>The DTMF digits that will terminate the recording process.</para>
467  </parameter>
468  <parameter name="timeout" required="true">
469  <para>The maximum recording time in milliseconds. Set to -1 for no
470  limit.</para>
471  </parameter>
472  <parameter name="offset_samples">
473  <para>Causes the recording to first seek to the specified offset before
474  recording begins.</para>
475  </parameter>
476  <parameter name="beep">
477  <para>Causes Asterisk to play a beep as recording begins. This argument
478  can take any value.</para>
479  </parameter>
480  <parameter name="s=silence">
481  <para>The number of seconds of silence that are permitted before the
482  recording is terminated, regardless of the
483  <replaceable>escape_digits</replaceable> or <replaceable>timeout</replaceable>
484  arguments. If specified, this parameter must be preceded by
485  <literal>s=</literal>.</para>
486  </parameter>
487  </syntax>
488  <description>
489  <para>Record to a file until a given dtmf digit in the sequence is received.
490  Returns <literal>-1</literal> on hangup or error. The format will specify what kind of file
491  will be recorded. The <replaceable>timeout</replaceable> is the maximum record time in
492  milliseconds, or <literal>-1</literal> for no <replaceable>timeout</replaceable>.
493  <replaceable>offset samples</replaceable> is optional, and, if provided, will seek
494  to the offset without exceeding the end of the
495  file. <replaceable>beep</replaceable> can take any value, and causes Asterisk
496  to play a beep to the channel that is about to be recorded. <replaceable>silence</replaceable> is
497  the number of seconds of silence allowed before the function returns despite the
498  lack of dtmf digits or reaching <replaceable>timeout</replaceable>. <replaceable>silence</replaceable>
499  value must be preceded by <literal>s=</literal> and is also optional.</para>
500  </description>
501  <see-also>
502  <ref type="application">AGI</ref>
503  </see-also>
504  </agi>
505  <agi name="say alpha" language="en_US">
506  <synopsis>
507  Says a given character string.
508  </synopsis>
509  <syntax>
510  <parameter name="number" required="true" />
511  <parameter name="escape_digits" required="true" />
512  </syntax>
513  <description>
514  <para>Say a given character string, returning early if any of the given DTMF digits
515  are received on the channel. Returns <literal>0</literal> if playback completes
516  without a digit being pressed, or the ASCII numerical value of the digit if one
517  was pressed or <literal>-1</literal> on error/hangup.</para>
518  </description>
519  <see-also>
520  <ref type="agi">say digits</ref>
521  <ref type="agi">say number</ref>
522  <ref type="agi">say phonetic</ref>
523  <ref type="agi">say date</ref>
524  <ref type="agi">say time</ref>
525  <ref type="agi">say datetime</ref>
526  <ref type="application">AGI</ref>
527  </see-also>
528  </agi>
529  <agi name="say digits" language="en_US">
530  <synopsis>
531  Says a given digit string.
532  </synopsis>
533  <syntax>
534  <parameter name="number" required="true" />
535  <parameter name="escape_digits" required="true" />
536  </syntax>
537  <description>
538  <para>Say a given digit string, returning early if any of the given DTMF digits
539  are received on the channel. Returns <literal>0</literal> if playback completes
540  without a digit being pressed, or the ASCII numerical value of the digit if one
541  was pressed or <literal>-1</literal> on error/hangup.</para>
542  </description>
543  <see-also>
544  <ref type="agi">say alpha</ref>
545  <ref type="agi">say number</ref>
546  <ref type="agi">say phonetic</ref>
547  <ref type="agi">say date</ref>
548  <ref type="agi">say time</ref>
549  <ref type="agi">say datetime</ref>
550  <ref type="application">AGI</ref>
551  </see-also>
552  </agi>
553  <agi name="say number" language="en_US">
554  <synopsis>
555  Says a given number.
556  </synopsis>
557  <syntax>
558  <parameter name="number" required="true" />
559  <parameter name="escape_digits" required="true" />
560  <parameter name="gender" />
561  </syntax>
562  <description>
563  <para>Say a given number, returning early if any of the given DTMF digits
564  are received on the channel. Returns <literal>0</literal> if playback
565  completes without a digit being pressed, or the ASCII numerical value of
566  the digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
567  </description>
568  <see-also>
569  <ref type="agi">say alpha</ref>
570  <ref type="agi">say digits</ref>
571  <ref type="agi">say phonetic</ref>
572  <ref type="agi">say date</ref>
573  <ref type="agi">say time</ref>
574  <ref type="agi">say datetime</ref>
575  <ref type="application">AGI</ref>
576  </see-also>
577  </agi>
578  <agi name="say phonetic" language="en_US">
579  <synopsis>
580  Says a given character string with phonetics.
581  </synopsis>
582  <syntax>
583  <parameter name="string" required="true" />
584  <parameter name="escape_digits" required="true" />
585  </syntax>
586  <description>
587  <para>Say a given character string with phonetics, returning early if any of the
588  given DTMF digits are received on the channel. Returns <literal>0</literal> if
589  playback completes without a digit pressed, the ASCII numerical value of the digit
590  if one was pressed, or <literal>-1</literal> on error/hangup.</para>
591  </description>
592  <see-also>
593  <ref type="agi">say alpha</ref>
594  <ref type="agi">say digits</ref>
595  <ref type="agi">say number</ref>
596  <ref type="agi">say date</ref>
597  <ref type="agi">say time</ref>
598  <ref type="agi">say datetime</ref>
599  <ref type="application">AGI</ref>
600  </see-also>
601  </agi>
602  <agi name="say date" language="en_US">
603  <synopsis>
604  Says a given date.
605  </synopsis>
606  <syntax>
607  <parameter name="date" required="true">
608  <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
609  Coordinated Universal Time (UTC).</para>
610  </parameter>
611  <parameter name="escape_digits" required="true" />
612  </syntax>
613  <description>
614  <para>Say a given date, returning early if any of the given DTMF digits are
615  received on the channel. Returns <literal>0</literal> if playback
616  completes without a digit being pressed, or the ASCII numerical value of the
617  digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
618  </description>
619  <see-also>
620  <ref type="agi">say alpha</ref>
621  <ref type="agi">say digits</ref>
622  <ref type="agi">say number</ref>
623  <ref type="agi">say phonetic</ref>
624  <ref type="agi">say time</ref>
625  <ref type="agi">say datetime</ref>
626  <ref type="application">AGI</ref>
627  </see-also>
628  </agi>
629  <agi name="say time" language="en_US">
630  <synopsis>
631  Says a given time.
632  </synopsis>
633  <syntax>
634  <parameter name="time" required="true">
635  <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
636  Coordinated Universal Time (UTC).</para>
637  </parameter>
638  <parameter name="escape_digits" required="true" />
639  </syntax>
640  <description>
641  <para>Say a given time, returning early if any of the given DTMF digits are
642  received on the channel. Returns <literal>0</literal> if playback completes
643  without a digit being pressed, or the ASCII numerical value of the digit if
644  one was pressed or <literal>-1</literal> on error/hangup.</para>
645  </description>
646  <see-also>
647  <ref type="agi">say alpha</ref>
648  <ref type="agi">say digits</ref>
649  <ref type="agi">say number</ref>
650  <ref type="agi">say phonetic</ref>
651  <ref type="agi">say date</ref>
652  <ref type="agi">say datetime</ref>
653  <ref type="application">AGI</ref>
654  </see-also>
655  </agi>
656  <agi name="say datetime" language="en_US">
657  <synopsis>
658  Says a given time as specified by the format given.
659  </synopsis>
660  <syntax>
661  <parameter name="time" required="true">
662  <para>Is number of seconds elapsed since 00:00:00
663  on January 1, 1970, Coordinated Universal Time (UTC)</para>
664  </parameter>
665  <parameter name="escape_digits" required="true" />
666  <parameter name="format">
667  <para>Is the format the time should be said in. See
668  <filename>voicemail.conf</filename> (defaults to <literal>ABdY
669  'digits/at' IMp</literal>).</para>
670  </parameter>
671  <parameter name="timezone">
672  <para>Acceptable values can be found in <filename>/usr/share/zoneinfo</filename>
673  Defaults to machine default.</para>
674  </parameter>
675  </syntax>
676  <description>
677  <para>Say a given time, returning early if any of the given DTMF digits are
678  received on the channel. Returns <literal>0</literal> if playback
679  completes without a digit being pressed, or the ASCII numerical value of the
680  digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
681  </description>
682  <see-also>
683  <ref type="agi">say alpha</ref>
684  <ref type="agi">say digits</ref>
685  <ref type="agi">say number</ref>
686  <ref type="agi">say phonetic</ref>
687  <ref type="agi">say date</ref>
688  <ref type="agi">say time</ref>
689  <ref type="application">AGI</ref>
690  </see-also>
691  </agi>
692  <agi name="send image" language="en_US">
693  <synopsis>
694  Sends images to channels supporting it.
695  </synopsis>
696  <syntax>
697  <parameter name="image" required="true" />
698  </syntax>
699  <description>
700  <para>Sends the given image on a channel. Most channels do not support the
701  transmission of images. Returns <literal>0</literal> if image is sent, or if
702  the channel does not support image transmission. Returns <literal>-1</literal>
703  only on error/hangup. Image names should not include extensions.</para>
704  </description>
705  <see-also>
706  <ref type="application">AGI</ref>
707  </see-also>
708  </agi>
709  <agi name="send text" language="en_US">
710  <synopsis>
711  Sends text to channels supporting it.
712  </synopsis>
713  <syntax>
714  <parameter name="text to send" required="true">
715  <para>Text consisting of greater than one word should be placed
716  in quotes since the command only accepts a single argument.</para>
717  </parameter>
718  </syntax>
719  <description>
720  <para>Sends the given text on a channel. Most channels do not support the
721  transmission of text. Returns <literal>0</literal> if text is sent, or if the
722  channel does not support text transmission. Returns <literal>-1</literal> only
723  on error/hangup.</para>
724  </description>
725  <see-also>
726  <ref type="agi">receive text</ref>
727  <ref type="application">AGI</ref>
728  </see-also>
729  </agi>
730  <agi name="set autohangup" language="en_US">
731  <synopsis>
732  Autohangup channel in some time.
733  </synopsis>
734  <syntax>
735  <parameter name="time" required="true" />
736  </syntax>
737  <description>
738  <para>Cause the channel to automatically hangup at <replaceable>time</replaceable>
739  seconds in the future. Of course it can be hungup before then as well. Setting to
740  <literal>0</literal> will cause the autohangup feature to be disabled on this channel.</para>
741  </description>
742  <see-also>
743  <ref type="application">AGI</ref>
744  </see-also>
745  </agi>
746  <agi name="set callerid" language="en_US">
747  <synopsis>
748  Sets callerid for the current channel.
749  </synopsis>
750  <syntax>
751  <parameter name="number" required="true" />
752  </syntax>
753  <description>
754  <para>Changes the callerid of the current channel.</para>
755  </description>
756  <see-also>
757  <ref type="application">AGI</ref>
758  </see-also>
759  </agi>
760  <agi name="set context" language="en_US">
761  <synopsis>
762  Sets channel context.
763  </synopsis>
764  <syntax>
765  <parameter name="desired context" required="true" />
766  </syntax>
767  <description>
768  <para>Sets the context for continuation upon exiting the application.</para>
769  </description>
770  <see-also>
771  <ref type="agi">set extension</ref>
772  <ref type="agi">set priority</ref>
773  <ref type="application">AGI</ref>
774  </see-also>
775  </agi>
776  <agi name="set extension" language="en_US">
777  <synopsis>
778  Changes channel extension.
779  </synopsis>
780  <syntax>
781  <parameter name="new extension" required="true" />
782  </syntax>
783  <description>
784  <para>Changes the extension for continuation upon exiting the application.</para>
785  </description>
786  <see-also>
787  <ref type="agi">set context</ref>
788  <ref type="agi">set priority</ref>
789  <ref type="application">AGI</ref>
790  </see-also>
791  </agi>
792  <agi name="set music" language="en_US">
793  <synopsis>
794  Enable/Disable Music on hold generator
795  </synopsis>
796  <syntax>
797  <parameter name="boolean" required="true">
798  <enumlist>
799  <enum name="on" />
800  <enum name="off" />
801  </enumlist>
802  </parameter>
803  <parameter name="class" required="true" />
804  </syntax>
805  <description>
806  <para>Enables/Disables the music on hold generator. If <replaceable>class</replaceable>
807  is not specified, then the <literal>default</literal> music on hold class will be
808  used. This generator will be stopped automatically when playing a file.</para>
809  <para>Always returns <literal>0</literal>.</para>
810  </description>
811  <see-also>
812  <ref type="application">AGI</ref>
813  </see-also>
814  </agi>
815  <agi name="set priority" language="en_US">
816  <synopsis>
817  Set channel dialplan priority.
818  </synopsis>
819  <syntax>
820  <parameter name="priority" required="true" />
821  </syntax>
822  <description>
823  <para>Changes the priority for continuation upon exiting the application.
824  The priority must be a valid priority or label.</para>
825  </description>
826  <see-also>
827  <ref type="agi">set context</ref>
828  <ref type="agi">set extension</ref>
829  <ref type="application">AGI</ref>
830  </see-also>
831  </agi>
832  <agi name="set variable" language="en_US">
833  <synopsis>
834  Sets a channel variable.
835  </synopsis>
836  <syntax>
837  <parameter name="variablename" required="true" />
838  <parameter name="value" required="true" />
839  </syntax>
840  <description>
841  <para>Sets a variable to the current channel.</para>
842  </description>
843  <see-also>
844  <ref type="agi">get variable</ref>
845  <ref type="agi">get full variable</ref>
846  <ref type="application">AGI</ref>
847  </see-also>
848  </agi>
849  <agi name="stream file" language="en_US">
850  <synopsis>
851  Sends audio file on channel.
852  </synopsis>
853  <syntax>
854  <parameter name="filename" required="true">
855  <para>File name to play. The file extension must not be
856  included in the <replaceable>filename</replaceable>.</para>
857  </parameter>
858  <parameter name="escape_digits" required="true">
859  <para>Use double quotes for the digits if you wish none to be
860  permitted.</para>
861  </parameter>
862  <parameter name="sample offset">
863  <para>If sample offset is provided then the audio will seek to sample
864  offset before play starts.</para>
865  </parameter>
866  </syntax>
867  <description>
868  <para>Send the given file, allowing playback to be interrupted by the given
869  digits, if any. Returns <literal>0</literal> if playback completes without a digit
870  being pressed, or the ASCII numerical value of the digit if one was pressed,
871  or <literal>-1</literal> on error or if the channel was disconnected. If
872  musiconhold is playing before calling stream file it will be automatically
873  stopped and will not be restarted after completion.</para>
874  <para>It sets the following channel variables upon completion:</para>
875  <variablelist>
876  <variable name="PLAYBACKSTATUS">
877  <para>The status of the playback attempt as a text string.</para>
878  <value name="SUCCESS"/>
879  <value name="FAILED"/>
880  </variable>
881  </variablelist>
882  </description>
883  <see-also>
884  <ref type="agi">control stream file</ref>
885  <ref type="agi">get option</ref>
886  <ref type="application">AGI</ref>
887  </see-also>
888  </agi>
889  <agi name="tdd mode" language="en_US">
890  <synopsis>
891  Toggles TDD mode (for the deaf).
892  </synopsis>
893  <syntax>
894  <parameter name="boolean" required="true">
895  <enumlist>
896  <enum name="on" />
897  <enum name="off" />
898  </enumlist>
899  </parameter>
900  </syntax>
901  <description>
902  <para>Enable/Disable TDD transmission/reception on a channel. Returns <literal>1</literal> if
903  successful, or <literal>0</literal> if channel is not TDD-capable.</para>
904  </description>
905  <see-also>
906  <ref type="application">AGI</ref>
907  </see-also>
908  </agi>
909  <agi name="verbose" language="en_US">
910  <synopsis>
911  Logs a message to the asterisk verbose log.
912  </synopsis>
913  <syntax>
914  <parameter name="message" required="true" />
915  <parameter name="level" required="true" />
916  </syntax>
917  <description>
918  <para>Sends <replaceable>message</replaceable> to the console via verbose
919  message system. <replaceable>level</replaceable> is the verbose level (1-4).
920  Always returns <literal>1</literal></para>
921  </description>
922  <see-also>
923  <ref type="application">AGI</ref>
924  </see-also>
925  </agi>
926  <agi name="wait for digit" language="en_US">
927  <synopsis>
928  Waits for a digit to be pressed.
929  </synopsis>
930  <syntax>
931  <parameter name="timeout" required="true" />
932  </syntax>
933  <description>
934  <para>Waits up to <replaceable>timeout</replaceable> milliseconds for channel to
935  receive a DTMF digit. Returns <literal>-1</literal> on channel failure, <literal>0</literal>
936  if no digit is received in the timeout, or the numerical value of the ascii of the digit if
937  one is received. Use <literal>-1</literal> for the <replaceable>timeout</replaceable> value if
938  you desire the call to block indefinitely.</para>
939  </description>
940  <see-also>
941  <ref type="application">AGI</ref>
942  </see-also>
943  </agi>
944  <agi name="speech create" language="en_US">
945  <synopsis>
946  Creates a speech object.
947  </synopsis>
948  <syntax>
949  <parameter name="engine" required="true" />
950  </syntax>
951  <description>
952  <para>Create a speech object to be used by the other Speech AGI commands.</para>
953  </description>
954  <see-also>
955  <ref type="agi">speech set</ref>
956  <ref type="agi">speech destroy</ref>
957  <ref type="agi">speech load grammar</ref>
958  <ref type="agi">speech unload grammar</ref>
959  <ref type="agi">speech activate grammar</ref>
960  <ref type="agi">speech deactivate grammar</ref>
961  <ref type="agi">speech recognize</ref>
962  <ref type="application">AGI</ref>
963  </see-also>
964  </agi>
965  <agi name="speech set" language="en_US">
966  <synopsis>
967  Sets a speech engine setting.
968  </synopsis>
969  <syntax>
970  <parameter name="name" required="true" />
971  <parameter name="value" required="true" />
972  </syntax>
973  <description>
974  <para>Set an engine-specific setting.</para>
975  </description>
976  <see-also>
977  <ref type="agi">speech create</ref>
978  <ref type="agi">speech destroy</ref>
979  <ref type="agi">speech load grammar</ref>
980  <ref type="agi">speech unload grammar</ref>
981  <ref type="agi">speech activate grammar</ref>
982  <ref type="agi">speech deactivate grammar</ref>
983  <ref type="agi">speech recognize</ref>
984  <ref type="application">AGI</ref>
985  </see-also>
986  </agi>
987  <agi name="speech destroy" language="en_US">
988  <synopsis>
989  Destroys a speech object.
990  </synopsis>
991  <syntax>
992  </syntax>
993  <description>
994  <para>Destroy the speech object created by <literal>SPEECH CREATE</literal>.</para>
995  </description>
996  <see-also>
997  <ref type="agi">speech create</ref>
998  <ref type="agi">speech set</ref>
999  <ref type="agi">speech load grammar</ref>
1000  <ref type="agi">speech unload grammar</ref>
1001  <ref type="agi">speech activate grammar</ref>
1002  <ref type="agi">speech deactivate grammar</ref>
1003  <ref type="agi">speech recognize</ref>
1004  <ref type="application">AGI</ref>
1005  </see-also>
1006  </agi>
1007  <agi name="speech load grammar" language="en_US">
1008  <synopsis>
1009  Loads a grammar.
1010  </synopsis>
1011  <syntax>
1012  <parameter name="grammar name" required="true" />
1013  <parameter name="path to grammar" required="true" />
1014  </syntax>
1015  <description>
1016  <para>Loads the specified grammar as the specified name.</para>
1017  </description>
1018  <see-also>
1019  <ref type="agi">speech create</ref>
1020  <ref type="agi">speech set</ref>
1021  <ref type="agi">speech destroy</ref>
1022  <ref type="agi">speech unload grammar</ref>
1023  <ref type="agi">speech activate grammar</ref>
1024  <ref type="agi">speech deactivate grammar</ref>
1025  <ref type="agi">speech recognize</ref>
1026  <ref type="application">AGI</ref>
1027  </see-also>
1028  </agi>
1029  <agi name="speech unload grammar" language="en_US">
1030  <synopsis>
1031  Unloads a grammar.
1032  </synopsis>
1033  <syntax>
1034  <parameter name="grammar name" required="true" />
1035  </syntax>
1036  <description>
1037  <para>Unloads the specified grammar.</para>
1038  </description>
1039  <see-also>
1040  <ref type="agi">speech create</ref>
1041  <ref type="agi">speech set</ref>
1042  <ref type="agi">speech destroy</ref>
1043  <ref type="agi">speech load grammar</ref>
1044  <ref type="agi">speech activate grammar</ref>
1045  <ref type="agi">speech deactivate grammar</ref>
1046  <ref type="agi">speech recognize</ref>
1047  <ref type="application">AGI</ref>
1048  </see-also>
1049  </agi>
1050  <agi name="speech activate grammar" language="en_US">
1051  <synopsis>
1052  Activates a grammar.
1053  </synopsis>
1054  <syntax>
1055  <parameter name="grammar name" required="true" />
1056  </syntax>
1057  <description>
1058  <para>Activates the specified grammar on the speech object.</para>
1059  </description>
1060  <see-also>
1061  <ref type="agi">speech create</ref>
1062  <ref type="agi">speech set</ref>
1063  <ref type="agi">speech destroy</ref>
1064  <ref type="agi">speech load grammar</ref>
1065  <ref type="agi">speech unload grammar</ref>
1066  <ref type="agi">speech deactivate grammar</ref>
1067  <ref type="agi">speech recognize</ref>
1068  <ref type="application">AGI</ref>
1069  </see-also>
1070  </agi>
1071  <agi name="speech deactivate grammar" language="en_US">
1072  <synopsis>
1073  Deactivates a grammar.
1074  </synopsis>
1075  <syntax>
1076  <parameter name="grammar name" required="true" />
1077  </syntax>
1078  <description>
1079  <para>Deactivates the specified grammar on the speech object.</para>
1080  </description>
1081  <see-also>
1082  <ref type="agi">speech create</ref>
1083  <ref type="agi">speech set</ref>
1084  <ref type="agi">speech destroy</ref>
1085  <ref type="agi">speech load grammar</ref>
1086  <ref type="agi">speech unload grammar</ref>
1087  <ref type="agi">speech activate grammar</ref>
1088  <ref type="agi">speech recognize</ref>
1089  <ref type="application">AGI</ref>
1090  </see-also>
1091  </agi>
1092  <agi name="speech recognize" language="en_US">
1093  <synopsis>
1094  Recognizes speech.
1095  </synopsis>
1096  <syntax>
1097  <parameter name="prompt" required="true" />
1098  <parameter name="timeout" required="true" />
1099  <parameter name="offset" />
1100  </syntax>
1101  <description>
1102  <para>Plays back given <replaceable>prompt</replaceable> while listening for
1103  speech and dtmf.</para>
1104  </description>
1105  <see-also>
1106  <ref type="agi">speech create</ref>
1107  <ref type="agi">speech set</ref>
1108  <ref type="agi">speech destroy</ref>
1109  <ref type="agi">speech load grammar</ref>
1110  <ref type="agi">speech unload grammar</ref>
1111  <ref type="agi">speech activate grammar</ref>
1112  <ref type="agi">speech deactivate grammar</ref>
1113  <ref type="application">AGI</ref>
1114  </see-also>
1115  </agi>
1116  <application name="AGI" language="en_US">
1117  <synopsis>
1118  Executes an AGI compliant application.
1119  </synopsis>
1120  <syntax>
1121  <parameter name="command" required="true">
1122  <para>How AGI should be invoked on the channel.</para>
1123  </parameter>
1124  <parameter name="args">
1125  <para>Arguments to pass to the AGI script or server.</para>
1126  <argument name="arg1" required="true" />
1127  <argument name="arg2" multiple="yes" />
1128  </parameter>
1129  </syntax>
1130  <description>
1131  <para>Executes an Asterisk Gateway Interface compliant
1132  program on a channel. AGI allows Asterisk to launch external programs written
1133  in any language to control a telephony channel, play audio, read DTMF digits,
1134  etc. by communicating with the AGI protocol.</para>
1135  <para>The following variants of AGI exist, and are chosen based on the value
1136  passed to <replaceable>command</replaceable>:</para>
1137  <enumlist>
1138  <enum name="AGI">
1139  <para>The classic variant of AGI, this will launch the script
1140  specified by <replaceable>command</replaceable> as a new process.
1141  Communication with the script occurs on <literal>stdin</literal> and
1142  <literal>stdout</literal>. If the full path to the script is not
1143  provided, the <directory>astagidir</directory> specified in
1144  <filename>asterisk.conf</filename> will be used.
1145  </para>
1146  </enum>
1147  <enum name="FastAGI">
1148  <para>Connect Asterisk to a FastAGI server using a TCP connection.
1149  The URI to the FastAGI server should be given in the form
1150  <literal>[scheme]://host.domain[:port][/script/name]</literal>,
1151  where <replaceable>scheme</replaceable> is either <literal>agi</literal>
1152  or <literal>hagi</literal>.</para>
1153  <para>In the case of <literal>hagi</literal>, an SRV lookup will be
1154  performed to try to connect to a list of FastAGI servers. The hostname in
1155  the URI must be prefixed with <literal>_agi._tcp</literal>. prior to the DNS resolution. For
1156  example, if you specify the URI <literal>hagi://agi.example.com/foo.agi</literal>
1157  the DNS query would be for <literal>_agi._tcp.agi.example.com</literal>. You
1158  will need to make sure this resolves correctly.</para>
1159  </enum>
1160  <enum name="AsyncAGI">
1161  <para>Use AMI to control the channel in AGI. AGI commands can be invoked
1162  using the <literal>AMI</literal> action, with a variety of AGI specific
1163  events passed back over the AMI connection. AsyncAGI should be invoked
1164  by passing <literal>agi:async</literal> to the <replaceable>command</replaceable>
1165  parameter.</para>
1166  </enum>
1167  </enumlist>
1168  <note>
1169  <para>As of <literal>1.6.0</literal>, this channel will
1170  not stop dialplan execution on hangup inside of this application. Dialplan
1171  execution will continue normally, even upon hangup until the AGI application
1172  signals a desire to stop (either by exiting or, in the case of a net script, by
1173  closing the connection).</para>
1174  <para>A locally executed AGI script will receive <literal>SIGHUP</literal> on
1175  hangup from the channel except when using <literal>DeadAGI</literal>
1176  (or when the channel is already hungup). A fast AGI server will
1177  correspondingly receive a <literal>HANGUP</literal> inline with the command dialog.
1178  Both of these signals may be disabled by setting the <variable>AGISIGHUP</variable>
1179  channel variable to <literal>no</literal> before executing the AGI application.
1180  Alternatively, if you would like the AGI application to exit immediately
1181  after a channel hangup is detected, set the <variable>AGIEXITONHANGUP</variable>
1182  variable to <literal>yes</literal>.</para>
1183  </note>
1184  <example title="Start the AGI script /tmp/my-cool-script.sh, passing it the contents of the channel variable FOO">
1185  same => n,AGI(/tmp/my-cool-script.sh,${FOO})
1186  </example>
1187  <example title="Start the AGI script my-cool-script.sh located in the astagidir directory, specified in asterisk.conf">
1188  same => n,AGI(my-cool-script.sh)
1189  </example>
1190  <example title="Connect to the FastAGI server located at 127.0.0.1 and start the script awesome-script">
1191  same => n,AGI(agi://127.0.0.1/awesome-script)
1192  </example>
1193  <example title="Start AsyncAGI">
1194  same => n,AGI(agi:async)
1195  </example>
1196  <para>This application sets the following channel variable upon completion:</para>
1197  <variablelist>
1198  <variable name="AGISTATUS">
1199  <para>The status of the attempt to the run the AGI script
1200  text string, one of:</para>
1201  <value name="SUCCESS" />
1202  <value name="FAILURE" />
1203  <value name="NOTFOUND" />
1204  <value name="HANGUP" />
1205  </variable>
1206  </variablelist>
1207  </description>
1208  <see-also>
1209  <ref type="manager">AGI</ref>
1210  <ref type="managerEvent">AsyncAGIStart</ref>
1211  <ref type="managerEvent">AsyncAGIEnd</ref>
1212  <ref type="application">EAGI</ref>
1213  <ref type="application">DeadAGI</ref>
1214  <ref type="filename">asterisk.conf</ref>
1215  </see-also>
1216  </application>
1217  <application name="EAGI" language="en_US">
1218  <synopsis>
1219  Executes an EAGI compliant application.
1220  </synopsis>
1221  <syntax>
1222  <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
1223  <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
1224  </syntax>
1225  <description>
1226  <para>Using 'EAGI' provides enhanced AGI, with incoming audio available out of band
1227  on file descriptor 3. In all other respects, it behaves in the same fashion as
1228  AGI. See the documentation for the <literal>AGI</literal> dialplan application for
1229  more information on invoking AGI on a channel.</para>
1230  <para>This application sets the following channel variable upon completion:</para>
1231  <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
1232  </description>
1233  <see-also>
1234  <ref type="application">AGI</ref>
1235  <ref type="application">DeadAGI</ref>
1236  </see-also>
1237  </application>
1238  <application name="DeadAGI" language="en_US">
1239  <synopsis>
1240  Executes AGI on a hungup channel.
1241  </synopsis>
1242  <syntax>
1243  <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
1244  <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
1245  </syntax>
1246  <description>
1247  <warning>
1248  <para>This application is deprecated and may be removed in a future version
1249  of Asterisk. Use the replacement application <literal>AGI</literal> instead
1250  of <literal>DeadAGI</literal>.
1251  </para>
1252  </warning>
1253  <para>Execute AGI on a 'dead' or hungup channel. See the documentation for the
1254  <literal>AGI</literal> dialplan application for more information on invoking
1255  AGI on a channel.</para>
1256  <para>This application sets the following channel variable upon completion:</para>
1257  <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
1258  </description>
1259  <see-also>
1260  <ref type="application">AGI</ref>
1261  <ref type="application">EAGI</ref>
1262  </see-also>
1263  </application>
1264  <manager name="AGI" language="en_US">
1265  <synopsis>
1266  Add an AGI command to execute by Async AGI.
1267  </synopsis>
1268  <syntax>
1269  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1270  <parameter name="Channel" required="true">
1271  <para>Channel that is currently in Async AGI.</para>
1272  </parameter>
1273  <parameter name="Command" required="true">
1274  <para>Application to execute.</para>
1275  </parameter>
1276  <parameter name="CommandID">
1277  <para>This will be sent back in CommandID header of AsyncAGI exec
1278  event notification.</para>
1279  </parameter>
1280  </syntax>
1281  <description>
1282  <para>Add an AGI command to the execute queue of the channel in Async AGI.</para>
1283  </description>
1284  <see-also>
1285  <ref type="managerEvent">AsyncAGIStart</ref>
1286  <ref type="managerEvent">AsyncAGIExec</ref>
1287  <ref type="managerEvent">AsyncAGIEnd</ref>
1288  </see-also>
1289  </manager>
1290  <managerEvent language="en_US" name="AsyncAGIStart">
1291  <managerEventInstance class="EVENT_FLAG_AGI">
1292  <synopsis>Raised when a channel starts AsyncAGI command processing.</synopsis>
1293  <syntax>
1294  <channel_snapshot/>
1295  <parameter name="Env">
1296  <para>URL encoded string read from the AsyncAGI server.</para>
1297  </parameter>
1298  </syntax>
1299  <see-also>
1300  <ref type="managerEvent">AsyncAGIEnd</ref>
1301  <ref type="managerEvent">AsyncAGIExec</ref>
1302  <ref type="application">AGI</ref>
1303  <ref type="manager">AGI</ref>
1304  </see-also>
1305  </managerEventInstance>
1306  </managerEvent>
1307  <managerEvent language="en_US" name="AsyncAGIEnd">
1308  <managerEventInstance class="EVENT_FLAG_AGI">
1309  <synopsis>Raised when a channel stops AsyncAGI command processing.</synopsis>
1310  <syntax>
1311  <channel_snapshot/>
1312  </syntax>
1313  <see-also>
1314  <ref type="managerEvent">AsyncAGIStart</ref>
1315  <ref type="managerEvent">AsyncAGIExec</ref>
1316  <ref type="application">AGI</ref>
1317  <ref type="manager">AGI</ref>
1318  </see-also>
1319  </managerEventInstance>
1320  </managerEvent>
1321  <managerEvent language="en_US" name="AsyncAGIExec">
1322  <managerEventInstance class="EVENT_FLAG_AGI">
1323  <synopsis>Raised when AsyncAGI completes an AGI command.</synopsis>
1324  <syntax>
1325  <channel_snapshot/>
1326  <parameter name="CommandID" required="false">
1327  <para>Optional command ID sent by the AsyncAGI server to identify the command.</para>
1328  </parameter>
1329  <parameter name="Result">
1330  <para>URL encoded result string from the executed AGI command.</para>
1331  </parameter>
1332  </syntax>
1333  <see-also>
1334  <ref type="managerEvent">AsyncAGIStart</ref>
1335  <ref type="managerEvent">AsyncAGIEnd</ref>
1336  <ref type="application">AGI</ref>
1337  <ref type="manager">AGI</ref>
1338  </see-also>
1339  </managerEventInstance>
1340  </managerEvent>
1341  <managerEvent language="en_US" name="AGIExecStart">
1342  <managerEventInstance class="EVENT_FLAG_AGI">
1343  <synopsis>Raised when a received AGI command starts processing.</synopsis>
1344  <syntax>
1345  <channel_snapshot/>
1346  <parameter name="Command">
1347  <para>The AGI command as received from the external source.</para>
1348  </parameter>
1349  <parameter name="CommandId">
1350  <para>Random identification number assigned to the execution of this command.</para>
1351  </parameter>
1352  </syntax>
1353  <see-also>
1354  <ref type="managerEvent">AGIExecEnd</ref>
1355  <ref type="application">AGI</ref>
1356  </see-also>
1357  </managerEventInstance>
1358  </managerEvent>
1359  <managerEvent language="en_US" name="AGIExecEnd">
1360  <managerEventInstance class="EVENT_FLAG_AGI">
1361  <synopsis>Raised when a received AGI command completes processing.</synopsis>
1362  <syntax>
1363  <channel_snapshot/>
1364  <xi:include xpointer="xpointer(/docs/managerEvent[@name='AGIExecStart']/managerEventInstance/syntax/parameter)" />
1365  <parameter name="ResultCode">
1366  <para>The numeric result code from AGI</para>
1367  </parameter>
1368  <parameter name="Result">
1369  <para>The text result reason from AGI</para>
1370  </parameter>
1371  </syntax>
1372  <see-also>
1373  <ref type="managerEvent">AGIExecStart</ref>
1374  <ref type="application">AGI</ref>
1375  </see-also>
1376  </managerEventInstance>
1377  </managerEvent>
1378  ***/
1379 
1380 #define MAX_ARGS 128
1381 #define MAX_CMD_LEN 80
1382 #define AGI_NANDFS_RETRY 3
1383 #define AGI_BUF_LEN 2048
1384 #define SRV_PREFIX "_agi._tcp."
1385 
1386 static char *app = "AGI";
1387 
1388 static char *eapp = "EAGI";
1389 
1390 static char *deadapp = "DeadAGI";
1391 
1392 static int agidebug = 0;
1393 
1394 #define TONE_BLOCK_SIZE 200
1395 
1396 /* Max time to connect to an AGI remote host */
1397 #define MAX_AGI_CONNECT 2000
1398 
1399 #define AGI_PORT 4573
1400 
1401 /*! Special return code for "asyncagi break" command. */
1402 #define ASYNC_AGI_BREAK 3
1403 
1411 };
1412 
1414 {
1416  RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1417  RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
1418 
1419  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1420  event_string = ast_manager_str_from_json_object(obj->blob, NULL);
1421  if (!channel_string || !event_string) {
1422  return NULL;
1423  }
1424 
1426  "%s"
1427  "%s",
1428  ast_str_buffer(channel_string),
1429  ast_str_buffer(event_string));
1430 }
1431 
1433 {
1434  return agi_channel_to_ami("AGIExecStart", message);
1435 }
1436 
1438 {
1439  return agi_channel_to_ami("AGIExecEnd", message);
1440 }
1441 
1443 {
1444  return agi_channel_to_ami("AsyncAGIStart", message);
1445 }
1446 
1448 {
1449  return agi_channel_to_ami("AsyncAGIExec", message);
1450 }
1451 
1453 {
1454  return agi_channel_to_ami("AsyncAGIEnd", message);
1455 }
1456 
1459  );
1462  );
1463 STASIS_MESSAGE_TYPE_DEFN_LOCAL(agi_async_start_type,
1465  );
1468  );
1471  );
1472 
1473 static agi_command *find_command(const char * const cmds[], int exact);
1474 
1476 #define AGI_BUF_INITSIZE 256
1477 
1478 int AST_OPTIONAL_API_NAME(ast_agi_send)(int fd, struct ast_channel *chan, char *fmt, ...)
1479 {
1480  int res = 0;
1481  va_list ap;
1482  struct ast_str *buf;
1483 
1485  return -1;
1486 
1487  va_start(ap, fmt);
1488  res = ast_str_set_va(&buf, 0, fmt, ap);
1489  va_end(ap);
1490 
1491  if (res == -1) {
1492  ast_log(LOG_ERROR, "Out of memory\n");
1493  return -1;
1494  }
1495 
1496  if (agidebug) {
1497  if (chan) {
1498  ast_verbose("<%s>AGI Tx >> %s", ast_channel_name(chan), ast_str_buffer(buf));
1499  } else {
1500  ast_verbose("AGI Tx >> %s", ast_str_buffer(buf));
1501  }
1502  }
1503 
1505 }
1506 
1507 /* linked list of AGI commands ready to be executed by Async AGI */
1508 struct agi_cmd {
1509  char *cmd_buffer;
1510  char *cmd_id;
1512 };
1513 
1514 static void free_agi_cmd(struct agi_cmd *cmd)
1515 {
1516  ast_free(cmd->cmd_buffer);
1517  ast_free(cmd->cmd_id);
1518  ast_free(cmd);
1519 }
1520 
1521 /* AGI datastore destructor */
1522 static void agi_destroy_commands_cb(void *data)
1523 {
1524  struct agi_cmd *cmd;
1525  AST_LIST_HEAD(, agi_cmd) *chan_cmds = data;
1526  AST_LIST_LOCK(chan_cmds);
1527  while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) {
1528  free_agi_cmd(cmd);
1529  }
1530  AST_LIST_UNLOCK(chan_cmds);
1531  AST_LIST_HEAD_DESTROY(chan_cmds);
1532  ast_free(chan_cmds);
1533 }
1534 
1535 /* channel datastore to keep the queue of AGI commands in the channel */
1536 static const struct ast_datastore_info agi_commands_datastore_info = {
1537  .type = "AsyncAGI",
1538  .destroy = agi_destroy_commands_cb
1539 };
1540 
1541 /*!
1542  * \brief Retrieve the list head to the requested channel's AGI datastore
1543  * \param chan Channel datastore is requested for
1544  * \param cmd Pointer to the struct pointer which will reference the head of the agi command list.
1545  *
1546  * \retval 0 if the datastore was valid and the list head was retrieved appropriately (even if it's
1547  * NULL and the list is empty)
1548  * \retval -1 if the datastore could not be retrieved causing an error
1549 */
1550 static int get_agi_cmd(struct ast_channel *chan, struct agi_cmd **cmd)
1551 {
1552  struct ast_datastore *store;
1554 
1555  ast_channel_lock(chan);
1557  ast_channel_unlock(chan);
1558  if (!store) {
1559  ast_log(LOG_ERROR, "Huh? Async AGI datastore disappeared on Channel %s!\n",
1560  ast_channel_name(chan));
1561  *cmd = NULL;
1562  return -1;
1563  }
1564  agi_commands = store->data;
1568  return 0;
1569 }
1570 
1571 /* channel is locked when calling this one either from the CLI or manager thread */
1572 static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
1573 {
1574  struct ast_datastore *store;
1575  struct agi_cmd *cmd;
1577 
1579  if (!store) {
1580  ast_log(LOG_WARNING, "Channel %s is not setup for Async AGI.\n", ast_channel_name(chan));
1581  return -1;
1582  }
1583  agi_commands = store->data;
1584  cmd = ast_calloc(1, sizeof(*cmd));
1585  if (!cmd) {
1586  return -1;
1587  }
1588  cmd->cmd_buffer = ast_strdup(cmd_buff);
1589  if (!cmd->cmd_buffer) {
1590  ast_free(cmd);
1591  return -1;
1592  }
1593  cmd->cmd_id = ast_strdup(cmd_id);
1594  if (!cmd->cmd_id) {
1595  ast_free(cmd->cmd_buffer);
1596  ast_free(cmd);
1597  return -1;
1598  }
1602  return 0;
1603 }
1604 
1605 static int add_to_agi(struct ast_channel *chan)
1606 {
1607  struct ast_datastore *datastore;
1608  AST_LIST_HEAD(, agi_cmd) *agi_cmds_list;
1609 
1610  /* check if already on AGI */
1611  ast_channel_lock(chan);
1613  ast_channel_unlock(chan);
1614  if (datastore) {
1615  /* we already have an AGI datastore, let's just
1616  return success */
1617  return 0;
1618  }
1619 
1620  /* the channel has never been on Async AGI,
1621  let's allocate it's datastore */
1622  datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI");
1623  if (!datastore) {
1624  return -1;
1625  }
1626  agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list));
1627  if (!agi_cmds_list) {
1628  ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n");
1629  ast_datastore_free(datastore);
1630  return -1;
1631  }
1632  datastore->data = agi_cmds_list;
1633  AST_LIST_HEAD_INIT(agi_cmds_list);
1634  ast_channel_lock(chan);
1635  ast_channel_datastore_add(chan, datastore);
1636  ast_channel_unlock(chan);
1637  return 0;
1638 }
1639 
1640 /*!
1641  * \brief CLI command to add applications to execute in Async AGI
1642  * \param e
1643  * \param cmd
1644  * \param a
1645  *
1646  * \retval CLI_SUCCESS on success
1647  * \retval NULL when init or tab completion is used
1648 */
1649 static char *handle_cli_agi_add_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1650 {
1651  struct ast_channel *chan;
1652  switch (cmd) {
1653  case CLI_INIT:
1654  e->command = "agi exec";
1655  e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n"
1656  " Add AGI command to the execute queue of the specified channel in Async AGI\n";
1657  return NULL;
1658  case CLI_GENERATE:
1659  if (a->pos == 2)
1660  return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
1661  return NULL;
1662  }
1663 
1664  if (a->argc < 4) {
1665  return CLI_SHOWUSAGE;
1666  }
1667 
1668  if (!(chan = ast_channel_get_by_name(a->argv[2]))) {
1669  ast_cli(a->fd, "Channel %s does not exist.\n", a->argv[2]);
1670  return CLI_FAILURE;
1671  }
1672 
1673  ast_channel_lock(chan);
1674 
1675  if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) {
1676  ast_cli(a->fd, "Failed to add AGI command to queue of channel %s\n", ast_channel_name(chan));
1677  ast_channel_unlock(chan);
1678  chan = ast_channel_unref(chan);
1679  return CLI_FAILURE;
1680  }
1681 
1682  ast_debug(1, "Added AGI command to channel %s queue\n", ast_channel_name(chan));
1683 
1684  ast_channel_unlock(chan);
1685  chan = ast_channel_unref(chan);
1686 
1687  return CLI_SUCCESS;
1688 }
1689 
1690 /*!
1691  * \brief Add a new command to execute by the Async AGI application
1692  * \param s
1693  * \param m
1694  *
1695  * It will append the application to the specified channel's queue
1696  * if the channel is not inside Async AGI application it will return an error
1697  * \retval 0 on success or incorrect use
1698  * \retval 1 on failure to add the command ( most likely because the channel
1699  * is not in Async AGI loop )
1700 */
1701 static int action_add_agi_cmd(struct mansession *s, const struct message *m)
1702 {
1703  const char *channel = astman_get_header(m, "Channel");
1704  const char *cmdbuff = astman_get_header(m, "Command");
1705  const char *cmdid = astman_get_header(m, "CommandID");
1706  struct ast_channel *chan;
1707  char buf[256];
1708 
1709  if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) {
1710  astman_send_error(s, m, "Both, Channel and Command are *required*");
1711  return 0;
1712  }
1713 
1714  if (!(chan = ast_channel_get_by_name(channel))) {
1715  snprintf(buf, sizeof(buf), "Channel %s does not exist.", channel);
1716  astman_send_error(s, m, buf);
1717  return 0;
1718  }
1719 
1720  ast_channel_lock(chan);
1721 
1722  if (add_agi_cmd(chan, cmdbuff, cmdid)) {
1723  snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", ast_channel_name(chan));
1724  astman_send_error(s, m, buf);
1725  ast_channel_unlock(chan);
1726  chan = ast_channel_unref(chan);
1727  return 0;
1728  }
1729 
1730  ast_channel_unlock(chan);
1731  chan = ast_channel_unref(chan);
1732 
1733  astman_send_ack(s, m, "Added AGI command to queue");
1734 
1735  return 0;
1736 }
1737 
1738 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead);
1739 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[]);
1740 
1741 /*!
1742  * \internal
1743  * \brief Read and handle a channel frame for Async AGI.
1744  *
1745  * \param chan Channel to read a frame from.
1746  *
1747  * \retval AGI_RESULT_SUCCESS on success.
1748  * \retval AGI_RESULT_HANGUP on hangup.
1749  * \retval AGI_RESULT_FAILURE on error.
1750  */
1751 static enum agi_result async_agi_read_frame(struct ast_channel *chan)
1752 {
1753  struct ast_frame *f;
1754 
1755  f = ast_read(chan);
1756  if (!f) {
1757  ast_debug(3, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
1758  return AGI_RESULT_HANGUP;
1759  }
1760  if (f->frametype == AST_FRAME_CONTROL) {
1761  /*
1762  * Is there any other frame we should care about besides
1763  * AST_CONTROL_HANGUP?
1764  */
1765  switch (f->subclass.integer) {
1766  case AST_CONTROL_HANGUP:
1767  ast_debug(3, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
1768  ast_frfree(f);
1769  return AGI_RESULT_HANGUP;
1770  default:
1771  break;
1772  }
1773  }
1774  ast_frfree(f);
1775 
1776  return AGI_RESULT_SUCCESS;
1777 }
1778 
1779 static enum agi_result launch_asyncagi(struct ast_channel *chan, int argc, char *argv[], int *efd)
1780 {
1781 /* This buffer sizes might cause truncation if the AGI command writes more data
1782  than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command
1783  that writes a response larger than 1024 bytes?, I don't think so, most of
1784  them are just result=blah stuff. However probably if GET VARIABLE is called
1785  and the variable has large amount of data, that could be a problem. We could
1786  make this buffers dynamic, but let's leave that as a second step.
1787 
1788  AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe
1789  number. Some characters of AGI buf will be url encoded to be sent to manager
1790  clients. An URL encoded character will take 3 bytes, but again, to cause
1791  truncation more than about 70% of the AGI buffer should be URL encoded for
1792  that to happen. Not likely at all.
1793 
1794  On the other hand. I wonder if read() could eventually return less data than
1795  the amount already available in the pipe? If so, how to deal with that?
1796  So far, my tests on Linux have not had any problems.
1797  */
1798 #define AGI_BUF_SIZE 1024
1799 #define AMI_BUF_SIZE 2048
1800  enum agi_result cmd_status;
1801  struct agi_cmd *cmd;
1802  int res;
1803  int fds[2];
1804  int hungup;
1805  int timeout = 100;
1806  char agi_buffer[AGI_BUF_SIZE + 1];
1807  char ami_buffer[AMI_BUF_SIZE];
1808  enum agi_result returnstatus = AGI_RESULT_SUCCESS;
1809  AGI async_agi;
1810  RAII_VAR(struct ast_json *, startblob, NULL, ast_json_unref);
1811 
1812  if (efd) {
1813  ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n");
1814  return AGI_RESULT_FAILURE;
1815  }
1816 
1817  /* add AsyncAGI datastore to the channel */
1818  if (add_to_agi(chan)) {
1819  ast_log(LOG_ERROR, "Failed to start Async AGI on channel %s\n", ast_channel_name(chan));
1820  return AGI_RESULT_FAILURE;
1821  }
1822 
1823  /* this pipe allows us to create a "fake" AGI struct to use
1824  the AGI commands */
1825  res = pipe(fds);
1826  if (res) {
1827  ast_log(LOG_ERROR, "Failed to create Async AGI pipe\n");
1828  /*
1829  * Intentionally do not remove the datastore added with
1830  * add_to_agi() the from channel. It will be removed when the
1831  * channel is hung up anyway.
1832  */
1833  return AGI_RESULT_FAILURE;
1834  }
1835 
1836  /* handlers will get the pipe write fd and we read the AGI responses
1837  from the pipe read fd */
1838  async_agi.fd = fds[1];
1839  async_agi.ctrl = fds[1];
1840  async_agi.audio = -1; /* no audio support */
1841  async_agi.fast = 0;
1842  async_agi.speech = NULL;
1843 
1844  /* notify possible manager users of a new channel ready to
1845  receive commands */
1846  setup_env(chan, "async", fds[1], 0, argc, argv);
1847  /* read the environment */
1848  res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1849  if (res <= 0) {
1850  ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s: %s\n",
1851  ast_channel_name(chan), res < 0 ? strerror(errno) : "EOF");
1852  returnstatus = AGI_RESULT_FAILURE;
1853  goto async_agi_abort;
1854  }
1855  agi_buffer[res] = '\0';
1856  /* encode it and send it thru the manager so whoever is going to take
1857  care of AGI commands on this channel can decide which AGI commands
1858  to execute based on the setup info */
1859  ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
1860  startblob = ast_json_pack("{s: s}", "Env", ami_buffer);
1861 
1862  ast_channel_publish_cached_blob(chan, agi_async_start_type(), startblob);
1863 
1864  hungup = ast_check_hangup_locked(chan);
1865 
1866  for (;;) {
1867  /*
1868  * Process as many commands as we can. Commands are added via
1869  * the manager or the cli threads.
1870  */
1871  while (!hungup) {
1872  RAII_VAR(struct ast_json *, execblob, NULL, ast_json_unref);
1873  res = get_agi_cmd(chan, &cmd);
1874 
1875  if (res) {
1876  returnstatus = AGI_RESULT_FAILURE;
1877  goto async_agi_done;
1878  } else if (!cmd) {
1879  break;
1880  }
1881 
1882  /* OK, we have a command, let's call the command handler. */
1883  cmd_status = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0);
1884 
1885  /*
1886  * The command handler must have written to our fake AGI struct
1887  * fd (the pipe), let's read the response.
1888  */
1889  res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1890  if (res <= 0) {
1891  ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s: %s\n",
1892  ast_channel_name(chan), res < 0 ? strerror(errno) : "EOF");
1893  free_agi_cmd(cmd);
1894  returnstatus = AGI_RESULT_FAILURE;
1895  goto async_agi_done;
1896  }
1897  /*
1898  * We have a response, let's send the response thru the manager.
1899  * Include the CommandID if it was specified when the command
1900  * was added.
1901  */
1902  agi_buffer[res] = '\0';
1903  ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
1904 
1905  execblob = ast_json_pack("{s: s}", "Result", ami_buffer);
1906  if (execblob && !ast_strlen_zero(cmd->cmd_id)) {
1907  ast_json_object_set(execblob, "CommandId", ast_json_string_create(cmd->cmd_id));
1908  }
1909  ast_channel_publish_cached_blob(chan, agi_async_exec_type(), execblob);
1910 
1911  free_agi_cmd(cmd);
1912 
1913  /*
1914  * Check the command status to determine if we should continue
1915  * executing more commands.
1916  */
1917  hungup = ast_check_hangup(chan);
1918  switch (cmd_status) {
1919  case AGI_RESULT_FAILURE:
1920  if (!hungup) {
1921  /* The failure was not because of a hangup. */
1922  returnstatus = AGI_RESULT_FAILURE;
1923  goto async_agi_done;
1924  }
1925  break;
1927  /* Only the "asyncagi break" command does this. */
1928  returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1929  goto async_agi_done;
1930  default:
1931  break;
1932  }
1933  }
1934 
1935  if (!hungup) {
1936  /* Wait a bit for a frame to read or to poll for a new command. */
1937  res = ast_waitfor(chan, timeout);
1938  if (res < 0) {
1939  ast_debug(1, "ast_waitfor returned <= 0 on chan %s\n", ast_channel_name(chan));
1940  returnstatus = AGI_RESULT_FAILURE;
1941  break;
1942  }
1943  } else {
1944  /*
1945  * Read the channel control queue until it is dry so we can
1946  * quit.
1947  */
1948  res = 1;
1949  }
1950  if (0 < res) {
1951  do {
1952  cmd_status = async_agi_read_frame(chan);
1953  if (cmd_status != AGI_RESULT_SUCCESS) {
1954  returnstatus = cmd_status;
1955  goto async_agi_done;
1956  }
1957  hungup = ast_check_hangup(chan);
1958  } while (hungup);
1959  } else {
1960  hungup = ast_check_hangup(chan);
1961  }
1962  }
1963 async_agi_done:
1964 
1965  if (async_agi.speech) {
1966  ast_speech_destroy(async_agi.speech);
1967  }
1968  /* notify manager users this channel cannot be controlled anymore by Async AGI */
1969  ast_channel_publish_cached_blob(chan, agi_async_end_type(), NULL);
1970 
1971 async_agi_abort:
1972  /* close the pipe */
1973  close(fds[0]);
1974  close(fds[1]);
1975 
1976  /*
1977  * Intentionally do not remove the datastore added with
1978  * add_to_agi() the from channel. There might be commands still
1979  * in the queue or in-flight to us and AsyncAGI may get called
1980  * again. The datastore destructor will be called on channel
1981  * destruction anyway.
1982  */
1983 
1984  if (returnstatus == AGI_RESULT_SUCCESS) {
1985  returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1986  }
1987  return returnstatus;
1988 
1989 #undef AGI_BUF_SIZE
1990 #undef AMI_BUF_SIZE
1991 }
1992 
1993 /*!
1994  * \internal
1995  * \brief Handle the connection that was started by launch_netscript.
1996  *
1997  * \param agiurl Url that we are trying to connect to.
1998  * \param addr Address that host was resolved to.
1999  * \param netsockfd File descriptor of socket.
2000  *
2001  * \retval 0 when connection is succesful.
2002  * \retval 1 when there is an error.
2003  */
2004 static int handle_connection(const char *agiurl, const struct ast_sockaddr addr, const int netsockfd)
2005 {
2006  struct pollfd pfds[1];
2007  int res, conresult;
2008  socklen_t reslen;
2009 
2010  reslen = sizeof(conresult);
2011 
2012  pfds[0].fd = netsockfd;
2013  pfds[0].events = POLLOUT;
2014 
2015  while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) {
2016  if (errno != EINTR) {
2017  if (!res) {
2018  ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n",
2019  agiurl, MAX_AGI_CONNECT);
2020  } else {
2021  ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
2022  }
2023 
2024  return 1;
2025  }
2026  }
2027 
2028  if (getsockopt(pfds[0].fd, SOL_SOCKET, SO_ERROR, &conresult, &reslen) < 0) {
2029  ast_log(LOG_WARNING, "Connection to %s failed with error: %s\n",
2030  ast_sockaddr_stringify(&addr), strerror(errno));
2031  return 1;
2032  }
2033 
2034  if (conresult) {
2035  ast_log(LOG_WARNING, "Connecting to '%s' failed for url '%s': %s\n",
2036  ast_sockaddr_stringify(&addr), agiurl, strerror(conresult));
2037  return 1;
2038  }
2039 
2040  return 0;
2041 }
2042 
2043 /* launch_netscript: The fastagi handler.
2044  FastAGI defaults to port 4573 */
2045 static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
2046 {
2047  int s = 0;
2048  char *host, *script;
2049  int num_addrs = 0, i = 0;
2050  struct ast_sockaddr *addrs;
2051 
2052  /* agiurl is "agi://host.domain[:port][/script/name]" */
2053  host = ast_strdupa(agiurl + 6); /* Remove agi:// */
2054 
2055  /* Strip off any script name */
2056  if ((script = strchr(host, '/'))) {
2057  *script++ = '\0';
2058  } else {
2059  script = "";
2060  }
2061 
2062  if (!(num_addrs = ast_sockaddr_resolve(&addrs, host, 0, AST_AF_UNSPEC))) {
2063  ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
2064  return AGI_RESULT_FAILURE;
2065  }
2066 
2067  for (i = 0; i < num_addrs; i++) {
2068  if (!ast_sockaddr_port(&addrs[i])) {
2069  ast_sockaddr_set_port(&addrs[i], AGI_PORT);
2070  }
2071 
2072  if ((s = ast_socket_nonblock(addrs[i].ss.ss_family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
2073  ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
2074  continue;
2075  }
2076 
2077  if (ast_connect(s, &addrs[i]) && errno == EINPROGRESS) {
2078 
2079  if (handle_connection(agiurl, addrs[i], s)) {
2080  close(s);
2081  continue;
2082  }
2083 
2084  } else {
2085  ast_log(LOG_WARNING, "Connection to %s failed with unexpected error: %s\n",
2086  ast_sockaddr_stringify(&addrs[i]), strerror(errno));
2087  }
2088 
2089  break;
2090  }
2091 
2092  ast_free(addrs);
2093 
2094  if (i == num_addrs) {
2095  ast_log(LOG_WARNING, "Couldn't connect to any host. FastAGI failed.\n");
2096  return AGI_RESULT_FAILURE;
2097  }
2098 
2099  if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) {
2100  if (errno != EINTR) {
2101  ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
2102  close(s);
2103  return AGI_RESULT_FAILURE;
2104  }
2105  }
2106 
2107  /* If we have a script parameter, relay it to the fastagi server */
2108  /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */
2109  if (!ast_strlen_zero(script)) {
2110  ast_agi_send(s, NULL, "agi_network_script: %s\n", script);
2111  }
2112 
2113  ast_debug(4, "Wow, connected!\n");
2114  fds[0] = s;
2115  fds[1] = s;
2116  return AGI_RESULT_SUCCESS_FAST;
2117 }
2118 
2119 /*!
2120  * \internal
2121  * \brief The HA fastagi handler.
2122  * \param agiurl The request URL as passed to Agi() in the dial plan
2123  * \param argv The parameters after the URL passed to Agi() in the dial plan
2124  * \param fds Input/output file descriptors
2125  *
2126  * Uses SRV lookups to try to connect to a list of FastAGI servers. The hostname in
2127  * the URI is prefixed with _agi._tcp. prior to the DNS resolution. For
2128  * example, if you specify the URI \a hagi://agi.example.com/foo.agi the DNS
2129  * query would be for \a _agi._tcp.agi.example.com and you'll need to make sure
2130  * this resolves.
2131  *
2132  * This function parses the URI, resolves the SRV service name, forms new URIs
2133  * with the results of the DNS lookup, and then calls launch_netscript on the
2134  * new URIs until one succeeds.
2135  *
2136  * \return the result of the AGI operation.
2137  */
2138 static enum agi_result launch_ha_netscript(char *agiurl, char *argv[], int *fds)
2139 {
2140  char *host, *script;
2141  enum agi_result result;
2142  struct srv_context *context = NULL;
2143  int srv_ret;
2144  char service[256];
2145  char resolved_uri[1024];
2146  const char *srvhost;
2147  unsigned short srvport;
2148 
2149  /* format of agiurl is "hagi://host.domain[:port][/script/name]" */
2150  if (strlen(agiurl) < 7) { /* Remove hagi:// */
2151  ast_log(LOG_WARNING, "An error occurred parsing the AGI URI: %s", agiurl);
2152  return AGI_RESULT_FAILURE;
2153  }
2154  host = ast_strdupa(agiurl + 7);
2155 
2156  /* Strip off any script name */
2157  if ((script = strchr(host, '/'))) {
2158  *script++ = '\0';
2159  } else {
2160  script = "";
2161  }
2162 
2163  if (strchr(host, ':')) {
2164  ast_log(LOG_WARNING, "Specifying a port number disables SRV lookups: %s\n", agiurl);
2165  return launch_netscript(agiurl + 1, argv, fds); /* +1 to strip off leading h from hagi:// */
2166  }
2167 
2168  snprintf(service, sizeof(service), "%s%s", SRV_PREFIX, host);
2169 
2170  while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) {
2171  snprintf(resolved_uri, sizeof(resolved_uri), "agi://%s:%d/%s", srvhost, srvport, script);
2172  result = launch_netscript(resolved_uri, argv, fds);
2174  ast_log(LOG_WARNING, "AGI request failed for host '%s' (%s:%d)\n", host, srvhost, srvport);
2175  } else {
2176  /* The script launched so we must cleanup the context. */
2178  return result;
2179  }
2180  }
2181  /*
2182  * The DNS SRV lookup failed or we ran out of servers to check.
2183  * ast_srv_lookup() has already cleaned up the context for us.
2184  */
2185  if (srv_ret < 0) {
2186  ast_log(LOG_WARNING, "SRV lookup failed for %s\n", agiurl);
2187  }
2188 
2189  return AGI_RESULT_FAILURE;
2190 }
2191 
2192 static enum agi_result launch_script(struct ast_channel *chan, char *script, int argc, char *argv[], int *fds, int *efd, int *opid)
2193 {
2194  char tmp[256];
2195  int pid, toast[2], fromast[2], audio[2], res;
2196  struct stat st;
2197 
2198  if (!strncasecmp(script, "agi://", 6)) {
2199  return (efd == NULL) ? launch_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
2200  }
2201  if (!strncasecmp(script, "hagi://", 7)) {
2202  return (efd == NULL) ? launch_ha_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
2203  }
2204  if (!strncasecmp(script, "agi:async", sizeof("agi:async") - 1)) {
2205  return launch_asyncagi(chan, argc, argv, efd);
2206  }
2207 
2208  if (script[0] != '/') {
2209  snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script);
2210  script = tmp;
2211  }
2212 
2213  /* Before even trying let's see if the file actually exists */
2214  if (stat(script, &st)) {
2215  ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script);
2216  return AGI_RESULT_NOTFOUND;
2217  }
2218 
2219  if (pipe(toast)) {
2220  ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
2221  return AGI_RESULT_FAILURE;
2222  }
2223  if (pipe(fromast)) {
2224  ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
2225  close(toast[0]);
2226  close(toast[1]);
2227  return AGI_RESULT_FAILURE;
2228  }
2229  if (efd) {
2230  if (pipe(audio)) {
2231  ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
2232  close(fromast[0]);
2233  close(fromast[1]);
2234  close(toast[0]);
2235  close(toast[1]);
2236  return AGI_RESULT_FAILURE;
2237  }
2238 
2239  res = ast_fd_set_flags(audio[1], O_NONBLOCK);
2240  if (res < 0) {
2241  ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
2242  close(fromast[0]);
2243  close(fromast[1]);
2244  close(toast[0]);
2245  close(toast[1]);
2246  close(audio[0]);
2247  close(audio[1]);
2248  return AGI_RESULT_FAILURE;
2249  }
2250  }
2251 
2252  if ((pid = ast_safe_fork(1)) < 0) {
2253  ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
2254  return AGI_RESULT_FAILURE;
2255  }
2256  if (!pid) {
2257  /* Pass paths to AGI via environmental variables */
2258  setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
2259  setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
2260  setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
2261  setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
2262  setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
2263  setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
2264  setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
2265  setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
2266  setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
2267  setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
2268  setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
2269 
2270  /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
2271  ast_set_priority(0);
2272 
2273  /* Redirect stdin and out, provide enhanced audio channel if desired */
2274  dup2(fromast[0], STDIN_FILENO);
2275  dup2(toast[1], STDOUT_FILENO);
2276  if (efd)
2277  dup2(audio[0], STDERR_FILENO + 1);
2278  else
2279  close(STDERR_FILENO + 1);
2280 
2281  /* Close everything but stdin/out/error */
2282  ast_close_fds_above_n(STDERR_FILENO + 1);
2283 
2284  /* Execute script */
2285  /* XXX argv should be deprecated in favor of passing agi_argX paramaters */
2286  execv(script, argv);
2287  /* Can't use ast_log since FD's are closed */
2288  ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno));
2289  /* Special case to set status of AGI to failure */
2290  fprintf(stdout, "failure\n");
2291  fflush(stdout);
2292  _exit(1);
2293  }
2294  ast_verb(3, "Launched AGI Script %s\n", script);
2295  fds[0] = toast[0];
2296  fds[1] = fromast[1];
2297  if (efd)
2298  *efd = audio[1];
2299  /* close what we're not using in the parent */
2300  close(toast[1]);
2301  close(fromast[0]);
2302 
2303  if (efd)
2304  close(audio[0]);
2305 
2306  *opid = pid;
2307  return AGI_RESULT_SUCCESS;
2308 }
2309 
2310 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
2311 {
2312  int count;
2313 
2314  /* Print initial environment, with agi_request always being the first
2315  thing */
2316  ast_agi_send(fd, chan, "agi_request: %s\n", request);
2317  ast_agi_send(fd, chan, "agi_channel: %s\n", ast_channel_name(chan));
2318  ast_agi_send(fd, chan, "agi_language: %s\n", ast_channel_language(chan));
2319  ast_agi_send(fd, chan, "agi_type: %s\n", ast_channel_tech(chan)->type);
2320  ast_agi_send(fd, chan, "agi_uniqueid: %s\n", ast_channel_uniqueid(chan));
2321  ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
2322 
2323  /* ANI/DNIS */
2324  ast_agi_send(fd, chan, "agi_callerid: %s\n",
2325  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "unknown"));
2326  ast_agi_send(fd, chan, "agi_calleridname: %s\n",
2327  S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "unknown"));
2328  ast_agi_send(fd, chan, "agi_callingpres: %d\n",
2330  ast_agi_send(fd, chan, "agi_callingani2: %d\n", ast_channel_caller(chan)->ani2);
2331  ast_agi_send(fd, chan, "agi_callington: %d\n", ast_channel_caller(chan)->id.number.plan);
2332  ast_agi_send(fd, chan, "agi_callingtns: %d\n", ast_channel_dialed(chan)->transit_network_select);
2333  ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(ast_channel_dialed(chan)->number.str, "unknown"));
2334  ast_agi_send(fd, chan, "agi_rdnis: %s\n",
2335  S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "unknown"));
2336 
2337  /* Context information */
2338  ast_agi_send(fd, chan, "agi_context: %s\n", ast_channel_context(chan));
2339  ast_agi_send(fd, chan, "agi_extension: %s\n", ast_channel_exten(chan));
2340  ast_agi_send(fd, chan, "agi_priority: %d\n", ast_channel_priority(chan));
2341  ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
2342 
2343  /* User information */
2344  ast_agi_send(fd, chan, "agi_accountcode: %s\n", ast_channel_accountcode(chan) ? ast_channel_accountcode(chan) : "");
2345  ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
2346 
2347  /* Send any parameters to the fastagi server that have been passed via the agi application */
2348  /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
2349  for(count = 1; count < argc; count++)
2350  ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
2351 
2352  /* End with empty return */
2353  ast_agi_send(fd, chan, "\n");
2354 }
2355 
2356 static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2357 {
2358  int res = 0;
2359 
2360  /* Answer the channel */
2361  if (ast_channel_state(chan) != AST_STATE_UP)
2362  res = ast_answer(chan);
2363 
2364  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2365  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2366 }
2367 
2368 static int handle_asyncagi_break(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2369 {
2370  ast_agi_send(agi->fd, chan, "200 result=0\n");
2371  return ASYNC_AGI_BREAK;
2372 }
2373 
2374 static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2375 {
2376  int res, to;
2377 
2378  if (argc != 4)
2379  return RESULT_SHOWUSAGE;
2380  if (sscanf(argv[3], "%30d", &to) != 1)
2381  return RESULT_SHOWUSAGE;
2382  res = ast_waitfordigit_full(chan, to, NULL, agi->audio, agi->ctrl);
2383  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2384  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2385 }
2386 
2387 static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2388 {
2389  int res;
2390 
2391  if (argc != 3)
2392  return RESULT_SHOWUSAGE;
2393 
2394  /* At the moment, the parser (perhaps broken) returns with
2395  the last argument PLUS the newline at the end of the input
2396  buffer. This probably needs to be fixed, but I wont do that
2397  because other stuff may break as a result. The right way
2398  would probably be to strip off the trailing newline before
2399  parsing, then here, add a newline at the end of the string
2400  before sending it to ast_sendtext --DUDE */
2401  res = ast_sendtext(chan, argv[2]);
2402  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2403  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2404 }
2405 
2406 static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2407 {
2408  int res;
2409 
2410  if (argc != 3)
2411  return RESULT_SHOWUSAGE;
2412 
2413  res = ast_recvchar(chan,atoi(argv[2]));
2414  if (res == 0) {
2415  ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
2416  return RESULT_SUCCESS;
2417  }
2418  if (res > 0) {
2419  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2420  return RESULT_SUCCESS;
2421  }
2422  ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
2423  return RESULT_FAILURE;
2424 }
2425 
2426 static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2427 {
2428  char *buf;
2429 
2430  if (argc != 3)
2431  return RESULT_SHOWUSAGE;
2432 
2433  buf = ast_recvtext(chan, atoi(argv[2]));
2434  if (buf) {
2435  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
2436  ast_free(buf);
2437  } else {
2438  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2439  }
2440  return RESULT_SUCCESS;
2441 }
2442 
2443 static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2444 {
2445  int res, x;
2446 
2447  if (argc != 3)
2448  return RESULT_SHOWUSAGE;
2449 
2450  if (!strncasecmp(argv[2],"on",2)) {
2451  x = 1;
2452  } else {
2453  x = 0;
2454  }
2455  if (!strncasecmp(argv[2],"mate",4)) {
2456  x = 2;
2457  }
2458  if (!strncasecmp(argv[2],"tdd",3)) {
2459  x = 1;
2460  }
2461  res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
2462  if (res) {
2463  /* Set channel option failed */
2464  ast_agi_send(agi->fd, chan, "200 result=0\n");
2465  } else {
2466  ast_agi_send(agi->fd, chan, "200 result=1\n");
2467  }
2468  return RESULT_SUCCESS;
2469 }
2470 
2471 static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2472 {
2473  int res;
2474 
2475  if (argc != 3) {
2476  return RESULT_SHOWUSAGE;
2477  }
2478 
2479  res = ast_send_image(chan, argv[2]);
2480  if (!ast_check_hangup(chan)) {
2481  res = 0;
2482  }
2483  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2484  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2485 }
2486 
2487 static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2488 {
2489  int res = 0, skipms = 3000;
2490  const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
2491  char stopkeybuf[2];
2492  long offsetms = 0;
2493  char offsetbuf[20];
2494 
2495  if (argc < 5 || argc > 10) {
2496  return RESULT_SHOWUSAGE;
2497  }
2498 
2499  if (!ast_strlen_zero(argv[4])) {
2500  stop = argv[4];
2501  }
2502 
2503  if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) {
2504  return RESULT_SHOWUSAGE;
2505  }
2506 
2507  if (argc > 6 && !ast_strlen_zero(argv[6])) {
2508  fwd = argv[6];
2509  }
2510 
2511  if (argc > 7 && !ast_strlen_zero(argv[7])) {
2512  rev = argv[7];
2513  }
2514 
2515  if (argc > 8 && !ast_strlen_zero(argv[8])) {
2516  suspend = argv[8];
2517  }
2518 
2519  if (argc > 9 && (sscanf(argv[9], "%30ld", &offsetms) != 1)) {
2520  return RESULT_SHOWUSAGE;
2521  }
2522 
2523  res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, &offsetms);
2524 
2525  /* If we stopped on one of our stop keys, return 0 */
2526  if (res > 0 && stop && strchr(stop, res)) {
2527  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
2528  snprintf(stopkeybuf, sizeof(stopkeybuf), "%c", res);
2529  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTOPKEY", stopkeybuf);
2530  } else if (res > 0 && res == AST_CONTROL_STREAM_STOP) {
2531  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "REMOTESTOPPED");
2532  res = 0;
2533  } else {
2534  if (res < 0) {
2535  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "ERROR");
2536  } else {
2537  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
2538  }
2539  }
2540 
2541  snprintf(offsetbuf, sizeof(offsetbuf), "%ld", offsetms);
2542  pbx_builtin_setvar_helper(chan, "CPLAYBACKOFFSET", offsetbuf);
2543 
2544  ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, offsetms);
2545 
2546  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2547 }
2548 
2549 static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2550 {
2551  int res;
2552  struct ast_filestream *fs, *vfs;
2553  long sample_offset = 0, max_length;
2554  const char *edigits = "";
2555 
2556  if (argc < 4 || argc > 5) {
2557  return RESULT_SHOWUSAGE;
2558  }
2559 
2560  if (argv[3]) {
2561  edigits = argv[3];
2562  }
2563 
2564  if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1)) {
2565  return RESULT_SHOWUSAGE;
2566  }
2567 
2568  if (!(fs = ast_openstream(chan, argv[2], ast_channel_language(chan)))) {
2569  ast_agi_send(agi->fd, chan, "200 result=-1 endpos=%ld\n", sample_offset);
2570  return RESULT_FAILURE;
2571  }
2572 
2573  if ((vfs = ast_openvstream(chan, argv[2], ast_channel_language(chan)))) {
2574  ast_debug(1, "Ooh, found a video stream, too\n");
2575  }
2576  ast_verb(3, "<%s> Playing '%s.%s' (escape_digits=%s) (sample_offset %ld) (language '%s')\n",
2578  edigits, sample_offset, S_OR(ast_channel_language(chan), "default"));
2579 
2580  ast_seekstream(fs, 0, SEEK_END);
2581  max_length = ast_tellstream(fs);
2582  ast_seekstream(fs, sample_offset, SEEK_SET);
2583  res = ast_applystream(chan, fs);
2584  if (vfs) {
2585  ast_applystream(chan, vfs);
2586  }
2587  ast_playstream(fs);
2588  if (vfs) {
2590  }
2591 
2592  res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
2593  /* this is to check for if ast_waitstream closed the stream, we probably are at
2594  * the end of the stream, return that amount, else check for the amount */
2595  sample_offset = (ast_channel_stream(chan)) ? ast_tellstream(fs) : max_length;
2596  ast_stopstream(chan);
2597  if (res == 1) {
2598  /* Stop this command, don't print a result line, as there is a new command */
2599  return RESULT_SUCCESS;
2600  }
2601  ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
2602  pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", res ? "FAILED" : "SUCCESS");
2603 
2604  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2605 }
2606 
2607 /*! \brief get option - really similar to the handle_streamfile, but with a timeout */
2608 static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2609 {
2610  int res;
2611  struct ast_filestream *fs, *vfs;
2612  long sample_offset = 0, max_length;
2613  int timeout = 0;
2614  const char *edigits = "";
2615 
2616  if ( argc < 4 || argc > 5 )
2617  return RESULT_SHOWUSAGE;
2618 
2619  if ( argv[3] )
2620  edigits = argv[3];
2621 
2622  if ( argc == 5 )
2623  timeout = atoi(argv[4]);
2624  else if (ast_channel_pbx(chan)->dtimeoutms) {
2625  /* by default dtimeout is set to 5sec */
2626  timeout = ast_channel_pbx(chan)->dtimeoutms; /* in msec */
2627  }
2628 
2629  if (!(fs = ast_openstream(chan, argv[2], ast_channel_language(chan)))) {
2630  ast_agi_send(agi->fd, chan, "200 result=-1 endpos=%ld\n", sample_offset);
2631  ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
2632  return RESULT_FAILURE;
2633  }
2634 
2635  if ((vfs = ast_openvstream(chan, argv[2], ast_channel_language(chan))))
2636  ast_debug(1, "Ooh, found a video stream, too\n");
2637 
2638  ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
2639 
2640  ast_seekstream(fs, 0, SEEK_END);
2641  max_length = ast_tellstream(fs);
2642  ast_seekstream(fs, sample_offset, SEEK_SET);
2643  res = ast_applystream(chan, fs);
2644  if (vfs)
2645  ast_applystream(chan, vfs);
2646  ast_playstream(fs);
2647  if (vfs)
2649 
2650  res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
2651  /* this is to check for if ast_waitstream closed the stream, we probably are at
2652  * the end of the stream, return that amount, else check for the amount */
2653  sample_offset = (ast_channel_stream(chan))?ast_tellstream(fs):max_length;
2654  ast_stopstream(chan);
2655  if (res == 1) {
2656  /* Stop this command, don't print a result line, as there is a new command */
2657  return RESULT_SUCCESS;
2658  }
2659 
2660  /* If the user didnt press a key, wait for digitTimeout*/
2661  if (res == 0 ) {
2662  res = ast_waitfordigit_full(chan, timeout, NULL, agi->audio, agi->ctrl);
2663  /* Make sure the new result is in the escape digits of the GET OPTION */
2664  if ( !strchr(edigits,res) )
2665  res=0;
2666  }
2667 
2668  ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
2669  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2670 }
2671 
2672 
2673 
2674 
2675 /*! \brief Say number in various language syntaxes */
2676 /* While waiting, we're sending a NULL. */
2677 static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2678 {
2679  int res, num;
2680 
2681  if (argc < 4 || argc > 5)
2682  return RESULT_SHOWUSAGE;
2683  if (sscanf(argv[2], "%30d", &num) != 1)
2684  return RESULT_SHOWUSAGE;
2685  res = ast_say_number_full(chan, num, argv[3], ast_channel_language(chan), argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
2686  if (res == 1)
2687  return RESULT_SUCCESS;
2688  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2689  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2690 }
2691 
2692 static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2693 {
2694  int res, num;
2695 
2696  if (argc != 4)
2697  return RESULT_SHOWUSAGE;
2698  if (sscanf(argv[2], "%30d", &num) != 1)
2699  return RESULT_SHOWUSAGE;
2700 
2701  res = ast_say_digit_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl);
2702  if (res == 1) /* New command */
2703  return RESULT_SUCCESS;
2704  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2705  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2706 }
2707 
2708 static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2709 {
2710  int res;
2711  int sensitivity = AST_SAY_CASE_NONE;
2712 
2713  if (argc < 4 || argc > 5) {
2714  return RESULT_SHOWUSAGE;
2715  }
2716 
2717  if (argc > 4) {
2718  switch (argv[4][0]) {
2719  case 'a':
2720  case 'A':
2721  sensitivity = AST_SAY_CASE_ALL;
2722  break;
2723  case 'l':
2724  case 'L':
2725  sensitivity = AST_SAY_CASE_LOWER;
2726  break;
2727  case 'n':
2728  case 'N':
2729  sensitivity = AST_SAY_CASE_NONE;
2730  break;
2731  case 'u':
2732  case 'U':
2733  sensitivity = AST_SAY_CASE_UPPER;
2734  break;
2735  case '\0':
2736  break;
2737  default:
2738  return RESULT_SHOWUSAGE;
2739  }
2740  }
2741  res = ast_say_character_str_full(chan, argv[2], argv[3], ast_channel_language(chan), sensitivity, agi->audio, agi->ctrl);
2742  if (res == 1) /* New command */
2743  return RESULT_SUCCESS;
2744  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2745  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2746 }
2747 
2748 static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2749 {
2750  int res, num;
2751 
2752  if (argc != 4)
2753  return RESULT_SHOWUSAGE;
2754  if (sscanf(argv[2], "%30d", &num) != 1)
2755  return RESULT_SHOWUSAGE;
2756  res = ast_say_date(chan, num, argv[3], ast_channel_language(chan));
2757  if (res == 1)
2758  return RESULT_SUCCESS;
2759  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2760  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2761 }
2762 
2763 static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2764 {
2765  int res, num;
2766 
2767  if (argc != 4)
2768  return RESULT_SHOWUSAGE;
2769  if (sscanf(argv[2], "%30d", &num) != 1)
2770  return RESULT_SHOWUSAGE;
2771  res = ast_say_time(chan, num, argv[3], ast_channel_language(chan));
2772  if (res == 1)
2773  return RESULT_SUCCESS;
2774  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2775  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2776 }
2777 
2778 static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2779 {
2780  int res = 0;
2781  time_t unixtime;
2782  const char *format, *zone = NULL;
2783 
2784  if (argc < 4)
2785  return RESULT_SHOWUSAGE;
2786 
2787  if (argc > 4) {
2788  format = argv[4];
2789  } else {
2790  /* XXX this doesn't belong here, but in the 'say' module */
2791  if (!strcasecmp(ast_channel_language(chan), "de")) {
2792  format = "A dBY HMS";
2793  } else {
2794  format = "ABdY 'digits/at' IMp";
2795  }
2796  }
2797 
2798  if (argc > 5 && !ast_strlen_zero(argv[5]))
2799  zone = argv[5];
2800 
2801  if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
2802  return RESULT_SHOWUSAGE;
2803 
2804  res = ast_say_date_with_format(chan, unixtime, argv[3], ast_channel_language(chan), format, zone);
2805  if (res == 1)
2806  return RESULT_SUCCESS;
2807 
2808  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2809  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2810 }
2811 
2812 static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2813 {
2814  int res;
2815 
2816  if (argc != 4)
2817  return RESULT_SHOWUSAGE;
2818 
2819  res = ast_say_phonetic_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl);
2820  if (res == 1) /* New command */
2821  return RESULT_SUCCESS;
2822  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2823  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2824 }
2825 
2826 static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2827 {
2828  int res, max, timeout;
2829  char data[1024];
2830 
2831  if (argc < 3)
2832  return RESULT_SHOWUSAGE;
2833  if (argc >= 4)
2834  timeout = atoi(argv[3]);
2835  else
2836  timeout = 0;
2837  if (argc >= 5)
2838  max = atoi(argv[4]);
2839  else
2840  max = 1024;
2841  res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
2842  if (res == 2) /* New command */
2843  return RESULT_SUCCESS;
2844  else if (res == 1)
2845  ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
2846  else if (res < 0 )
2847  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2848  else
2849  ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
2850  return RESULT_SUCCESS;
2851 }
2852 
2853 static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2854 {
2855 
2856  if (argc != 3)
2857  return RESULT_SHOWUSAGE;
2858  ast_channel_context_set(chan, argv[2]);
2859  ast_agi_send(agi->fd, chan, "200 result=0\n");
2860  return RESULT_SUCCESS;
2861 }
2862 
2863 static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2864 {
2865  if (argc != 3)
2866  return RESULT_SHOWUSAGE;
2867  ast_channel_exten_set(chan, argv[2]);
2868  ast_agi_send(agi->fd, chan, "200 result=0\n");
2869  return RESULT_SUCCESS;
2870 }
2871 
2872 static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2873 {
2874  int pri;
2875 
2876  if (argc != 3)
2877  return RESULT_SHOWUSAGE;
2878 
2879  if (sscanf(argv[2], "%30d", &pri) != 1) {
2880  pri = ast_findlabel_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), argv[2],
2881  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
2882  if (pri < 1)
2883  return RESULT_SHOWUSAGE;
2884  }
2885 
2886  ast_explicit_goto(chan, NULL, NULL, pri);
2887  ast_agi_send(agi->fd, chan, "200 result=0\n");
2888  return RESULT_SUCCESS;
2889 }
2890 
2891 static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
2892 {
2893  struct ast_filestream *fs;
2894  struct ast_frame *f;
2895  struct timeval start;
2896  long sample_offset = 0;
2897  int res = 0;
2898  int ms;
2899 
2900  struct ast_dsp *sildet=NULL; /* silence detector dsp */
2901  int totalsilence = 0;
2902  int dspsilence = 0;
2903  int silence = 0; /* amount of silence to allow */
2904  int gotsilence = 0; /* did we timeout for silence? */
2905  char *silencestr = NULL;
2906  RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
2907 
2908  /* XXX EAGI FIXME XXX */
2909 
2910  if (argc < 6)
2911  return RESULT_SHOWUSAGE;
2912  if (sscanf(argv[5], "%30d", &ms) != 1)
2913  return RESULT_SHOWUSAGE;
2914 
2915  if (argc > 6)
2916  silencestr = strchr(argv[6],'s');
2917  if ((argc > 7) && (!silencestr))
2918  silencestr = strchr(argv[7],'s');
2919  if ((argc > 8) && (!silencestr))
2920  silencestr = strchr(argv[8],'s');
2921 
2922  if (silencestr) {
2923  if (strlen(silencestr) > 2) {
2924  if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
2925  silencestr++;
2926  silencestr++;
2927  if (silencestr)
2928  silence = atoi(silencestr);
2929  if (silence > 0)
2930  silence *= 1000;
2931  }
2932  }
2933  }
2934 
2935  if (silence > 0) {
2936  rfmt = ao2_bump(ast_channel_readformat(chan));
2937  res = ast_set_read_format(chan, ast_format_slin);
2938  if (res < 0) {
2939  ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
2940  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2941  return RESULT_FAILURE;
2942  }
2943  sildet = ast_dsp_new();
2944  if (!sildet) {
2945  ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
2946  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2947  return RESULT_FAILURE;
2948  }
2950  }
2951 
2952  /* backward compatibility, if no offset given, arg[6] would have been
2953  * caught below and taken to be a beep, else if it is a digit then it is a
2954  * offset */
2955  if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
2956  res = ast_streamfile(chan, "beep", ast_channel_language(chan));
2957 
2958  if ((argc > 7) && (!strchr(argv[7], '=')))
2959  res = ast_streamfile(chan, "beep", ast_channel_language(chan));
2960 
2961  if (!res)
2962  res = ast_waitstream(chan, argv[4]);
2963  if (res) {
2964  ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
2965  } else {
2966  fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE);
2967  if (!fs) {
2968  res = -1;
2969  ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res);
2970  if (sildet)
2971  ast_dsp_free(sildet);
2972  return RESULT_FAILURE;
2973  }
2974 
2975  /* Request a video update */
2977 
2978  ast_channel_stream_set(chan, fs);
2979  ast_applystream(chan,fs);
2980  /* really should have checks */
2981  ast_seekstream(fs, sample_offset, SEEK_SET);
2982  ast_truncstream(fs);
2983 
2984  start = ast_tvnow();
2985  while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
2986  res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
2987  if (res < 0) {
2988  ast_closestream(fs);
2989  ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
2990  if (sildet)
2991  ast_dsp_free(sildet);
2992  return RESULT_FAILURE;
2993  }
2994  f = ast_read(chan);
2995  if (!f) {
2996  ast_closestream(fs);
2997  ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
2998  if (sildet)
2999  ast_dsp_free(sildet);
3000  return RESULT_FAILURE;
3001  }
3002  switch(f->frametype) {
3003  case AST_FRAME_DTMF:
3004  if (strchr(argv[4], f->subclass.integer)) {
3005  /* This is an interrupting character, so rewind to chop off any small
3006  amount of DTMF that may have been recorded
3007  */
3008  ast_stream_rewind(fs, 200);
3009  ast_truncstream(fs);
3010  sample_offset = ast_tellstream(fs);
3011  ast_closestream(fs);
3012  ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass.integer, sample_offset);
3013  ast_frfree(f);
3014  if (sildet)
3015  ast_dsp_free(sildet);
3016  return RESULT_SUCCESS;
3017  }
3018  break;
3019  case AST_FRAME_VOICE:
3020  ast_writestream(fs, f);
3021  /* this is a safe place to check progress since we know that fs
3022  * is valid after a write, and it will then have our current
3023  * location */
3024  sample_offset = ast_tellstream(fs);
3025  if (silence > 0) {
3026  dspsilence = 0;
3027  ast_dsp_silence(sildet, f, &dspsilence);
3028  if (dspsilence) {
3029  totalsilence = dspsilence;
3030  } else {
3031  totalsilence = 0;
3032  }
3033  if (totalsilence > silence) {
3034  /* Ended happily with silence */
3035  gotsilence = 1;
3036  break;
3037  }
3038  }
3039  break;
3040  case AST_FRAME_VIDEO:
3041  ast_writestream(fs, f);
3042  default:
3043  /* Ignore all other frames */
3044  break;
3045  }
3046  ast_frfree(f);
3047  if (gotsilence)
3048  break;
3049  }
3050 
3051  if (gotsilence) {
3052  ast_stream_rewind(fs, silence-1000);
3053  ast_truncstream(fs);
3054  sample_offset = ast_tellstream(fs);
3055  }
3056  ast_closestream(fs);
3057  ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
3058  }
3059 
3060  if (silence > 0) {
3061  res = ast_set_read_format(chan, rfmt);
3062  if (res)
3063  ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
3064  ast_dsp_free(sildet);
3065  }
3066 
3067  return RESULT_SUCCESS;
3068 }
3069 
3070 static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3071 {
3072  double timeout;
3073  struct timeval whentohangup = { 0, 0 };
3074 
3075  if (argc != 3)
3076  return RESULT_SHOWUSAGE;
3077  if (sscanf(argv[2], "%30lf", &timeout) != 1)
3078  return RESULT_SHOWUSAGE;
3079  if (timeout < 0)
3080  timeout = 0;
3081  if (timeout) {
3082  whentohangup.tv_sec = timeout;
3083  whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
3084  }
3085  ast_channel_lock(chan);
3086  ast_channel_setwhentohangup_tv(chan, whentohangup);
3087  ast_channel_unlock(chan);
3088  ast_agi_send(agi->fd, chan, "200 result=0\n");
3089  return RESULT_SUCCESS;
3090 }
3091 
3092 static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3093 {
3094  struct ast_channel *c;
3095 
3096  if (argc == 1) {
3097  /* no argument: hangup the current channel */
3098  ast_set_hangupsource(chan, "dialplan/agi", 0);
3100  ast_agi_send(agi->fd, chan, "200 result=1\n");
3101  return RESULT_SUCCESS;
3102  } else if (argc == 2) {
3103  /* one argument: look for info on the specified channel */
3104  if ((c = ast_channel_get_by_name(argv[1]))) {
3105  /* we have a matching channel */
3106  ast_set_hangupsource(c, "dialplan/agi", 0);
3108  c = ast_channel_unref(c);
3109  ast_agi_send(agi->fd, chan, "200 result=1\n");
3110  return RESULT_SUCCESS;
3111  }
3112  /* if we get this far no channel name matched the argument given */
3113  ast_agi_send(agi->fd, chan, "200 result=-1\n");
3114  return RESULT_SUCCESS;
3115  } else {
3116  return RESULT_SHOWUSAGE;
3117  }
3118 }
3119 
3120 static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3121 {
3122  int res, workaround;
3123  struct ast_app *app_to_exec;
3124 
3125  if (argc < 2)
3126  return RESULT_SHOWUSAGE;
3127 
3128  ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : "");
3129 
3130  if ((app_to_exec = pbx_findapp(argv[1]))) {
3131  ast_channel_lock(chan);
3132  if (!(workaround = ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_WORKAROUNDS))) {
3134  }
3135  ast_channel_unlock(chan);
3136  res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]);
3137  if (!workaround) {
3139  }
3140  } else {
3141  ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
3142  res = -2;
3143  }
3144  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
3145 
3146  /* Even though this is wrong, users are depending upon this result. */
3147  return res;
3148 }
3149 
3150 static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3151 {
3152  char tmp[256]="";
3153  char *l = NULL, *n = NULL;
3154 
3155  if (argv[2]) {
3156  ast_copy_string(tmp, argv[2], sizeof(tmp));
3157  ast_callerid_parse(tmp, &n, &l);
3158  if (l)
3160  else
3161  l = "";
3162  if (!n)
3163  n = "";
3164  ast_set_callerid(chan, l, n, NULL);
3165  }
3166 
3167  ast_agi_send(agi->fd, chan, "200 result=1\n");
3168  return RESULT_SUCCESS;
3169 }
3170 
3171 static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3172 {
3173  if (argc == 2) {
3174  /* no argument: supply info on the current channel */
3175  ast_agi_send(agi->fd, chan, "200 result=%u\n", ast_channel_state(chan));
3176  return RESULT_SUCCESS;
3177  } else if (argc == 3) {
3178  struct ast_channel_snapshot *snapshot;
3179 
3180  /* one argument: look for info on the specified channel */
3181  snapshot = ast_channel_snapshot_get_latest_by_name(argv[2]);
3182  if (snapshot) {
3183  ast_agi_send(agi->fd, chan, "200 result=%u\n", snapshot->state);
3184  ao2_ref(snapshot, -1);
3185  return RESULT_SUCCESS;
3186  }
3187  /* if we get this far no channel name matched the argument given */
3188  ast_agi_send(agi->fd, chan, "200 result=-1\n");
3189  return RESULT_SUCCESS;
3190  } else {
3191  return RESULT_SHOWUSAGE;
3192  }
3193 }
3194 
3195 static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3196 {
3197  if (argc != 4) {
3198  return RESULT_SHOWUSAGE;
3199  }
3200 
3201  if (argv[3])
3202  pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
3203 
3204  ast_agi_send(agi->fd, chan, "200 result=1\n");
3205  return RESULT_SUCCESS;
3206 }
3207 
3208 static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3209 {
3210  char *ret;
3211  char tempstr[1024] = "";
3212 
3213  if (argc != 3)
3214  return RESULT_SHOWUSAGE;
3215 
3216  /* check if we want to execute an ast_custom_function */
3217  if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
3218  ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
3219  } else {
3220  pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
3221  }
3222 
3223  if (ret)
3224  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
3225  else
3226  ast_agi_send(agi->fd, chan, "200 result=0\n");
3227 
3228  return RESULT_SUCCESS;
3229 }
3230 
3231 static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3232 {
3233  struct ast_channel *chan2 = NULL;
3234 
3235  if (argc != 4 && argc != 5) {
3236  return RESULT_SHOWUSAGE;
3237  }
3238 
3239  if (argc == 5) {
3240  chan2 = ast_channel_get_by_name(argv[4]);
3241  } else {
3242  chan2 = ast_channel_ref(chan);
3243  }
3244 
3245  if (chan2) {
3246  struct ast_str *str = ast_str_create(16);
3247  if (!str) {
3248  ast_agi_send(agi->fd, chan, "200 result=0\n");
3249  return RESULT_SUCCESS;
3250  }
3251  ast_str_substitute_variables(&str, 0, chan2, argv[3]);
3252  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(str));
3253  ast_free(str);
3254  } else {
3255  ast_agi_send(agi->fd, chan, "200 result=0\n");
3256  }
3257 
3258  if (chan2) {
3259  chan2 = ast_channel_unref(chan2);
3260  }
3261 
3262  return RESULT_SUCCESS;
3263 }
3264 
3265 static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3266 {
3267  int level = 0;
3268 
3269  if (argc < 2)
3270  return RESULT_SHOWUSAGE;
3271 
3272  if (argv[2])
3273  sscanf(argv[2], "%30d", &level);
3274 
3275  ast_verb(level, "%s: %s\n", ast_channel_data(chan), argv[1]);
3276 
3277  ast_agi_send(agi->fd, chan, "200 result=1\n");
3278 
3279  return RESULT_SUCCESS;
3280 }
3281 
3282 static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3283 {
3284  int res;
3285  struct ast_str *buf;
3286 
3287  if (argc != 4)
3288  return RESULT_SHOWUSAGE;
3289 
3290  if (!(buf = ast_str_create(16))) {
3291  ast_agi_send(agi->fd, chan, "200 result=-1\n");
3292  return RESULT_SUCCESS;
3293  }
3294 
3295  do {
3296  res = ast_db_get(argv[2], argv[3], ast_str_buffer(buf), ast_str_size(buf));
3298  if (ast_str_strlen(buf) < ast_str_size(buf) - 1) {
3299  break;
3300  }
3301  if (ast_str_make_space(&buf, ast_str_size(buf) * 2)) {
3302  break;
3303  }
3304  } while (1);
3305 
3306  if (res)
3307  ast_agi_send(agi->fd, chan, "200 result=0\n");
3308  else
3309  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(buf));
3310 
3311  ast_free(buf);
3312  return RESULT_SUCCESS;
3313 }
3314 
3315 static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3316 {
3317  int res;
3318 
3319  if (argc != 5)
3320  return RESULT_SHOWUSAGE;
3321  res = ast_db_put(argv[2], argv[3], argv[4]);
3322  ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
3323  return RESULT_SUCCESS;
3324 }
3325 
3326 static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3327 {
3328  int res;
3329 
3330  if (argc != 4)
3331  return RESULT_SHOWUSAGE;
3332  res = ast_db_del(argv[2], argv[3]);
3333  ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
3334  return RESULT_SUCCESS;
3335 }
3336 
3337 static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3338 {
3339  int num_deleted;
3340 
3341  if ((argc < 3) || (argc > 4)) {
3342  return RESULT_SHOWUSAGE;
3343  }
3344  if (argc == 4) {
3345  num_deleted = ast_db_deltree(argv[2], argv[3]);
3346  } else {
3347  num_deleted = ast_db_deltree(argv[2], NULL);
3348  }
3349 
3350  ast_agi_send(agi->fd, chan, "200 result=%c\n", num_deleted > 0 ? '0' : '1');
3351  return RESULT_SUCCESS;
3352 }
3353 
3354 static char *handle_cli_agi_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3355 {
3356  switch (cmd) {
3357  case CLI_INIT:
3358  e->command = "agi set debug [on|off]";
3359  e->usage =
3360  "Usage: agi set debug [on|off]\n"
3361  " Enables/disables dumping of AGI transactions for\n"
3362  " debugging purposes.\n";
3363  return NULL;
3364 
3365  case CLI_GENERATE:
3366  return NULL;
3367  }
3368 
3369  if (a->argc != e->args)
3370  return CLI_SHOWUSAGE;
3371 
3372  if (strncasecmp(a->argv[3], "off", 3) == 0) {
3373  agidebug = 0;
3374  } else if (strncasecmp(a->argv[3], "on", 2) == 0) {
3375  agidebug = 1;
3376  } else {
3377  return CLI_SHOWUSAGE;
3378  }
3379  ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis");
3380  return CLI_SUCCESS;
3381 }
3382 
3383 static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char * const argv[])
3384 {
3385  ast_agi_send(agi->fd, chan, "200 result=0\n");
3386  return RESULT_SUCCESS;
3387 }
3388 
3389 static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3390 {
3391  if (argc < 3) {
3392  return RESULT_SHOWUSAGE;
3393  }
3394  if (!strncasecmp(argv[2], "on", 2))
3395  ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
3396  else if (!strncasecmp(argv[2], "off", 3))
3397  ast_moh_stop(chan);
3398  ast_agi_send(agi->fd, chan, "200 result=0\n");
3399  return RESULT_SUCCESS;
3400 }
3401 
3402 static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3403 {
3404  struct ast_format_cap *cap;
3405 
3406  /* If a structure already exists, return an error */
3407  if (agi->speech) {
3408  ast_agi_send(agi->fd, chan, "200 result=0\n");
3409  return RESULT_SUCCESS;
3410  }
3411 
3413  return RESULT_FAILURE;
3414  }
3416  if ((agi->speech = ast_speech_new(argv[2], cap))) {
3417  ast_agi_send(agi->fd, chan, "200 result=1\n");
3418  } else {
3419  ast_agi_send(agi->fd, chan, "200 result=0\n");
3420  }
3421  ao2_ref(cap, -1);
3422 
3423  return RESULT_SUCCESS;
3424 }
3425 
3426 static int handle_speechset(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3427 {
3428  /* Check for minimum arguments */
3429  if (argc != 4)
3430  return RESULT_SHOWUSAGE;
3431 
3432  /* Check to make sure speech structure exists */
3433  if (!agi->speech) {
3434  ast_agi_send(agi->fd, chan, "200 result=0\n");
3435  return RESULT_SUCCESS;
3436  }
3437 
3438  ast_speech_change(agi->speech, argv[2], argv[3]);
3439  ast_agi_send(agi->fd, chan, "200 result=1\n");
3440 
3441  return RESULT_SUCCESS;
3442 }
3443 
3444 static int handle_speechdestroy(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3445 {
3446  if (agi->speech) {
3447  ast_speech_destroy(agi->speech);
3448  agi->speech = NULL;
3449  ast_agi_send(agi->fd, chan, "200 result=1\n");
3450  } else {
3451  ast_agi_send(agi->fd, chan, "200 result=0\n");
3452  }
3453 
3454  return RESULT_SUCCESS;
3455 }
3456 
3457 static int handle_speechloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3458 {
3459  if (argc != 5)
3460  return RESULT_SHOWUSAGE;
3461 
3462  if (!agi->speech) {
3463  ast_agi_send(agi->fd, chan, "200 result=0\n");
3464  return RESULT_SUCCESS;
3465  }
3466 
3467  if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
3468  ast_agi_send(agi->fd, chan, "200 result=0\n");
3469  else
3470  ast_agi_send(agi->fd, chan, "200 result=1\n");
3471 
3472  return RESULT_SUCCESS;
3473 }
3474 
3475 static int handle_speechunloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3476 {
3477  if (argc != 4)
3478  return RESULT_SHOWUSAGE;
3479 
3480  if (!agi->speech) {
3481  ast_agi_send(agi->fd, chan, "200 result=0\n");
3482  return RESULT_SUCCESS;
3483  }
3484 
3485  if (ast_speech_grammar_unload(agi->speech, argv[3]))
3486  ast_agi_send(agi->fd, chan, "200 result=0\n");
3487  else
3488  ast_agi_send(agi->fd, chan, "200 result=1\n");
3489 
3490  return RESULT_SUCCESS;
3491 }
3492 
3493 static int handle_speechactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3494 {
3495  if (argc != 4)
3496  return RESULT_SHOWUSAGE;
3497 
3498  if (!agi->speech) {
3499  ast_agi_send(agi->fd, chan, "200 result=0\n");
3500  return RESULT_SUCCESS;
3501  }
3502 
3503  if (ast_speech_grammar_activate(agi->speech, argv[3]))
3504  ast_agi_send(agi->fd, chan, "200 result=0\n");
3505  else
3506  ast_agi_send(agi->fd, chan, "200 result=1\n");
3507 
3508  return RESULT_SUCCESS;
3509 }
3510 
3511 static int handle_speechdeactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3512 {
3513  if (argc != 4)
3514  return RESULT_SHOWUSAGE;
3515 
3516  if (!agi->speech) {
3517  ast_agi_send(agi->fd, chan, "200 result=0\n");
3518  return RESULT_SUCCESS;
3519  }
3520 
3521  if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
3522  ast_agi_send(agi->fd, chan, "200 result=0\n");
3523  else
3524  ast_agi_send(agi->fd, chan, "200 result=1\n");
3525 
3526  return RESULT_SUCCESS;
3527 }
3528 
3529 static int speech_streamfile(struct ast_channel *chan, const char *filename, const char *preflang, int offset)
3530 {
3531  struct ast_filestream *fs = NULL;
3532 
3533  if (!(fs = ast_openstream(chan, filename, preflang)))
3534  return -1;
3535 
3536  if (offset)
3537  ast_seekstream(fs, offset, SEEK_SET);
3538 
3539  if (ast_applystream(chan, fs))
3540  return -1;
3541 
3542  if (ast_playstream(fs))
3543  return -1;
3544 
3545  return 0;
3546 }
3547 
3548 static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
3549 {
3550  struct ast_speech *speech = agi->speech;
3551  const char *prompt;
3552  char dtmf = 0, tmp[4096] = "", *buf = tmp;
3553  int timeout = 0, offset = 0, res = 0, i = 0;
3554  long current_offset = 0;
3555  const char *reason = NULL;
3556  struct ast_frame *fr = NULL;
3557  struct ast_speech_result *result = NULL;
3558  size_t left = sizeof(tmp);
3559  time_t start = 0, current;
3560 
3561  if (argc < 4)
3562  return RESULT_SHOWUSAGE;
3563 
3564  if (!speech) {
3565  ast_agi_send(agi->fd, chan, "200 result=0\n");
3566  return RESULT_SUCCESS;
3567  }
3568 
3569  prompt = argv[2];
3570  timeout = atoi(argv[3]);
3571 
3572  /* If offset is specified then convert from text to integer */
3573  if (argc == 5)
3574  offset = atoi(argv[4]);
3575 
3576  /* We want frames coming in signed linear */
3577  if (ast_set_read_format(chan, ast_format_slin)) {
3578  ast_agi_send(agi->fd, chan, "200 result=0\n");
3579  return RESULT_SUCCESS;
3580  }
3581 
3582  /* Setup speech structure */
3583  if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
3585  ast_speech_start(speech);
3586  }
3587 
3588  /* Start playing prompt */
3589  speech_streamfile(chan, prompt, ast_channel_language(chan), offset);
3590 
3591  /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */
3592  while (ast_strlen_zero(reason)) {
3593  /* Run scheduled items */
3595 
3596  /* See maximum time of waiting */
3597  if ((res = ast_sched_wait(ast_channel_sched(chan))) < 0)
3598  res = 1000;
3599 
3600  /* Wait for frame */
3601  if (ast_waitfor(chan, res) > 0) {
3602  if (!(fr = ast_read(chan))) {
3603  reason = "hangup";
3604  break;
3605  }
3606  }
3607 
3608  /* Perform timeout check */
3609  if ((timeout > 0) && (start > 0)) {
3610  time(&current);
3611  if ((current - start) >= timeout) {
3612  reason = "timeout";
3613  if (fr)
3614  ast_frfree(fr);
3615  break;
3616  }
3617  }
3618 
3619  /* Check the speech structure for any changes */
3620  ast_mutex_lock(&speech->lock);
3621 
3622  /* See if we need to quiet the audio stream playback */
3623  if (ast_test_flag(speech, AST_SPEECH_QUIET) && ast_channel_stream(chan)) {
3624  current_offset = ast_tellstream(ast_channel_stream(chan));
3625  ast_stopstream(chan);
3627  }
3628 
3629  /* Check each state */
3630  switch (speech->state) {
3632  /* If the stream is done, start timeout calculation */
3633  if ((timeout > 0) && start == 0 && ((!ast_channel_stream(chan)) || (ast_channel_streamid(chan) == -1 && ast_channel_timingfunc(chan) == NULL))) {
3634  ast_stopstream(chan);
3635  time(&start);
3636  }
3637  /* Write audio frame data into speech engine if possible */
3638  if (fr && fr->frametype == AST_FRAME_VOICE)
3639  ast_speech_write(speech, fr->data.ptr, fr->datalen);
3640  break;
3641  case AST_SPEECH_STATE_WAIT:
3642  /* Cue waiting sound if not already playing */
3643  if ((!ast_channel_stream(chan)) || (ast_channel_streamid(chan) == -1 && ast_channel_timingfunc(chan) == NULL)) {
3644  ast_stopstream(chan);
3645  /* If a processing sound exists, or is not none - play it */
3646  if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none"))
3647  speech_streamfile(chan, speech->processing_sound, ast_channel_language(chan), 0);
3648  }
3649  break;
3650  case AST_SPEECH_STATE_DONE:
3651  /* Get the results */
3652  speech->results = ast_speech_results_get(speech);
3653  /* Change state to not ready */
3655  reason = "speech";
3656  break;
3657  default:
3658  break;
3659  }
3660  ast_mutex_unlock(&speech->lock);
3661 
3662  /* Check frame for DTMF or hangup */
3663  if (fr) {
3664  if (fr->frametype == AST_FRAME_DTMF) {
3665  reason = "dtmf";
3666  dtmf = fr->subclass.integer;
3667  } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_HANGUP) {
3668  reason = "hangup";
3669  }
3670  ast_frfree(fr);
3671  }
3672  }
3673 
3674  if (!strcasecmp(reason, "speech")) {
3675  /* Build string containing speech results */
3676  for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) {
3677  /* Build result string */
3678  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);
3679  /* Increment result count */
3680  i++;
3681  }
3682  /* Print out */
3683  ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
3684  } else if (!strcasecmp(reason, "dtmf")) {
3685  ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
3686  } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
3687  ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
3688  } else {
3689  ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset);
3690  }
3691 
3692  return RESULT_SUCCESS;
3693 }
3694 
3695 /*!
3696  * \brief AGI commands list
3697  */
3698 static struct agi_command commands[] = {
3699  { { "answer", NULL }, handle_answer, NULL, NULL, 0 },
3700  { { "asyncagi", "break", NULL }, handle_asyncagi_break, NULL, NULL, 1 },
3701  { { "channel", "status", NULL }, handle_channelstatus, NULL, NULL, 0 },
3702  { { "database", "del", NULL }, handle_dbdel, NULL, NULL, 1 },
3703  { { "database", "deltree", NULL }, handle_dbdeltree, NULL, NULL, 1 },
3704  { { "database", "get", NULL }, handle_dbget, NULL, NULL, 1 },
3705  { { "database", "put", NULL }, handle_dbput, NULL, NULL, 1 },
3706  { { "exec", NULL }, handle_exec, NULL, NULL, 1 },
3707  { { "get", "data", NULL }, handle_getdata, NULL, NULL, 0 },
3708  { { "get", "full", "variable", NULL }, handle_getvariablefull, NULL, NULL, 1 },
3709  { { "get", "option", NULL }, handle_getoption, NULL, NULL, 0 },
3710  { { "get", "variable", NULL }, handle_getvariable, NULL, NULL, 1 },
3711  { { "hangup", NULL }, handle_hangup, NULL, NULL, 0 },
3712  { { "noop", NULL }, handle_noop, NULL, NULL, 1 },
3713  { { "receive", "char", NULL }, handle_recvchar, NULL, NULL, 0 },
3714  { { "receive", "text", NULL }, handle_recvtext, NULL, NULL, 0 },
3715  { { "record", "file", NULL }, handle_recordfile, NULL, NULL, 0 },
3716  { { "say", "alpha", NULL }, handle_sayalpha, NULL, NULL, 0},
3717  { { "say", "digits", NULL }, handle_saydigits, NULL, NULL, 0 },
3718  { { "say", "number", NULL }, handle_saynumber, NULL, NULL, 0 },
3719  { { "say", "phonetic", NULL }, handle_sayphonetic, NULL, NULL, 0},
3720  { { "say", "date", NULL }, handle_saydate, NULL, NULL, 0},
3721  { { "say", "time", NULL }, handle_saytime, NULL, NULL, 0},
3722  { { "say", "datetime", NULL }, handle_saydatetime, NULL, NULL, 0},
3723  { { "send", "image", NULL }, handle_sendimage, NULL, NULL, 0},
3724  { { "send", "text", NULL }, handle_sendtext, NULL, NULL, 0},
3725  { { "set", "autohangup", NULL }, handle_autohangup, NULL, NULL, 0},
3726  { { "set", "callerid", NULL }, handle_setcallerid, NULL, NULL, 0},
3727  { { "set", "context", NULL }, handle_setcontext, NULL, NULL, 0},
3728  { { "set", "extension", NULL }, handle_setextension, NULL, NULL, 0},
3729  { { "set", "music", NULL }, handle_setmusic, NULL, NULL, 0 },
3730  { { "set", "priority", NULL }, handle_setpriority, NULL, NULL, 0 },
3731  { { "set", "variable", NULL }, handle_setvariable, NULL, NULL, 1 },
3732  { { "stream", "file", NULL }, handle_streamfile, NULL, NULL, 0 },
3733  { { "control", "stream", "file", NULL }, handle_controlstreamfile, NULL, NULL, 0 },
3734  { { "tdd", "mode", NULL }, handle_tddmode, NULL, NULL, 0 },
3735  { { "verbose", NULL }, handle_verbose, NULL, NULL, 1 },
3736  { { "wait", "for", "digit", NULL }, handle_waitfordigit, NULL, NULL, 0 },
3737  { { "speech", "create", NULL }, handle_speechcreate, NULL, NULL, 0 },
3738  { { "speech", "set", NULL }, handle_speechset, NULL, NULL, 0 },
3739  { { "speech", "destroy", NULL }, handle_speechdestroy, NULL, NULL, 1 },
3740  { { "speech", "load", "grammar", NULL }, handle_speechloadgrammar, NULL, NULL, 0 },
3741  { { "speech", "unload", "grammar", NULL }, handle_speechunloadgrammar, NULL, NULL, 1 },
3742  { { "speech", "activate", "grammar", NULL }, handle_speechactivategrammar, NULL, NULL, 0 },
3743  { { "speech", "deactivate", "grammar", NULL }, handle_speechdeactivategrammar, NULL, NULL, 0 },
3744  { { "speech", "recognize", NULL }, handle_speechrecognize, NULL, NULL, 0 },
3745 };
3746 
3748 
3749 static char *help_workhorse(int fd, const char * const match[])
3750 {
3751  char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN];
3752  struct agi_command *e;
3753 
3754  if (match)
3755  ast_join(matchstr, sizeof(matchstr), match);
3756 
3757  ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description");
3760  if (!e->cmda[0])
3761  break;
3762  /* Hide commands that start with '_' */
3763  if ((e->cmda[0])[0] == '_')
3764  continue;
3765  ast_join(fullcmd, sizeof(fullcmd), e->cmda);
3766  if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
3767  continue;
3768  ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, S_OR(e->summary, "Not available"));
3769  }
3771 
3772  return CLI_SUCCESS;
3773 }
3774 
3776 {
3777  char fullcmd[MAX_CMD_LEN];
3778 
3779  ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3780 
3781  if (!find_command(cmd->cmda, 1)) {
3782  *((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC;
3783  if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
3784 #ifdef AST_XML_DOCS
3785  *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd, NULL);
3786  *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd, NULL);
3787  *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd, NULL);
3788  *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd, NULL);
3789  *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
3790 #endif
3791 #ifndef HAVE_NULLSAFE_PRINTF
3792  if (!cmd->summary) {
3793  *((char **) &cmd->summary) = ast_strdup("");
3794  }
3795  if (!cmd->usage) {
3796  *((char **) &cmd->usage) = ast_strdup("");
3797  }
3798  if (!cmd->syntax) {
3799  *((char **) &cmd->syntax) = ast_strdup("");
3800  }
3801  if (!cmd->seealso) {
3802  *((char **) &cmd->seealso) = ast_strdup("");
3803  }
3804 #endif
3805  }
3806 
3807  cmd->mod = mod;
3809  AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
3811  ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
3812  return 1;
3813  } else {
3814  ast_log(LOG_WARNING, "Command already registered!\n");
3815  return 0;
3816  }
3817 }
3818 
3820 {
3821  struct agi_command *e;
3822  int unregistered = 0;
3823  char fullcmd[MAX_CMD_LEN];
3824 
3825  ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3826 
3829  if (cmd == e) {
3831 #ifdef AST_XML_DOCS
3832  if (e->docsrc == AST_XML_DOC) {
3833  ast_free((char *) e->summary);
3834  ast_free((char *) e->usage);
3835  ast_free((char *) e->syntax);
3836  ast_free((char *) e->seealso);
3837  *((char **) &e->summary) = NULL;
3838  *((char **) &e->usage) = NULL;
3839  *((char **) &e->syntax) = NULL;
3840  *((char **) &e->seealso) = NULL;
3841  }
3842 #endif
3843  unregistered=1;
3844  break;
3845  }
3846  }
3849  if (unregistered) {
3850  ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd);
3851  }
3852  return unregistered;
3853 }
3854 
3855 int AST_OPTIONAL_API_NAME(ast_agi_register_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
3856 {
3857  unsigned int i, x = 0;
3858 
3859  for (i = 0; i < len; i++) {
3860  if (ast_agi_register(mod, cmd + i) == 1) {
3861  x++;
3862  continue;
3863  }
3864 
3865  /* registration failed, unregister everything
3866  that had been registered up to that point
3867  */
3868  for (; x > 0; x--) {
3869  /* we are intentionally ignoring the
3870  result of ast_agi_unregister() here,
3871  but it should be safe to do so since
3872  we just registered these commands and
3873  the only possible way for unregistration
3874  to fail is if the command is not
3875  registered
3876  */
3877  (void) ast_agi_unregister(cmd + x - 1);
3878  }
3879  return -1;
3880  }
3881 
3882  return 0;
3883 }
3884 
3886 {
3887  unsigned int i;
3888  int res = 0;
3889 
3890  for (i = 0; i < len; i++) {
3891  /* remember whether any of the unregistration
3892  attempts failed... there is no recourse if
3893  any of them do
3894  */
3895  res |= ast_agi_unregister(cmd + i);
3896  }
3897 
3898  return res;
3899 }
3900 
3901 static agi_command *find_command(const char * const cmds[], int exact)
3902 {
3903  int y, match;
3904  struct agi_command *e;
3905 
3908  if (!e->cmda[0])
3909  break;
3910  /* start optimistic */
3911  match = 1;
3912  for (y = 0; match && cmds[y]; y++) {
3913  /* If there are no more words in the command (and we're looking for
3914  an exact match) or there is a difference between the two words,
3915  then this is not a match */
3916  if (!e->cmda[y] && !exact)
3917  break;
3918  /* don't segfault if the next part of a command doesn't exist */
3919  if (!e->cmda[y]) {
3921  return NULL;
3922  }
3923  if (strcasecmp(e->cmda[y], cmds[y]))
3924  match = 0;
3925  }
3926  /* If more words are needed to complete the command then this is not
3927  a candidate (unless we're looking for a really inexact answer */
3928  if ((exact > -1) && e->cmda[y])
3929  match = 0;
3930  if (match) {
3932  return e;
3933  }
3934  }
3936  return NULL;
3937 }
3938 
3939 static int parse_args(char *s, int *max, const char *argv[])
3940 {
3941  int x = 0, quoted = 0, escaped = 0, whitespace = 1;
3942  char *cur;
3943 
3944  cur = s;
3945  while(*s) {
3946  switch(*s) {
3947  case '"':
3948  /* If it's escaped, put a literal quote */
3949  if (escaped)
3950  goto normal;
3951  else
3952  quoted = !quoted;
3953  if (quoted && whitespace) {
3954  /* If we're starting a quote, coming off white space start a new word, too */
3955  argv[x++] = cur;
3956  whitespace=0;
3957  }
3958  escaped = 0;
3959  break;
3960  case ' ':
3961  case '\t':
3962  if (!quoted && !escaped) {
3963  /* If we're not quoted, mark this as whitespace, and
3964  end the previous argument */
3965  whitespace = 1;
3966  *(cur++) = '\0';
3967  } else
3968  /* Otherwise, just treat it as anything else */
3969  goto normal;
3970  break;
3971  case '\\':
3972  /* If we're escaped, print a literal, otherwise enable escaping */
3973  if (escaped) {
3974  goto normal;
3975  } else {
3976  escaped=1;
3977  }
3978  break;
3979  default:
3980 normal:
3981  if (whitespace) {
3982  if (x >= MAX_ARGS -1) {
3983  ast_log(LOG_WARNING, "Too many arguments, truncating\n");
3984  break;
3985  }
3986  /* Coming off of whitespace, start the next argument */
3987  argv[x++] = cur;
3988  whitespace=0;
3989  }
3990  *(cur++) = *s;
3991  escaped=0;
3992  }
3993  s++;
3994  }
3995  /* Null terminate */
3996  *(cur++) = '\0';
3997  argv[x] = NULL;
3998  *max = x;
3999  return 0;
4000 }
4001 
4002 static void publish_async_exec_end(struct ast_channel *chan, int command_id, const char *command, int result_code, const char *result)
4003 {
4004  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
4005  blob = ast_json_pack("{s: i, s: s, s: i, s: s}",
4006  "CommandId", command_id,
4007  "Command", command,
4008  "ResultCode", result_code,
4009  "Result", result);
4010  ast_channel_publish_cached_blob(chan, agi_exec_end_type(), blob);
4011 }
4012 
4013 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
4014 {
4015  const char *argv[MAX_ARGS] = {0};
4016  int argc = MAX_ARGS;
4017  int res;
4018  agi_command *c;
4019  char *ami_cmd = ast_strdupa(buf);
4020  const char *ami_res;
4021  int command_id = ast_random();
4022  int resultcode = 0;
4023  RAII_VAR(struct ast_json *, startblob, NULL, ast_json_unref);
4024 
4025  startblob = ast_json_pack("{s: i, s: s}",
4026  "CommandId", command_id,
4027  "Command", ami_cmd);
4028  ast_channel_publish_cached_blob(chan, agi_exec_start_type(), startblob);
4029 
4030  parse_args(buf, &argc, argv);
4031  c = find_command(argv, 0);
4032  if (!c || !ast_module_running_ref(c->mod)) {
4033  ami_res = "Invalid or unknown command";
4034  resultcode = 510;
4035 
4036  ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
4037 
4038  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4039 
4040  return AGI_RESULT_SUCCESS;
4041  }
4042 
4043  if (!dead || (dead && c->dead)) {
4044  res = c->handler(chan, agi, argc, argv);
4045  switch (res) {
4046  case RESULT_SHOWUSAGE:
4047  ami_res = "Usage";
4048  resultcode = 520;
4049 
4050  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4051 
4052  if (ast_strlen_zero(c->usage)) {
4053  ast_agi_send(agi->fd, chan, "520 Invalid command syntax. Proper usage not available.\n");
4054  } else {
4055  ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n");
4056  ast_agi_send(agi->fd, chan, "%s\n", c->usage);
4057  ast_agi_send(agi->fd, chan, "520 End of proper usage.\n");
4058  }
4059 
4060  break;
4061  case RESULT_FAILURE:
4062  ami_res = "Failure";
4063  resultcode = -1;
4064 
4065  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4066 
4067  /* The RESULT_FAILURE code is usually because the channel hungup. */
4068  return AGI_RESULT_FAILURE;
4069  case ASYNC_AGI_BREAK:
4070  ami_res = "Success";
4071  resultcode = 200;
4072 
4073  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4074 
4075  return AGI_RESULT_SUCCESS_ASYNC;
4076  case RESULT_SUCCESS:
4077  ami_res = "Success";
4078  resultcode = 200;
4079 
4080  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4081 
4082  break;
4083  default:
4084  ami_res = "Unknown Result";
4085  resultcode = 200;
4086 
4087  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4088 
4089  break;
4090  }
4091  } else {
4092  ami_res = "Command Not Permitted on a dead channel or intercept routine";
4093  resultcode = 511;
4094 
4095  ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
4096 
4097  publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
4098  }
4099  ast_module_unref(c->mod);
4100 
4101  return AGI_RESULT_SUCCESS;
4102 }
4103 
4104 static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
4105 {
4106  struct ast_channel *c;
4107  int outfd;
4108  int ms;
4109  int needhup = 0;
4110  enum agi_result returnstatus = AGI_RESULT_SUCCESS;
4111  struct ast_frame *f;
4112  char buf[AGI_BUF_LEN];
4113  char *res = NULL;
4114  FILE *readf;
4115  /* how many times we'll retry if ast_waitfor_nandfs will return without either
4116  channel or file descriptor in case select is interrupted by a system call (EINTR) */
4117  int retry = AGI_NANDFS_RETRY;
4118  int send_sighup;
4119  const char *sighup_str;
4120  const char *exit_on_hangup_str;
4121  int exit_on_hangup;
4122  /*! Running in an interception routine is like DeadAGI mode. No touchy the channel frames. */
4123  int in_intercept = ast_channel_get_intercept_mode();
4124 
4125  ast_channel_lock(chan);
4126  sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
4127  send_sighup = !ast_false(sighup_str);
4128  exit_on_hangup_str = pbx_builtin_getvar_helper(chan, "AGIEXITONHANGUP");
4129  exit_on_hangup = ast_true(exit_on_hangup_str);
4130  ast_channel_unlock(chan);
4131 
4132  if (!(readf = fdopen(agi->ctrl, "r"))) {
4133  ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
4134  if (send_sighup && pid > -1)
4135  kill(pid, SIGHUP);
4136  close(agi->ctrl);
4137  return AGI_RESULT_FAILURE;
4138  }
4139 
4140  setlinebuf(readf);
4141  setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv);
4142  for (;;) {
4143  if (needhup) {
4144  needhup = 0;
4145  dead = 1;
4146  if (send_sighup) {
4147  if (pid > -1) {
4148  kill(pid, SIGHUP);
4149  } else if (agi->fast) {
4150  ast_agi_send(agi->fd, chan, "HANGUP\n");
4151  }
4152  }
4153  if (exit_on_hangup) {
4154  break;
4155  }
4156  }
4157  ms = -1;
4158  if (dead || in_intercept) {
4159  c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
4160  } else if (!ast_check_hangup(chan)) {
4161  c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
4162  } else {
4163  /*
4164  * Read the channel control queue until it is dry so we can
4165  * switch to dead mode.
4166  */
4167  c = chan;
4168  }
4169  if (c) {
4170  retry = AGI_NANDFS_RETRY;
4171  /* Idle the channel until we get a command */
4172  f = ast_read(c);
4173  if (!f) {
4174  ast_debug(1, "%s hungup\n", ast_channel_name(chan));
4175  needhup = 1;
4176  if (!returnstatus) {
4177  returnstatus = AGI_RESULT_HANGUP;
4178  }
4179  } else {
4180  /* If it's voice, write it to the audio pipe */
4181  if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
4182  /* Write, ignoring errors */
4183  if (write(agi->audio, f->data.ptr, f->datalen) < 0) {
4184  }
4185  }
4186  ast_frfree(f);
4187  }
4188  } else if (outfd > -1) {
4189  size_t len = sizeof(buf);
4190  size_t buflen = 0;
4191  enum agi_result cmd_status;
4192 
4193  retry = AGI_NANDFS_RETRY;
4194  buf[0] = '\0';
4195 
4196  while (len > 1) {
4197  res = fgets(buf + buflen, len, readf);
4198  if (feof(readf))
4199  break;
4200  if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN)))
4201  break;
4202  if (res != NULL && !agi->fast)
4203  break;
4204  buflen = strlen(buf);
4205  if (buflen && buf[buflen - 1] == '\n')
4206  break;
4207  len = sizeof(buf) - buflen;
4208  if (agidebug)
4209  ast_verbose("AGI Rx << temp buffer %s - errno %s\nNo \\n received, checking again.\n", buf, strerror(errno));
4210  }
4211 
4212  if (!buf[0]) {
4213  /* Program terminated */
4214  ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", ast_channel_name(chan), request, returnstatus);
4215  if (pid > 0)
4216  waitpid(pid, status, 0);
4217  /* No need to kill the pid anymore, since they closed us */
4218  pid = -1;
4219  break;
4220  }
4221 
4222  /* Special case for inability to execute child process */
4223  if (*buf && strncasecmp(buf, "failure", 7) == 0) {
4224  returnstatus = AGI_RESULT_FAILURE;
4225  break;
4226  }
4227 
4228  /* get rid of trailing newline, if any */
4229  buflen = strlen(buf);
4230  if (buflen && buf[buflen - 1] == '\n') {
4231  buf[buflen - 1] = '\0';
4232  }
4233 
4234  if (agidebug)
4235  ast_verbose("<%s>AGI Rx << %s\n", ast_channel_name(chan), buf);
4236  cmd_status = agi_handle_command(chan, agi, buf, dead || in_intercept);
4237  switch (cmd_status) {
4238  case AGI_RESULT_FAILURE:
4239  if (dead || in_intercept || !ast_check_hangup(chan)) {
4240  /* The failure was not because of a hangup. */
4241  returnstatus = AGI_RESULT_FAILURE;
4242  }
4243  break;
4244  default:
4245  break;
4246  }
4247  } else {
4248  if (--retry <= 0) {
4249  ast_log(LOG_WARNING, "No channel, no fd?\n");
4250  returnstatus = AGI_RESULT_FAILURE;
4251  break;
4252  }
4253  }
4254  }
4255 
4256  if (agi->speech) {
4257  ast_speech_destroy(agi->speech);
4258  }
4259  /* Notify process */
4260  if (send_sighup) {
4261  if (pid > -1) {
4262  if (kill(pid, SIGHUP)) {
4263  ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
4264  } else { /* Give the process a chance to die */
4265  usleep(1);
4266  }
4267  waitpid(pid, status, WNOHANG);
4268  } else if (agi->fast) {
4269  ast_agi_send(agi->fd, chan, "HANGUP\n");
4270  }
4271  }
4272  fclose(readf);
4273  return returnstatus;
4274 }
4275 
4276 static char *handle_cli_agi_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4277 {
4278  struct agi_command *command;
4279  char fullcmd[MAX_CMD_LEN];
4280  int error = 0;
4281 
4282  switch (cmd) {
4283  case CLI_INIT:
4284  e->command = "agi show commands [topic]";
4285  e->usage =
4286  "Usage: agi show commands [topic] <topic>\n"
4287  " When called with a topic as an argument, displays usage\n"
4288  " information on the given command. If called without a\n"
4289  " topic, it provides a list of AGI commands.\n";
4290  case CLI_GENERATE:
4291  return NULL;
4292  }
4293  if (a->argc < e->args - 1 || (a->argc >= e->args && strcasecmp(a->argv[e->args - 1], "topic")))
4294  return CLI_SHOWUSAGE;
4295  if (a->argc > e->args - 1) {
4296  command = find_command(a->argv + e->args, 1);
4297  if (command) {
4298  char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL;
4299  char info[30 + MAX_CMD_LEN]; /* '-= Info about...' */
4300  char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS]; /* '-= Info about...' with colors */
4301  char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
4302  char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Description]\n with colors */
4303  char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Runs Dead]\n with colors */
4304  char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS]; /* 'Yes' or 'No' with colors */
4305  char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS]; /* [See Also]\n with colors */
4306  char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
4307  size_t synlen, desclen, seealsolen, stxlen;
4308 
4309  term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle));
4310  term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle));
4311  term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle));
4312  term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle));
4313  term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle));
4314  term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent));
4315 
4316  ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
4317  snprintf(info, sizeof(info), "\n -= Info about agi '%s' =- ", fullcmd);
4318  term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle));
4319 #ifdef AST_XML_DOCS
4320  if (command->docsrc == AST_XML_DOC) {
4321  synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1);
4322  description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1);
4323  seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1);
4324  if (!seealso || !description || !synopsis) {
4325  error = 1;
4326  goto return_cleanup;
4327  }
4328  } else
4329 #endif
4330  {
4331  synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
4332  synopsis = ast_malloc(synlen);
4333 
4334  desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
4335  description = ast_malloc(desclen);
4336 
4337  seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
4338  seealso = ast_malloc(seealsolen);
4339 
4340  if (!synopsis || !description || !seealso) {
4341  error = 1;
4342  goto return_cleanup;
4343  }
4344  term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen);
4345  term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen);
4346  term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen);
4347  }
4348 
4349  stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
4350  syntax = ast_malloc(stxlen);
4351  if (!syntax) {
4352  error = 1;
4353  goto return_cleanup;
4354  }
4355  term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen);
4356 
4357  ast_cli(a->fd, "%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", infotitle, stxtitle, syntax,
4358  desctitle, description, syntitle, synopsis, deadtitle, deadcontent,
4359  seealsotitle, seealso);
4360 return_cleanup:
4361  ast_free(synopsis);
4362  ast_free(description);
4363  ast_free(syntax);
4364  ast_free(seealso);
4365  } else {
4366  if (find_command(a->argv + e->args, -1)) {
4367  return help_workhorse(a->fd, a->argv + e->args);
4368  } else {
4369  ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
4370  ast_cli(a->fd, "No such command '%s'.\n", fullcmd);
4371  }
4372  }
4373  } else {
4374  return help_workhorse(a->fd, NULL);
4375  }
4376  return (error ? CLI_FAILURE : CLI_SUCCESS);
4377 }
4378 
4379 /*! \brief Convert string to use HTML escaped characters
4380  \note Maybe this should be a generic function?
4381 */
4382 static void write_html_escaped(FILE *htmlfile, char *str)
4383 {
4384  char *cur = str;
4385 
4386  while(*cur) {
4387  switch (*cur) {
4388  case '<':
4389  fprintf(htmlfile, "%s", "&lt;");
4390  break;
4391  case '>':
4392  fprintf(htmlfile, "%s", "&gt;");
4393  break;
4394  case '&':
4395  fprintf(htmlfile, "%s", "&amp;");
4396  break;
4397  case '"':
4398  fprintf(htmlfile, "%s", "&quot;");
4399  break;
4400  default:
4401  fprintf(htmlfile, "%c", *cur);
4402  break;
4403  }
4404  cur++;
4405  }
4406 
4407  return;
4408 }
4409 
4410 static int write_htmldump(const char *filename)
4411 {
4412  struct agi_command *command;
4413  char fullcmd[MAX_CMD_LEN];
4414  FILE *htmlfile;
4415 
4416  if (!(htmlfile = fopen(filename, "wt")))
4417  return -1;
4418 
4419  fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
4420  fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
4421  fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
4422 
4424  AST_RWLIST_TRAVERSE(&agi_commands, command, list) {
4425  char *tempstr, *stringp;
4426 
4427  if (!command->cmda[0]) /* end ? */
4428  break;
4429  /* Hide commands that start with '_' */
4430  if ((command->cmda[0])[0] == '_')
4431  continue;
4432  ast_join(fullcmd, sizeof(fullcmd), command->cmda);
4433 
4434  fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
4435  fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary);
4436 #ifdef AST_XML_DOCS
4437  stringp = ast_xmldoc_printable(command->usage, 0);
4438 #else
4439  stringp = ast_strdup(command->usage);
4440 #endif
4441  tempstr = strsep(&stringp, "\n");
4442 
4443  fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">");
4444  write_html_escaped(htmlfile, tempstr);
4445  fprintf(htmlfile, "</TD></TR>\n");
4446  fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
4447 
4448  while ((tempstr = strsep(&stringp, "\n")) != NULL) {
4449  write_html_escaped(htmlfile, tempstr);
4450  fprintf(htmlfile, "<BR>\n");
4451  }
4452  fprintf(htmlfile, "</TD></TR>\n");
4453  fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
4454  ast_free(stringp);
4455  }
4457  fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
4458  fclose(htmlfile);
4459  return 0;
4460 }
4461 
4462 static char *handle_cli_agi_dump_html(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4463 {
4464  switch (cmd) {
4465  case CLI_INIT:
4466  e->command = "agi dump html";
4467  e->usage =
4468  "Usage: agi dump html <filename>\n"
4469  " Dumps the AGI command list in HTML format to the given\n"
4470  " file.\n";
4471  return NULL;
4472  case CLI_GENERATE:
4473  return NULL;
4474  }
4475  if (a->argc != e->args + 1)
4476  return CLI_SHOWUSAGE;
4477 
4478  if (write_htmldump(a->argv[e->args]) < 0) {
4479  ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]);
4480  return CLI_SHOWUSAGE;
4481  }
4482  ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]);
4483  return CLI_SUCCESS;
4484 }
4485 
4486 static int agi_exec_full(struct ast_channel *chan, const char *data, int enhanced, int dead)
4487 {
4488  enum agi_result res;
4489  char *buf;
4490  int fds[2], efd = -1, pid = -1;
4492  AST_APP_ARG(arg)[MAX_ARGS];
4493  );
4494  AGI agi;
4495 
4496  if (ast_strlen_zero(data)) {
4497  ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
4498  return -1;
4499  }
4500  if (dead)
4501  ast_debug(3, "Hungup channel detected, running agi in dead mode.\n");
4502  memset(&agi, 0, sizeof(agi));
4503  buf = ast_strdupa(data);
4505  args.arg[args.argc] = NULL;
4506 #if 0
4507  /* Answer if need be */
4508  if (chan->_state != AST_STATE_UP) {
4509  if (ast_answer(chan))
4510  return -1;
4511  }
4512 #endif
4513  res = launch_script(chan, args.arg[0], args.argc, args.arg, fds, enhanced ? &efd : NULL, &pid);
4514  /* Async AGI do not require run_agi(), so just proceed if normal AGI
4515  or Fast AGI are setup with success. */
4516  if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
4517  int status = 0;
4518  agi.fd = fds[1];
4519  agi.ctrl = fds[0];
4520  agi.audio = efd;
4521  agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
4522  res = run_agi(chan, args.arg[0], &agi, pid, &status, dead, args.argc, args.arg);
4523  /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
4524  if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status)
4525  res = AGI_RESULT_FAILURE;
4526  if (fds[1] != fds[0])
4527  close(fds[1]);
4528  if (efd > -1)
4529  close(efd);
4530  }
4532 
4533  switch (res) {
4534  case AGI_RESULT_SUCCESS:
4537  pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
4538  break;
4539  case AGI_RESULT_FAILURE:
4540  pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE");
4541  break;
4542  case AGI_RESULT_NOTFOUND:
4543  pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND");
4544  break;
4545  case AGI_RESULT_HANGUP:
4546  pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP");
4547  return -1;
4548  }
4549 
4550  return 0;
4551 }
4552 
4553 static int agi_exec(struct ast_channel *chan, const char *data)
4554 {
4555  if (!ast_check_hangup(chan))
4556  return agi_exec_full(chan, data, 0, 0);
4557  else
4558  return agi_exec_full(chan, data, 0, 1);
4559 }
4560 
4561 static int eagi_exec(struct ast_channel *chan, const char *data)
4562 {
4563  int res;
4564  struct ast_format *readformat;
4565  struct ast_format *requested_format = NULL;
4566  const char *requested_format_name;
4567 
4568  if (ast_check_hangup(chan)) {
4569  ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n");
4570  return 0;
4571  }
4572 
4573  requested_format_name = pbx_builtin_getvar_helper(chan, "EAGI_AUDIO_FORMAT");
4574  if (requested_format_name) {
4575  requested_format = ast_format_cache_get(requested_format_name);
4576  if (requested_format) {
4577  ast_verb(3, "<%s> Setting EAGI audio pipe format to %s\n",
4578  ast_channel_name(chan), ast_format_get_name(requested_format));
4579  } else {
4580  ast_log(LOG_ERROR, "Could not find requested format: %s\n", requested_format_name);
4581  }
4582  }
4583 
4584  readformat = ao2_bump(ast_channel_readformat(chan));
4585  if (ast_set_read_format(chan, requested_format ?: ast_format_slin)) {
4586  ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", ast_channel_name(chan));
4587  ao2_cleanup(requested_format);
4588  ao2_cleanup(readformat);
4589  return -1;
4590  }
4591  res = agi_exec_full(chan, data, 1, 0);
4592  if (!res) {
4593  if (ast_set_read_format(chan, readformat)) {
4594  ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", ast_channel_name(chan),
4595  ast_format_get_name(readformat));
4596  }
4597  }
4598  ao2_cleanup(requested_format);
4599  ao2_cleanup(readformat);
4600  return res;
4601 }
4602 
4603 static int deadagi_exec(struct ast_channel *chan, const char *data)
4604 {
4605  ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n");
4606  return agi_exec(chan, data);
4607 }
4608 
4609 static struct ast_cli_entry cli_agi[] = {
4610  AST_CLI_DEFINE(handle_cli_agi_add_cmd, "Add AGI command to a channel in Async AGI"),
4611  AST_CLI_DEFINE(handle_cli_agi_debug, "Enable/Disable AGI debugging"),
4612  AST_CLI_DEFINE(handle_cli_agi_show, "List AGI commands or specific help"),
4613  AST_CLI_DEFINE(handle_cli_agi_dump_html, "Dumps a list of AGI commands in HTML format")
4614 };
4615 
4616 #ifdef TEST_FRAMEWORK
4617 AST_TEST_DEFINE(test_agi_null_docs)
4618 {
4619  int res = AST_TEST_PASS;
4620  struct agi_command noop_command =
4621  { { "testnoop", NULL }, handle_noop, NULL, NULL, 0 };
4622 
4623  switch (cmd) {
4624  case TEST_INIT:
4625  info->name = "null_agi_docs";
4626  info->category = "/res/agi/";
4627  info->summary = "AGI command with no documentation";
4628  info->description = "Test whether an AGI command with no documentation will crash Asterisk";
4629  return AST_TEST_NOT_RUN;
4630  case TEST_EXECUTE:
4631  break;
4632  }
4633 
4634  if (ast_agi_register(ast_module_info->self, &noop_command) == 0) {
4635  ast_test_status_update(test, "Unable to register testnoop command, because res_agi is not loaded.\n");
4636  return AST_TEST_NOT_RUN;
4637  }
4638 
4639 #ifndef HAVE_NULLSAFE_PRINTF
4640  /* Test for condition without actually crashing Asterisk */
4641  if (noop_command.usage == NULL) {
4642  ast_test_status_update(test, "AGI testnoop usage was not updated properly.\n");
4643  res = AST_TEST_FAIL;
4644  }
4645  if (noop_command.syntax == NULL) {
4646  ast_test_status_update(test, "AGI testnoop syntax was not updated properly.\n");
4647  res = AST_TEST_FAIL;
4648  }
4649 #endif
4650 
4651  ast_agi_unregister(&noop_command);
4652  return res;
4653 }
4654 #endif
4655 
4656 static int unload_module(void)
4657 {
4658  STASIS_MESSAGE_TYPE_CLEANUP(agi_exec_start_type);
4659  STASIS_MESSAGE_TYPE_CLEANUP(agi_exec_end_type);
4660  STASIS_MESSAGE_TYPE_CLEANUP(agi_async_start_type);
4661  STASIS_MESSAGE_TYPE_CLEANUP(agi_async_exec_type);
4662  STASIS_MESSAGE_TYPE_CLEANUP(agi_async_end_type);
4663 
4668  ast_manager_unregister("AGI");
4670  AST_TEST_UNREGISTER(test_agi_null_docs);
4671  return 0;
4672 }
4673 
4674 static int load_module(void)
4675 {
4676  int err = 0;
4677 
4678  err |= STASIS_MESSAGE_TYPE_INIT(agi_exec_start_type);
4679  err |= STASIS_MESSAGE_TYPE_INIT(agi_exec_end_type);
4680  err |= STASIS_MESSAGE_TYPE_INIT(agi_async_start_type);
4681  err |= STASIS_MESSAGE_TYPE_INIT(agi_async_exec_type);
4682  err |= STASIS_MESSAGE_TYPE_INIT(agi_async_end_type);
4683 
4690 
4691  AST_TEST_REGISTER(test_agi_null_docs);
4692 
4693  if (err) {
4694  unload_module();
4695  return AST_MODULE_LOAD_DECLINE;
4696  }
4697 
4698  return AST_MODULE_LOAD_SUCCESS;
4699 }
4700 
4702  .support_level = AST_MODULE_SUPPORT_CORE,
4703  .load = load_module,
4704  .unload = unload_module,
4705  .load_pri = AST_MODPRI_APP_DEPEND,
4706  .requires = "res_speech",
4707 );
AGI Extension interfaces - Asterisk Gateway Interface.
jack_status_t status
Definition: app_jack.c:146
const char * str
Definition: app_jack.c:147
unsigned int stop
Definition: app_meetme.c:1098
static int skipms
Asterisk version information.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Persistent data storage (akin to *doze registry)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:412
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:457
static struct ast_str * prompt
Definition: asterisk.c:2761
Asterisk main include file. File version handling, generic pbx functions.
#define AST_FILE_MODE
Definition: asterisk.h:32
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1835
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static int tmp()
Definition: bt_open.c:389
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1008
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:947
static void suspend(struct cc_core_instance *core_instance)
Definition: ccss.c:3193
static PGresult * result
Definition: cel_pgsql.c:84
static snd_pcm_format_t format
Definition: chan_alsa.c:106
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2312
static const char type[]
Definition: chan_ooh323.c:109
static int request(void *obj)
Definition: chan_pjsip.c:2580
enum ast_cc_service_type service
Definition: chan_sip.c:956
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
struct ast_filestream * ast_channel_stream(const struct ast_channel *chan)
void ast_channel_stream_set(struct ast_channel *chan, struct ast_filestream *value)
const char * ast_channel_accountcode(const struct ast_channel *chan)
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Clear a flag on a channel.
Definition: channel.c:11220
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2384
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:2989
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1815
const char * ast_channel_uniqueid(const struct ast_channel *chan)
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
const char * ast_channel_data(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int ast_recvchar(struct ast_channel *chan, int timeout)
Receives a text character from a channel.
Definition: channel.c:4741
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3163
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
int ast_channel_get_intercept_mode(void)
Am I currently running an intercept dialplan routine.
Definition: channel.c:10415
int ast_channel_priority(const struct ast_channel *chan)
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:459
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4292
int ast_sendtext(struct ast_channel *chan, const char *text)
Sends text to a channel.
Definition: channel.c:4844
@ AST_FLAG_DISABLE_WORKAROUNDS
Definition: channel.h:1022
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7417
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5839
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
const char * ast_channel_language(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
const char * ast_channel_exten(const struct ast_channel *chan)
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Definition: channel.c:2498
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2470
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2398
ast_timing_func_t ast_channel_timingfunc(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
char * ast_recvtext(struct ast_channel *chan, int timeout)
Receives a text string from a channel Read a string of text from a channel.
Definition: channel.c:4752
void ast_channel_setwhentohangup_tv(struct ast_channel *chan, struct timeval offset)
Set when to hang a channel up.
Definition: channel.c:510
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1448
void ast_channel_context_set(struct ast_channel *chan, const char *value)
int ast_channel_streamid(const struct ast_channel *chan)
struct ast_sched_context * ast_channel_sched(const struct ast_channel *chan)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7505
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2806
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4312
#define ast_channel_unlock(chan)
Definition: channel.h:2923
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
int ast_waitfordigit_full(struct ast_channel *c, int ms, const char *breakon, int audiofd, int ctrlfd)
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to mon...
Definition: channel.c:3240
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: main/cli.c:1862
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
#define RESULT_SHOWUSAGE
Definition: cli.h:41
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define RESULT_SUCCESS
Definition: cli.h:40
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define RESULT_FAILURE
Definition: cli.h:42
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
Convenient Signal Processing routines.
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Definition: dsp.c:1778
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1773
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1748
@ THRESHOLD_SILENCE
Definition: dsp.h:73
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1486
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1999
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
#define max(a, b)
Definition: f2c.h:198
Generic File Format Support. Should be included by clients of the file handling routines....
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:1083
int ast_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd, int monfd)
Definition: file.c:1826
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
Writes a frame to a stream.
Definition: file.c:244
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:1073
int ast_stream_rewind(struct ast_filestream *fs, off_t ms)
Rewind stream ms.
Definition: file.c:1098
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applies a open stream to a channel.
Definition: file.c:1055
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1291
struct ast_filestream * ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts writing a file.
Definition: file.c:1402
int ast_truncstream(struct ast_filestream *fs)
Trunc stream at current location.
Definition: file.c:1078
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1109
int ast_playstream(struct ast_filestream *s)
Play a open stream on a channel.
Definition: file.c:1061
struct ast_filestream * ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:790
struct ast_filestream * ast_openvstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:847
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1817
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
Media Format Cache API.
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
Definition: format_cache.h:278
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static const char name[]
Definition: format_mp3.c:68
static char * synopsis
Definition: func_enum.c:154
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_str * ast_manager_str_from_json_object(struct ast_json *blob, key_exclusion_cb exclusion_cb)
Convert a JSON object into an AMI compatible string.
Definition: manager.c:1828
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3166
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3198
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:2827
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7268
void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message using the latest snapshot from the cache.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest_by_name(const char *name)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
General Asterisk channel definitions for image handling.
int ast_send_image(struct ast_channel *chan, const char *filename)
Sends an image.
Definition: image.c:158
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other fu...
Definition: main/app.c:247
void ast_safe_fork_cleanup(void)
Common routine to cleanup after fork'ed process is complete (if reaping was stopped)
Definition: main/app.c:3328
int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms, long *offsetms)
Stream a file with fast forward, pause, reverse, restart.
Definition: main/app.c:1535
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child.
Definition: main/app.c:3267
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: main/app.c:3262
int setenv(const char *name, const char *value, int overwrite)
char * strsep(char **str, const char *delims)
#define AST_FRAME_DTMF
#define ast_frfree(fr)
#define AST_OPTION_TDD
@ AST_FRAME_VIDEO
@ AST_FRAME_VOICE
@ AST_FRAME_CONTROL
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_HANGUP
@ AST_CONTROL_STREAM_STOP
#define ast_debug(level,...)
Log a DEBUG message.
void ast_child_verbose(int level, const char *fmt,...)
Definition: logger.c:908
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:404
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
Definition: linkedlists.h:333
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:653
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:173
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439