Skip to content
Snippets Groups Projects
pbx.c 377 KiB
Newer Older
  • Learn to ignore specific revisions
  • Russell Bryant's avatar
    Russell Bryant committed
    /*
    
     * Asterisk -- An open source telephony toolkit.
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * Copyright (C) 1999 - 2008, Digium, Inc.
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * Mark Spencer <markster@digium.com>
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * See http://www.asterisk.org for more information about
     * the Asterisk project. Please do not directly contact
     * any of the maintainers of this project for assistance;
     * the project provides a web site, mailing lists and IRC
     * channels for your use.
     *
    
    Mark Spencer's avatar
    Mark Spencer committed
     * This program is free software, distributed under the terms of
    
     * the GNU General Public License Version 2. See the LICENSE file
    
     * \brief Core PBX routines.
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
     * \author Mark Spencer <markster@digium.com>
    
    Mark Spencer's avatar
    Mark Spencer committed
     */
    
    
    /*** MODULEINFO
    	<support_level>core</support_level>
     ***/
    
    
    ASTERISK_REGISTER_FILE()
    
    #include "asterisk/_private.h"
    
    #include "asterisk/paths.h"	/* use ast_config_AST_SYSTEM_NAME */
    
    #include <ctype.h>
    #include <time.h>
    #include <sys/time.h>
    
    #if defined(SOLARIS)
    #include <sys/loadavg.h>
    #endif
    
    #include "asterisk/lock.h"
    #include "asterisk/cli.h"
    #include "asterisk/pbx.h"
    #include "asterisk/channel.h"
    #include "asterisk/file.h"
    #include "asterisk/callerid.h"
    #include "asterisk/cdr.h"
    #include "asterisk/config.h"
    #include "asterisk/term.h"
    
    Steve Murphy's avatar
    Steve Murphy committed
    #include "asterisk/time.h"
    
    #include "asterisk/manager.h"
    #include "asterisk/ast_expr.h"
    #include "asterisk/linkedlists.h"
    
    #define	SAY_STUBS	/* generate declarations and stubs for say methods */
    
    #include "asterisk/say.h"
    #include "asterisk/utils.h"
    #include "asterisk/causes.h"
    #include "asterisk/musiconhold.h"
    #include "asterisk/app.h"
    
    #include "asterisk/presencestate.h"
    
    #include "asterisk/module.h"
    
    #include "asterisk/indications.h"
    
    #include "asterisk/taskprocessor.h"
    
    #include "asterisk/xmldoc.h"
    
    #include "asterisk/astobj2.h"
    
    #include "asterisk/stasis_channels.h"
    
    /*!
     * \note I M P O R T A N T :
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
     *		The speed of extension handling will likely be among the most important
     * aspects of this PBX.  The switching scheme as it exists right now isn't
     * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
     * of priorities, but a constant search time here would be great ;-)
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * A new algorithm to do searching based on a 'compiled' pattern tree is introduced
     * here, and shows a fairly flat (constant) search time, even for over
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
     * 10000 patterns.
    
     *
     * Also, using a hash table for context/priority name lookup can help prevent
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
     * the find_extension routines from absorbing exponential cpu cycles as the number
     * of contexts/priorities grow. I've previously tested find_extension with red-black trees,
     * which have O(log2(n)) speed. Right now, I'm using hash tables, which do
     * searches (ideally) in O(1) time. While these techniques do not yield much
    
    Steve Murphy's avatar
    Steve Murphy committed
     * speed in small dialplans, they are worth the trouble in large dialplans.
    
    /*** DOCUMENTATION
    	<application name="Answer" language="en_US">
    		<synopsis>
    			Answer a channel if ringing.
    		</synopsis>
    		<syntax>
    			<parameter name="delay">
    				<para>Asterisk will wait this number of milliseconds before returning to
    				the dialplan after answering the call.</para>
    			</parameter>
    		</syntax>
    		<description>
    			<para>If the call has not been answered, this application will
    			answer it. Otherwise, it has no effect on the call.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Hangup</ref>
    		</see-also>
    
    	</application>
    	<application name="BackGround" language="en_US">
    		<synopsis>
    			Play an audio file while waiting for digits of an extension to go to.
    		</synopsis>
    		<syntax>
    			<parameter name="filenames" required="true" argsep="&amp;">
    				<argument name="filename1" required="true" />
    				<argument name="filename2" multiple="true" />
    			</parameter>
    			<parameter name="options">
    				<optionlist>
    					<option name="s">
    						<para>Causes the playback of the message to be skipped
    						if the channel is not in the <literal>up</literal> state (i.e. it
    						hasn't been answered yet). If this happens, the
    						application will return immediately.</para>
    					</option>
    					<option name="n">
    						<para>Don't answer the channel before playing the files.</para>
    					</option>
    					<option name="m">
    						<para>Only break if a digit hit matches a one digit
    						extension in the destination context.</para>
    					</option>
    				</optionlist>
    			</parameter>
    			<parameter name="langoverride">
    				<para>Explicitly specifies which language to attempt to use for the requested sound files.</para>
    			</parameter>
    			<parameter name="context">
    				<para>This is the dialplan context that this application will use when exiting
    				to a dialed extension.</para>
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    			</parameter>
    
    		</syntax>
    		<description>
    			<para>This application will play the given list of files <emphasis>(do not put extension)</emphasis>
    			while waiting for an extension to be dialed by the calling channel. To continue waiting
    			for digits after this application has finished playing files, the <literal>WaitExten</literal>
    			application should be used.</para>
    			<para>If one of the requested sound files does not exist, call processing will be terminated.</para>
    			<para>This application sets the following channel variable upon completion:</para>
    			<variablelist>
    				<variable name="BACKGROUNDSTATUS">
    					<para>The status of the background attempt as a text string.</para>
    					<value name="SUCCESS" />
    					<value name="FAILED" />
    				</variable>
    			</variablelist>
    		</description>
    		<see-also>
    
    			<ref type="application">ControlPlayback</ref>
    			<ref type="application">WaitExten</ref>
    			<ref type="application">BackgroundDetect</ref>
    			<ref type="function">TIMEOUT</ref>
    
    		</see-also>
    	</application>
    	<application name="Busy" language="en_US">
    		<synopsis>
    			Indicate the Busy condition.
    		</synopsis>
    		<syntax>
    			<parameter name="timeout">
    				<para>If specified, the calling channel will be hung up after the specified number of seconds.
    				Otherwise, this application will wait until the calling channel hangs up.</para>
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application will indicate the busy condition to the calling channel.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Congestion</ref>
    
    			<ref type="application">Progress</ref>
    
    			<ref type="application">Playtones</ref>
    			<ref type="application">Hangup</ref>
    		</see-also>
    
    	</application>
    	<application name="Congestion" language="en_US">
    		<synopsis>
    			Indicate the Congestion condition.
    		</synopsis>
    		<syntax>
    			<parameter name="timeout">
    				<para>If specified, the calling channel will be hung up after the specified number of seconds.
    				Otherwise, this application will wait until the calling channel hangs up.</para>
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application will indicate the congestion condition to the calling channel.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Busy</ref>
    
    			<ref type="application">Progress</ref>
    
    			<ref type="application">Playtones</ref>
    			<ref type="application">Hangup</ref>
    		</see-also>
    
    	</application>
    	<application name="ExecIfTime" language="en_US">
    		<synopsis>
    			Conditional application execution based on the current time.
    		</synopsis>
    		<syntax argsep="?">
    			<parameter name="day_condition" required="true">
    				<argument name="times" required="true" />
    				<argument name="weekdays" required="true" />
    				<argument name="mdays" required="true" />
    				<argument name="months" required="true" />
    
    				<argument name="timezone" required="false" />
    
    			</parameter>
    			<parameter name="appname" required="true" hasparams="optional">
    				<argument name="appargs" required="true" />
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application will execute the specified dialplan application, with optional
    			arguments, if the current time matches the given time specification.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Exec</ref>
    
    			<ref type="application">ExecIf</ref>
    
    			<ref type="application">TryExec</ref>
    
    			<ref type="application">GotoIfTime</ref>
    
    	</application>
    	<application name="Goto" language="en_US">
    		<synopsis>
    			Jump to a particular priority, extension, or context.
    		</synopsis>
    		<syntax>
    			<parameter name="context" />
    			<parameter name="extensions" />
    			<parameter name="priority" required="true" />
    		</syntax>
    		<description>
    			<para>This application will set the current context, extension, and priority in the channel structure.
    			After it completes, the pbx engine will continue dialplan execution at the specified location.
    			If no specific <replaceable>extension</replaceable>, or <replaceable>extension</replaceable> and
    			<replaceable>context</replaceable>, are specified, then this application will
    			just set the specified <replaceable>priority</replaceable> of the current extension.</para>
    			<para>At least a <replaceable>priority</replaceable> is required as an argument, or the goto will
    			return a <literal>-1</literal>,	and the channel and call will be terminated.</para>
    			<para>If the location that is put into the channel information is bogus, and asterisk cannot
    			find that location in the dialplan, then the execution engine will try to find and execute the code in
    			the <literal>i</literal> (invalid) extension in the current context. If that does not exist, it will try to execute the
    
    			<literal>h</literal> extension. If neither the <literal>h</literal> nor <literal>i</literal> extensions
    
    			have been defined, the channel is hung up, and the execution of instructions on the channel is terminated.
    			What this means is that, for example, you specify a context that does not exist, then
    			it will not be possible to find the <literal>h</literal> or <literal>i</literal> extensions,
    			and the call will terminate!</para>
    		</description>
    
    		<see-also>
    			<ref type="application">GotoIf</ref>
    			<ref type="application">GotoIfTime</ref>
    			<ref type="application">Gosub</ref>
    			<ref type="application">Macro</ref>
    		</see-also>
    
    	</application>
    	<application name="GotoIf" language="en_US">
    		<synopsis>
    			Conditional goto.
    		</synopsis>
    		<syntax argsep="?">
    			<parameter name="condition" required="true" />
    			<parameter name="destination" required="true" argsep=":">
    				<argument name="labeliftrue">
    
    					<para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
    					Takes the form similar to Goto() of [[context,]extension,]priority.</para>
    
    				</argument>
    				<argument name="labeliffalse">
    
    					<para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
    					Takes the form similar to Goto() of [[context,]extension,]priority.</para>
    
    				</argument>
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application will set the current context, extension, and priority in the channel structure
    			based on the evaluation of the given condition. After this application completes, the
    			pbx engine will continue dialplan execution at the specified location in the dialplan.
    			The labels are specified with the same syntax as used within the Goto application.
    			If the label chosen by the condition is omitted, no jump is performed, and the execution passes to the
    			next instruction. If the target location is bogus, and does not exist, the execution engine will try
    			to find and execute the code in the <literal>i</literal> (invalid) extension in the current context.
    			If that does not exist, it will try to execute the <literal>h</literal> extension.
    
    			If neither the <literal>h</literal> nor <literal>i</literal> extensions have been defined,
    
    			the channel is hung up, and the execution of instructions on the channel is terminated.
    			Remember that this command can set the current context, and if the context specified
    			does not exist, then it will not be able to find any 'h' or 'i' extensions there, and
    			the channel and call will both be terminated!.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Goto</ref>
    			<ref type="application">GotoIfTime</ref>
    			<ref type="application">GosubIf</ref>
    			<ref type="application">MacroIf</ref>
    		</see-also>
    
    	</application>
    	<application name="GotoIfTime" language="en_US">
    		<synopsis>
    			Conditional Goto based on the current time.
    		</synopsis>
    		<syntax argsep="?">
    			<parameter name="condition" required="true">
    				<argument name="times" required="true" />
    				<argument name="weekdays" required="true" />
    				<argument name="mdays" required="true" />
    				<argument name="months" required="true" />
    
    				<argument name="timezone" required="false" />
    
    			</parameter>
    			<parameter name="destination" required="true" argsep=":">
    
    				<argument name="labeliftrue">
    					<para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
    					Takes the form similar to Goto() of [[context,]extension,]priority.</para>
    				</argument>
    				<argument name="labeliffalse">
    					<para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
    					Takes the form similar to Goto() of [[context,]extension,]priority.</para>
    				</argument>
    
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application will set the context, extension, and priority in the channel structure
    			based on the evaluation of the given time specification. After this application completes,
    			the pbx engine will continue dialplan execution at the specified location in the dialplan.
    			If the current time is within the given time specification, the channel will continue at
    			<replaceable>labeliftrue</replaceable>. Otherwise the channel will continue at <replaceable>labeliffalse</replaceable>.
    			If the label chosen by the condition is omitted, no jump is performed, and execution passes to the next
    			instruction. If the target jump location is bogus, the same actions would be taken as for <literal>Goto</literal>.
    			Further information on the time specification can be found in examples
    			illustrating how to do time-based context includes in the dialplan.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">GotoIf</ref>
    
    			<ref type="application">Goto</ref>
    
    			<ref type="function">IFTIME</ref>
    
    			<ref type="function">TESTTIME</ref>
    
    	</application>
    	<application name="ImportVar" language="en_US">
    		<synopsis>
    			Import a variable from a channel into a new variable.
    		</synopsis>
    		<syntax argsep="=">
    			<parameter name="newvar" required="true" />
    			<parameter name="vardata" required="true">
    				<argument name="channelname" required="true" />
    				<argument name="variable" required="true" />
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application imports a <replaceable>variable</replaceable> from the specified
    			<replaceable>channel</replaceable> (as opposed to the current one) and stores it as a variable
    			(<replaceable>newvar</replaceable>) in the current channel (the channel that is calling this
    			application). Variables created by this application have the same inheritance properties as those
    			created with the <literal>Set</literal> application.</para>
    		</description>
    		<see-also>
    			<ref type="application">Set</ref>
    		</see-also>
    	</application>
    	<application name="Hangup" language="en_US">
    		<synopsis>
    			Hang up the calling channel.
    		</synopsis>
    		<syntax>
    			<parameter name="causecode">
    				<para>If a <replaceable>causecode</replaceable> is given the channel's
    				hangup cause will be set to the given value.</para>
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application will hang up the calling channel.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Answer</ref>
    			<ref type="application">Busy</ref>
    			<ref type="application">Congestion</ref>
    		</see-also>
    
    	</application>
    	<application name="Incomplete" language="en_US">
    		<synopsis>
    			Returns AST_PBX_INCOMPLETE value.
    		</synopsis>
    		<syntax>
    			<parameter name="n">
    				<para>If specified, then Incomplete will not attempt to answer the channel first.</para>
    				<note><para>Most channel types need to be in Answer state in order to receive DTMF.</para></note>
    			</parameter>
    		</syntax>
    		<description>
    			<para>Signals the PBX routines that the previous matched extension is incomplete
    			and that further input should be allowed before matching can be considered
    			to be complete.  Can be used within a pattern match when certain criteria warrants
    			a longer match.</para>
    		</description>
    	</application>
    	<application name="NoOp" language="en_US">
    		<synopsis>
    			Do Nothing (No Operation).
    		</synopsis>
    		<syntax>
    			<parameter name="text">
    				<para>Any text provided can be viewed at the Asterisk CLI.</para>
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application does nothing. However, it is useful for debugging purposes.</para>
    			<para>This method can be used to see the evaluations of variables or functions without having any effect.</para>
    		</description>
    		<see-also>
    			<ref type="application">Verbose</ref>
    
    			<ref type="application">Log</ref>
    
    		</see-also>
    	</application>
    	<application name="Proceeding" language="en_US">
    		<synopsis>
    			Indicate proceeding.
    		</synopsis>
    		<syntax />
    		<description>
    			<para>This application will request that a proceeding message be provided to the calling channel.</para>
    		</description>
    	</application>
    	<application name="Progress" language="en_US">
    		<synopsis>
    			Indicate progress.
    		</synopsis>
    		<syntax />
    		<description>
    			<para>This application will request that in-band progress information be provided to the calling channel.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Busy</ref>
    			<ref type="application">Congestion</ref>
    			<ref type="application">Ringing</ref>
    			<ref type="application">Playtones</ref>
    		</see-also>
    
    	</application>
    	<application name="RaiseException" language="en_US">
    		<synopsis>
    			Handle an exceptional condition.
    		</synopsis>
    		<syntax>
    			<parameter name="reason" required="true" />
    		</syntax>
    		<description>
    			<para>This application will jump to the <literal>e</literal> extension in the current context, setting the
    			dialplan function EXCEPTION(). If the <literal>e</literal> extension does not exist, the call will hangup.</para>
    		</description>
    
    		<see-also>
    			<ref type="function">Exception</ref>
    		</see-also>
    
    	</application>
    	<application name="Ringing" language="en_US">
    		<synopsis>
    			Indicate ringing tone.
    		</synopsis>
    		<syntax />
    		<description>
    			<para>This application will request that the channel indicate a ringing tone to the user.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Busy</ref>
    			<ref type="application">Congestion</ref>
    			<ref type="application">Progress</ref>
    			<ref type="application">Playtones</ref>
    		</see-also>
    
    	</application>
    	<application name="SayAlpha" language="en_US">
    		<synopsis>
    			Say Alpha.
    		</synopsis>
    		<syntax>
    			<parameter name="string" required="true" />
    		</syntax>
    		<description>
    
    			<para>This application will play the sounds that correspond to the letters
    			of the given <replaceable>string</replaceable>. If the channel variable
    			<variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive),
    			then this application will react to DTMF in the	same way as
    			<literal>Background</literal>.</para>
    
    		</description>
    
    		<see-also>
    			<ref type="application">SayDigits</ref>
    			<ref type="application">SayNumber</ref>
    			<ref type="application">SayPhonetic</ref>
    			<ref type="function">CHANNEL</ref>
    		</see-also>
    
    	</application>
    
    	<application name="SayAlphaCase" language="en_US">
    		<synopsis>
    			Say Alpha.
    		</synopsis>
    		<syntax>
    			<parameter name="casetype" required="true" >
    				<enumlist>
    					<enum name="a">
    						<para>Case sensitive (all) pronunciation.
    						(Ex: SayAlphaCase(a,aBc); - lowercase a uppercase b lowercase c).</para>
    					</enum>
    					<enum name="l">
    						<para>Case sensitive (lower) pronunciation.
    						(Ex: SayAlphaCase(l,aBc); - lowercase a b lowercase c).</para>
    					</enum>
    					<enum name="n">
    						<para>Case insensitive pronunciation. Equivalent to SayAlpha.
    						(Ex: SayAlphaCase(n,aBc) - a b c).</para>
    					</enum>
    					<enum name="u">
    						<para>Case sensitive (upper) pronunciation.
    						(Ex: SayAlphaCase(u,aBc); - a uppercase b c).</para>
    					</enum>
    				</enumlist>
    			</parameter>
    			<parameter name="string" required="true" />
    		</syntax>
    		<description>
    			<para>This application will play the sounds that correspond to the letters of the
    			given <replaceable>string</replaceable>.  Optionally, a <replaceable>casetype</replaceable> may be
    
    			specified.  This will be used for case-insensitive or case-sensitive pronunciations. If the channel
    			variable <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
    			application will react to DTMF in the same way as <literal>Background</literal>.</para>
    
    		</description>
    		<see-also>
    			<ref type="application">SayDigits</ref>
    			<ref type="application">SayNumber</ref>
    			<ref type="application">SayPhonetic</ref>
    			<ref type="application">SayAlpha</ref>
    			<ref type="function">CHANNEL</ref>
    		</see-also>
    	</application>
    
    	<application name="SayDigits" language="en_US">
    		<synopsis>
    			Say Digits.
    		</synopsis>
    		<syntax>
    			<parameter name="digits" required="true" />
    		</syntax>
    		<description>
    			<para>This application will play the sounds that correspond to the digits of
    
    			the given number. This will use the language that is currently set for the channel.
    			If the channel variable <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true'
    			(case insensitive), then this application will react to DTMF in the same way as
    			<literal>Background</literal>.</para>
    
    		</description>
    
    		<see-also>
    			<ref type="application">SayAlpha</ref>
    			<ref type="application">SayNumber</ref>
    			<ref type="application">SayPhonetic</ref>
    			<ref type="function">CHANNEL</ref>
    		</see-also>
    
    	</application>
    	<application name="SayNumber" language="en_US">
    		<synopsis>
    			Say Number.
    		</synopsis>
    		<syntax>
    			<parameter name="digits" required="true" />
    			<parameter name="gender" />
    		</syntax>
    		<description>
    
    			<para>This application will play the sounds that correspond to the given
    			<replaceable>digits</replaceable>. Optionally, a <replaceable>gender</replaceable> may be
    			specified. This will use the language that is currently set for the channel. See the CHANNEL()
    			function for more information on setting the language for the channel. If the channel variable
    			<variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
    			application will react to DTMF in the same way as <literal>Background</literal>.</para>
    
    		</description>
    
    		<see-also>
    			<ref type="application">SayAlpha</ref>
    			<ref type="application">SayDigits</ref>
    			<ref type="application">SayPhonetic</ref>
    			<ref type="function">CHANNEL</ref>
    		</see-also>
    
    	</application>
    	<application name="SayPhonetic" language="en_US">
    		<synopsis>
    			Say Phonetic.
    		</synopsis>
    		<syntax>
    			<parameter name="string" required="true" />
    		</syntax>
    		<description>
    			<para>This application will play the sounds from the phonetic alphabet that correspond to the
    
    			letters in the given <replaceable>string</replaceable>. If the channel variable
    			<variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
    			application will react to DTMF in the same way as <literal>Background</literal>.</para>
    
    		</description>
    
    		<see-also>
    			<ref type="application">SayAlpha</ref>
    			<ref type="application">SayDigits</ref>
    			<ref type="application">SayNumber</ref>
    		</see-also>
    
    	</application>
    	<application name="Set" language="en_US">
    		<synopsis>
    			Set channel variable or function value.
    		</synopsis>
    		<syntax argsep="=">
    			<parameter name="name" required="true" />
    			<parameter name="value" required="true" />
    		</syntax>
    		<description>
    			<para>This function can be used to set the value of channel variables or dialplan functions.
    			When setting variables, if the variable name is prefixed with <literal>_</literal>,
    			the variable will be inherited into channels created from the current channel.
    			If the variable name is prefixed with <literal>__</literal>, the variable will be
    			inherited into channels created from the current channel and all children channels.</para>
    			<note><para>If (and only if), in <filename>/etc/asterisk/asterisk.conf</filename>, you have
    
    			a <literal>[compat]</literal> category, and you have <literal>app_set = 1.4</literal> under that, then
    			the behavior of this app changes, and strips surrounding quotes from the right hand side as
    			it did previously in 1.4.
    
    			The advantages of not stripping out quoting, and not caring about the separator characters (comma and vertical bar)
    			were sufficient to make these changes in 1.6. Confusion about how many backslashes would be needed to properly
    			protect separators and quotes in various database access strings has been greatly
    			reduced by these changes.</para></note>
    		</description>
    
    		<see-also>
    			<ref type="application">MSet</ref>
    			<ref type="function">GLOBAL</ref>
    			<ref type="function">SET</ref>
    			<ref type="function">ENV</ref>
    		</see-also>
    
    	</application>
    	<application name="MSet" language="en_US">
    		<synopsis>
    			Set channel variable(s) or function value(s).
    		</synopsis>
    		<syntax>
    			<parameter name="set1" required="true" argsep="=">
    				<argument name="name1" required="true" />
    				<argument name="value1" required="true" />
    			</parameter>
    			<parameter name="set2" multiple="true" argsep="=">
    				<argument name="name2" required="true" />
    				<argument name="value2" required="true" />
    			</parameter>
    		</syntax>
    		<description>
    			<para>This function can be used to set the value of channel variables or dialplan functions.
    			When setting variables, if the variable name is prefixed with <literal>_</literal>,
    			the variable will be inherited into channels created from the current channel
    			If the variable name is prefixed with <literal>__</literal>, the variable will be
    			inherited into channels created from the current channel and all children channels.
    			MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus
    			prone to doing things that you may not expect. For example, it strips surrounding
    			double-quotes from the right-hand side (value). If you need to put a separator
    			character (comma or vert-bar), you will need to escape them by inserting a backslash
    			before them. Avoid its use if possible.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">Set</ref>
    		</see-also>
    
    	</application>
    	<application name="SetAMAFlags" language="en_US">
    		<synopsis>
    			Set the AMA Flags.
    		</synopsis>
    		<syntax>
    			<parameter name="flag" />
    		</syntax>
    		<description>
    			<para>This application will set the channel's AMA Flags for billing purposes.</para>
    
    			<warning><para>This application is deprecated. Please use the CHANNEL function instead.</para></warning>
    
    		</description>
    
    		<see-also>
    			<ref type="function">CDR</ref>
    
    			<ref type="function">CHANNEL</ref>
    
    	</application>
    	<application name="Wait" language="en_US">
    		<synopsis>
    			Waits for some time.
    		</synopsis>
    		<syntax>
    			<parameter name="seconds" required="true">
    				<para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
    				application to wait for 1.5 seconds.</para>
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para>
    		</description>
    	</application>
    	<application name="WaitExten" language="en_US">
    		<synopsis>
    			Waits for an extension to be entered.
    		</synopsis>
    		<syntax>
    			<parameter name="seconds">
    				<para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
    				application to wait for 1.5 seconds.</para>
    			</parameter>
    			<parameter name="options">
    				<optionlist>
    					<option name="m">
    						<para>Provide music on hold to the caller while waiting for an extension.</para>
    						<argument name="x">
    
    							<para>Specify the class for music on hold. <emphasis>CHANNEL(musicclass) will
    							be used instead if set</emphasis></para>
    
    						</argument>
    					</option>
    				</optionlist>
    			</parameter>
    		</syntax>
    		<description>
    			<para>This application waits for the user to enter a new extension for a specified number
    			of <replaceable>seconds</replaceable>.</para>
    
    			<xi:include xpointer="xpointer(/docs/application[@name='Macro']/description/warning[2])" />
    
    		</description>
    		<see-also>
    			<ref type="application">Background</ref>
    
    			<ref type="function">TIMEOUT</ref>
    
    		</see-also>
    	</application>
    	<function name="EXCEPTION" language="en_US">
    		<synopsis>
    			Retrieve the details of the current dialplan exception.
    		</synopsis>
    		<syntax>
    			<parameter name="field" required="true">
    				<para>The following fields are available for retrieval:</para>
    				<enumlist>
    					<enum name="reason">
    						<para>INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom
    						value set by the RaiseException() application</para>
    					</enum>
    					<enum name="context">
    						<para>The context executing when the exception occurred.</para>
    					</enum>
    					<enum name="exten">
    						<para>The extension executing when the exception occurred.</para>
    					</enum>
    					<enum name="priority">
    						<para>The numeric priority executing when the exception occurred.</para>
    					</enum>
    				</enumlist>
    			</parameter>
    		</syntax>
    		<description>
    			<para>Retrieve the details (specified <replaceable>field</replaceable>) of the current dialplan exception.</para>
    		</description>
    
    		<see-also>
    			<ref type="application">RaiseException</ref>
    		</see-also>
    
    	<function name="TESTTIME" language="en_US">
    		<synopsis>
    			Sets a time to be used with the channel to test logical conditions.
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    		</synopsis>
    
    		<syntax>
    			<parameter name="date" required="true" argsep=" ">
    				<para>Date in ISO 8601 format</para>
    			</parameter>
    			<parameter name="time" required="true" argsep=" ">
    				<para>Time in HH:MM:SS format (24-hour time)</para>
    			</parameter>
    			<parameter name="zone" required="false">
    				<para>Timezone name</para>
    			</parameter>
    		</syntax>
    		<description>
    			<para>To test dialplan timing conditions at times other than the current time, use
    			this function to set an alternate date and time.  For example, you may wish to evaluate
    			whether a location will correctly identify to callers that the area is closed on Christmas
    			Day, when Christmas would otherwise fall on a day when the office is normally open.</para>
    
    		</description>
    
    		<see-also>
    			<ref type="application">GotoIfTime</ref>
    		</see-also>
    	</function>
    
    	<manager name="ShowDialPlan" language="en_US">
    		<synopsis>
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    			Show dialplan contexts and extensions
    
    		</synopsis>
    		<syntax>
    			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
    			<parameter name="Extension">
    				<para>Show a specific extension.</para>
    			</parameter>
    			<parameter name="Context">
    				<para>Show a specific context.</para>
    			</parameter>
    		</syntax>
    		<description>
    			<para>Show dialplan contexts and extensions. Be aware that showing the full dialplan
    			may take a lot of capacity.</para>
    		</description>
    	</manager>
    
    	<manager name="ExtensionStateList" language="en_US">
    		<synopsis>
    			List the current known extension states.
    		</synopsis>
    		<syntax>
    			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
    		</syntax>
    		<description>
    			<para>This will list out all known extension states in a
    			sequence of <replaceable>ExtensionStatus</replaceable> events.
    			When finished, a <replaceable>ExtensionStateListComplete</replaceable> event
    			will be emitted.</para>
    		</description>
    		<see-also>
    			<ref type="manager">ExtensionState</ref>
    			<ref type="function">HINT</ref>
    			<ref type="function">EXTENSION_STATE</ref>
    		</see-also>
    		<responses>
    			<list-elements>
    				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ExtensionStatus'])" />
    			</list-elements>
    			<managerEvent name="ExtensionStateListComplete" language="en_US">
    				<managerEventInstance class="EVENT_FLAG_COMMAND">
    					<synopsis>
    						Indicates the end of the list the current known extension states.
    					</synopsis>
    					<syntax>
    						<parameter name="EventList">
    							<para>Conveys the status of the event list.</para>
    						</parameter>
    						<parameter name="ListItems">
    							<para>Conveys the number of statuses reported.</para>
    						</parameter>
    					</syntax>
    				</managerEventInstance>
    			</managerEvent>
    		</responses>
    	</manager>
    
    #ifdef LOW_MEMORY
    #define EXT_DATA_SIZE 256
    #else
    #define EXT_DATA_SIZE 8192
    #endif
    
    #define VAR_BUF_SIZE 4096
    
    #define	VAR_NORMAL		1
    #define	VAR_SOFTTRAN	2
    #define	VAR_HARDTRAN	3
    
    
    #define BACKGROUND_SKIP		(1 << 0)
    #define BACKGROUND_NOANSWER	(1 << 1)
    
    #define BACKGROUND_MATCHEXTEN	(1 << 2)
    #define BACKGROUND_PLAYBACK	(1 << 3)
    
    AST_APP_OPTIONS(background_opts, {
    	AST_APP_OPTION('s', BACKGROUND_SKIP),
    	AST_APP_OPTION('n', BACKGROUND_NOANSWER),
    	AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
    	AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
    
    #define WAITEXTEN_DIALTONE	(1 << 1)
    
    AST_APP_OPTIONS(waitexten_opts, {
    
    	AST_APP_OPTION_ARG('d', WAITEXTEN_DIALTONE, 0),
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct ast_context;
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    AST_THREADSTORAGE(switch_data);
    
    AST_THREADSTORAGE(extensionstate_buf);
    
    /*!
     * \brief A thread local indicating whether the current thread can run
     * 'dangerous' dialplan functions.
     */
    AST_THREADSTORAGE(thread_inhibit_escalations_tl);
    
    /*!
     * \brief Set to true (non-zero) to globally allow all dangerous dialplan
     * functions to run.
     */
    static int live_dangerously;
    
    Russell Bryant's avatar
    Russell Bryant committed
    /*!
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
       \brief ast_exten: An extension
    
    	The dialplan is saved as a linked list with each context
    	having it's own linked list of extensions - one item per
    	priority.
    */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct ast_exten {
    
    Russell Bryant's avatar
    Russell Bryant committed
    	char *exten;			/*!< Extension name */
    	int matchcid;			/*!< Match caller id ? */
    
    	const char *cidmatch;		/*!< Caller id to match for this extension */
    
    Russell Bryant's avatar
    Russell Bryant committed
    	int priority;			/*!< Priority */
    
    Russell Bryant's avatar
    Russell Bryant committed
    	struct ast_context *parent;	/*!< The context this extension belongs to  */
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    	const char *app;		/*!< Application to execute */
    
    	struct ast_app *cached_app;     /*!< Cached location of application */
    
    Russell Bryant's avatar
    Russell Bryant committed
    	void *data;			/*!< Data to use (arguments) */
    	void (*datad)(void *);		/*!< Data destructor */
    	struct ast_exten *peer;		/*!< Next higher priority with our extension */
    
    Steve Murphy's avatar
    Steve Murphy committed
    	struct ast_hashtab *peer_table;    /*!< Priorities list in hashtab form -- only on the head of the peer list */
    	struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
    
    Russell Bryant's avatar
    Russell Bryant committed
    	const char *registrar;		/*!< Registrar */
    	struct ast_exten *next;		/*!< Extension with a greater ID */
    
    /*! \brief ast_include: include= support in extensions.conf */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct ast_include {
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
    	const char *name;
    
    	const char *rname;			/*!< Context to include */
    
    Russell Bryant's avatar
    Russell Bryant committed
    	const char *registrar;			/*!< Registrar */
    	int hastime;				/*!< If time construct exists */
    	struct ast_timing timing;               /*!< time construct */
    	struct ast_include *next;		/*!< Link them together */
    
    /*! \brief ast_sw: Switch statement in extensions.conf */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct ast_sw {
    
    Russell Bryant's avatar
    Russell Bryant committed
    	const char *registrar;			/*!< Registrar */
    	char *data;				/*!< Data load */
    
    /*! \brief ast_ignorepat: Ignore patterns in dial plan */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct ast_ignorepat {
    
    	const char *registrar;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_ignorepat *next;
    
    /*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
    struct match_char
    {
    	int is_pattern; /* the pattern started with '_' */
    	int deleted;    /* if this is set, then... don't return it */
    	int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
    	struct match_char *alt_char;
    	struct match_char *next_char;
    	struct ast_exten *exten; /* attached to last char of a pattern for exten */
    
    	char x[1];       /* the pattern itself-- matches a single char */
    
    };
    
    struct scoreboard  /* make sure all fields are 0 before calling new_find_extension */
    {
    	int total_specificity;
    	int total_length;
    	char last_char;   /* set to ! or . if they are the end of the pattern */
    	int canmatch;     /* if the string to match was just too short */
    
    	struct ast_exten *canmatch_exten;
    	struct ast_exten *exten;
    };
    
    
    /*! \brief ast_context: An extension context */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct ast_context {
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    	ast_rwlock_t lock;			/*!< A lock to prevent multiple threads from clobbering the context */
    
    	struct ast_exten *root;			/*!< The root of the list of extensions */
    
    Steve Murphy's avatar
    Steve Murphy committed
    	struct ast_hashtab *root_table;            /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree  */
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    	struct match_char *pattern_tree;        /*!< A tree to speed up extension pattern matching */
    
    	struct ast_context *next;		/*!< Link them together */
    	struct ast_include *includes;		/*!< Include other contexts */
    	struct ast_ignorepat *ignorepats;	/*!< Patterns for which to continue playing dialtone */
    
    Steve Murphy's avatar
    Steve Murphy committed
    	char *registrar;			/*!< Registrar -- make sure you malloc this, as the registrar may have to survive module unloads */
    
    Steve Murphy's avatar
    Steve Murphy committed
    	int refcount;                   /*!< each module that would have created this context should inc/dec this as appropriate */
    
    	AST_LIST_HEAD_NOLOCK(, ast_sw) alts;	/*!< Alternative switches */
    
    	ast_mutex_t macrolock;			/*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
    
    	char name[0];				/*!< Name of the context */
    
    /*! \brief ast_app: A registered application */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct ast_app {
    
    	int (*execute)(struct ast_channel *chan, const char *data);
    
    	AST_DECLARE_STRING_FIELDS(
    		AST_STRING_FIELD(synopsis);     /*!< Synopsis text for 'show applications' */
    		AST_STRING_FIELD(description);  /*!< Description (help text) for 'show application &lt;name&gt;' */
    		AST_STRING_FIELD(syntax);       /*!< Syntax text for 'core show applications' */
    		AST_STRING_FIELD(arguments);    /*!< Arguments description */
    		AST_STRING_FIELD(seealso);      /*!< See also */
    	);
    
    #ifdef AST_XML_DOCS
    	enum ast_doc_src docsrc;		/*!< Where the documentation come from. */
    #endif