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