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