Fri Jul 15 2011 11:56:57

Asterisk developer's documentation


app_dial.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2008, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief dial() & retrydial() - Trivial application to dial a channel and send an URL on answer
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  *
00025  * \ingroup applications
00026  */
00027 
00028 /*** MODULEINFO
00029    <depend>chan_local</depend>
00030  ***/
00031 
00032 
00033 #include "asterisk.h"
00034 
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 319528 $")
00036 
00037 #include <sys/time.h>
00038 #include <sys/signal.h>
00039 #include <sys/stat.h>
00040 #include <netinet/in.h>
00041 
00042 #include "asterisk/paths.h" /* use ast_config_AST_DATA_DIR */
00043 #include "asterisk/lock.h"
00044 #include "asterisk/file.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/pbx.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/translate.h"
00049 #include "asterisk/say.h"
00050 #include "asterisk/config.h"
00051 #include "asterisk/features.h"
00052 #include "asterisk/musiconhold.h"
00053 #include "asterisk/callerid.h"
00054 #include "asterisk/utils.h"
00055 #include "asterisk/app.h"
00056 #include "asterisk/causes.h"
00057 #include "asterisk/rtp.h"
00058 #include "asterisk/cdr.h"
00059 #include "asterisk/manager.h"
00060 #include "asterisk/privacy.h"
00061 #include "asterisk/stringfields.h"
00062 #include "asterisk/global_datastores.h"
00063 #include "asterisk/dsp.h"
00064 
00065 /*** DOCUMENTATION
00066    <application name="Dial" language="en_US">
00067       <synopsis>
00068          Attempt to connect to another device or endpoint and bridge the call.
00069       </synopsis>
00070       <syntax>
00071          <parameter name="Technology/Resource" required="true" argsep="&amp;">
00072             <argument name="Technology/Resource" required="true">
00073                <para>Specification of the device(s) to dial.  These must be in the format of
00074                <literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
00075                represents a particular channel driver, and <replaceable>Resource</replaceable>
00076                represents a resource available to that particular channel driver.</para>
00077             </argument>
00078             <argument name="Technology2/Resource2" required="false" multiple="true">
00079                <para>Optional extra devices to dial in parallel</para>
00080                <para>If you need more then one enter them as
00081                Technology2/Resource2&amp;Technology3/Resourse3&amp;.....</para>
00082             </argument>
00083          </parameter>
00084          <parameter name="timeout" required="false">
00085             <para>Specifies the number of seconds we attempt to dial the specified devices</para>
00086             <para>If not specified, this defaults to 136 years.</para>
00087          </parameter>
00088          <parameter name="options" required="false">
00089             <optionlist>
00090             <option name="A">
00091                <argument name="x" required="true">
00092                   <para>The file to play to the called party</para>
00093                </argument>
00094                <para>Play an announcement to the called party, where <replaceable>x</replaceable> is the prompt to be played</para>
00095             </option>
00096             <option name="C">
00097                <para>Reset the call detail record (CDR) for this call.</para>
00098             </option>
00099             <option name="c">
00100                <para>If the Dial() application cancels this call, always set the flag to tell the channel
00101                driver that the call is answered elsewhere.</para>
00102             </option>
00103             <option name="d">
00104                <para>Allow the calling user to dial a 1 digit extension while waiting for
00105                a call to be answered. Exit to that extension if it exists in the
00106                current context, or the context defined in the <variable>EXITCONTEXT</variable> variable,
00107                if it exists.</para>
00108             </option>
00109             <option name="D" argsep=":">
00110                <argument name="called" />
00111                <argument name="calling" />
00112                <para>Send the specified DTMF strings <emphasis>after</emphasis> the called
00113                party has answered, but before the call gets bridged. The 
00114                <replaceable>called</replaceable> DTMF string is sent to the called party, and the 
00115                <replaceable>calling</replaceable> DTMF string is sent to the calling party. Both arguments 
00116                can be used alone.</para>
00117             </option>
00118             <option name="e">
00119                <para>Execute the <literal>h</literal> extension for peer after the call ends</para>
00120             </option>
00121             <option name="f">
00122                <para>Force the callerid of the <emphasis>calling</emphasis> channel to be set as the
00123                extension associated with the channel using a dialplan <literal>hint</literal>.
00124                For example, some PSTNs do not allow CallerID to be set to anything
00125                other than the number assigned to the caller.</para>
00126             </option>
00127             <option name="F" argsep="^">
00128                <argument name="context" required="false" />
00129                <argument name="exten" required="false" />
00130                <argument name="priority" required="true" />
00131                <para>When the caller hangs up, transfer the called party
00132                to the specified destination and continue execution at that location.</para>
00133             </option>
00134             <option name="g">
00135                <para>Proceed with dialplan execution at the next priority in the current extension if the
00136                destination channel hangs up.</para>
00137             </option>
00138             <option name="G" argsep="^">
00139                <argument name="context" required="false" />
00140                <argument name="exten" required="false" />
00141                <argument name="priority" required="true" />
00142                <para>If the call is answered, transfer the calling party to
00143                the specified <replaceable>priority</replaceable> and the called party to the specified 
00144                <replaceable>priority</replaceable> plus one.</para>
00145                <note>
00146                   <para>You cannot use any additional action post answer options in conjunction with this option.</para>
00147                </note>
00148             </option>
00149             <option name="h">
00150                <para>Allow the called party to hang up by sending the <literal>*</literal> DTMF digit.</para>
00151             </option>
00152             <option name="H">
00153                <para>Allow the calling party to hang up by hitting the <literal>*</literal> DTMF digit.</para>
00154             </option>
00155             <option name="i">
00156                <para>Asterisk will ignore any forwarding requests it may receive on this dial attempt.</para>
00157             </option>
00158             <option name="k">
00159                <para>Allow the called party to enable parking of the call by sending
00160                the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
00161             </option>
00162             <option name="K">
00163                <para>Allow the calling party to enable parking of the call by sending
00164                the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
00165             </option>
00166             <option name="L" argsep=":">
00167                <argument name="x" required="true">
00168                   <para>Maximum call time, in milliseconds</para>
00169                </argument>
00170                <argument name="y">
00171                   <para>Warning time, in milliseconds</para>
00172                </argument>
00173                <argument name="z">
00174                   <para>Repeat time, in milliseconds</para>
00175                </argument>
00176                <para>Limit the call to <replaceable>x</replaceable> milliseconds. Play a warning when <replaceable>y</replaceable> milliseconds are
00177                left. Repeat the warning every <replaceable>z</replaceable> milliseconds until time expires.</para>
00178                <para>This option is affected by the following variables:</para>
00179                <variablelist>
00180                   <variable name="LIMIT_PLAYAUDIO_CALLER">
00181                      <value name="yes" default="true" />
00182                      <value name="no" />
00183                      <para>If set, this variable causes Asterisk to play the prompts to the caller.</para>
00184                   </variable>
00185                   <variable name="LIMIT_PLAYAUDIO_CALLEE">
00186                      <value name="yes" />
00187                      <value name="no" default="true"/>
00188                      <para>If set, this variable causes Asterisk to play the prompts to the callee.</para>
00189                   </variable>
00190                   <variable name="LIMIT_TIMEOUT_FILE">
00191                      <value name="filename"/>
00192                      <para>If specified, <replaceable>filename</replaceable> specifies the sound prompt to play when the timeout is reached.
00193                      If not set, the time remaining will be announced.</para>
00194                   </variable>
00195                   <variable name="LIMIT_CONNECT_FILE">
00196                      <value name="filename"/>
00197                      <para>If specified, <replaceable>filename</replaceable> specifies the sound prompt to play when the call begins.
00198                      If not set, the time remaining will be announced.</para>
00199                   </variable>
00200                   <variable name="LIMIT_WARNING_FILE">
00201                      <value name="filename"/>
00202                      <para>If specified, <replaceable>filename</replaceable> specifies the sound prompt to play as
00203                      a warning when time <replaceable>x</replaceable> is reached. If not set, the time remaining will be announced.</para>
00204                   </variable>
00205                </variablelist>
00206             </option>
00207             <option name="m">
00208                <argument name="class" required="false"/>
00209                <para>Provide hold music to the calling party until a requested
00210                channel answers. A specific music on hold <replaceable>class</replaceable>
00211                (as defined in <filename>musiconhold.conf</filename>) can be specified.</para>
00212             </option>
00213             <option name="M" argsep="^">
00214                <argument name="macro" required="true">
00215                   <para>Name of the macro that should be executed.</para>
00216                </argument>
00217                <argument name="arg" multiple="true">
00218                   <para>Macro arguments</para>
00219                </argument>
00220                <para>Execute the specified <replaceable>macro</replaceable> for the <emphasis>called</emphasis> channel 
00221                before connecting to the calling channel. Arguments can be specified to the Macro
00222                using <literal>^</literal> as a delimiter. The macro can set the variable
00223                <variable>MACRO_RESULT</variable> to specify the following actions after the macro is
00224                finished executing:</para>
00225                <variablelist>
00226                   <variable name="MACRO_RESULT">
00227                      <para>If set, this action will be taken after the macro finished executing.</para>
00228                      <value name="ABORT">
00229                         Hangup both legs of the call
00230                      </value>
00231                      <value name="CONGESTION">
00232                         Behave as if line congestion was encountered
00233                      </value>
00234                      <value name="BUSY">
00235                         Behave as if a busy signal was encountered
00236                      </value>
00237                      <value name="CONTINUE">
00238                         Hangup the called party and allow the calling party to continue dialplan execution at the next priority
00239                      </value>
00240                      <!-- TODO: Fix this syntax up, once we've figured out how to specify the GOTO syntax -->
00241                      <value name="GOTO:&lt;context&gt;^&lt;exten&gt;^&lt;priority&gt;">
00242                         Transfer the call to the specified destination.
00243                      </value>
00244                   </variable>
00245                </variablelist>
00246                <note>
00247                   <para>You cannot use any additional action post answer options in conjunction
00248                   with this option. Also, pbx services are not run on the peer (called) channel,
00249                   so you will not be able to set timeouts via the TIMEOUT() function in this macro.</para>
00250                </note>
00251                <warning><para>Be aware of the limitations that macros have, specifically with regards to use of
00252                the <literal>WaitExten</literal> application. For more information, see the documentation for
00253                Macro()</para></warning>
00254             </option>
00255             <option name="n">
00256                     <argument name="delete">
00257                        <para>With <replaceable>delete</replaceable> either not specified or set to <literal>0</literal>,
00258                   the recorded introduction will not be deleted if the caller hangs up while the remote party has not
00259                   yet answered.</para>
00260                   <para>With <replaceable>delete</replaceable> set to <literal>1</literal>, the introduction will
00261                   always be deleted.</para>
00262                </argument>
00263                <para>This option is a modifier for the call screening/privacy mode. (See the 
00264                <literal>p</literal> and <literal>P</literal> options.) It specifies
00265                that no introductions are to be saved in the <directory>priv-callerintros</directory>
00266                directory.</para>
00267             </option>
00268             <option name="N">
00269                <para>This option is a modifier for the call screening/privacy mode. It specifies
00270                that if Caller*ID is present, do not screen the call.</para>
00271             </option>
00272             <option name="o">
00273                <para>Specify that the Caller*ID that was present on the <emphasis>calling</emphasis> channel
00274                be set as the Caller*ID on the <emphasis>called</emphasis> channel. This was the
00275                behavior of Asterisk 1.0 and earlier.</para>
00276             </option>
00277             <option name="O">
00278                <argument name="mode">
00279                   <para>With <replaceable>mode</replaceable> either not specified or set to <literal>1</literal>,
00280                   the originator hanging up will cause the phone to ring back immediately.</para>
00281                   <para>With <replaceable>mode</replaceable> set to <literal>2</literal>, when the operator 
00282                   flashes the trunk, it will ring their phone back.</para>
00283                </argument>
00284                <para>Enables <emphasis>operator services</emphasis> mode.  This option only
00285                works when bridging a DAHDI channel to another DAHDI channel
00286                only. if specified on non-DAHDI interfaces, it will be ignored.
00287                When the destination answers (presumably an operator services
00288                station), the originator no longer has control of their line.
00289                They may hang up, but the switch will not release their line
00290                until the destination party (the operator) hangs up.</para>
00291             </option>
00292             <option name="p">
00293                <para>This option enables screening mode. This is basically Privacy mode
00294                without memory.</para>
00295             </option>
00296             <option name="P">
00297                <argument name="x" />
00298                <para>Enable privacy mode. Use <replaceable>x</replaceable> as the family/key in the AstDB database if
00299                it is provided. The current extension is used if a database family/key is not specified.</para>
00300             </option>
00301             <option name="r">
00302                <para>Indicate ringing to the calling party, even if the called party isn't actually ringing. Pass no audio to the calling
00303                party until the called channel has answered.</para>
00304             </option>
00305             <option name="S">
00306                <argument name="x" required="true" />
00307                <para>Hang up the call <replaceable>x</replaceable> seconds <emphasis>after</emphasis> the called party has
00308                answered the call.</para>
00309             </option>
00310             <option name="t">
00311                <para>Allow the called party to transfer the calling party by sending the
00312                DTMF sequence defined in <filename>features.conf</filename>. This setting does not perform policy enforcement on
00313                transfers initiated by other methods.</para>
00314             </option>
00315             <option name="T">
00316                <para>Allow the calling party to transfer the called party by sending the
00317                DTMF sequence defined in <filename>features.conf</filename>. This setting does not perform policy enforcement on
00318                transfers initiated by other methods.</para>
00319             </option>
00320             <option name="U" argsep="^">
00321                <argument name="x" required="true">
00322                   <para>Name of the subroutine to execute via Gosub</para>
00323                </argument>
00324                <argument name="arg" multiple="true" required="false">
00325                   <para>Arguments for the Gosub routine</para>
00326                </argument>
00327                <para>Execute via Gosub the routine <replaceable>x</replaceable> for the <emphasis>called</emphasis> channel before connecting
00328                to the calling channel. Arguments can be specified to the Gosub
00329                using <literal>^</literal> as a delimiter. The Gosub routine can set the variable
00330                <variable>GOSUB_RESULT</variable> to specify the following actions after the Gosub returns.</para>
00331                <variablelist>
00332                   <variable name="GOSUB_RESULT">
00333                      <value name="ABORT">
00334                         Hangup both legs of the call.
00335                      </value>
00336                      <value name="CONGESTION">
00337                         Behave as if line congestion was encountered.
00338                      </value>
00339                      <value name="BUSY">
00340                         Behave as if a busy signal was encountered.
00341                      </value>
00342                      <value name="CONTINUE">
00343                         Hangup the called party and allow the calling party
00344                         to continue dialplan execution at the next priority.
00345                      </value>
00346                      <!-- TODO: Fix this syntax up, once we've figured out how to specify the GOTO syntax -->
00347                      <value name="GOTO:&lt;context&gt;^&lt;exten&gt;^&lt;priority&gt;">
00348                         Transfer the call to the specified priority. Optionally, an extension, or
00349                         extension and priority can be specified.
00350                      </value>
00351                   </variable>
00352                </variablelist>
00353                <note>
00354                   <para>You cannot use any additional action post answer options in conjunction
00355                   with this option. Also, pbx services are not run on the peer (called) channel,
00356                   so you will not be able to set timeouts via the TIMEOUT() function in this routine.</para>
00357                </note>
00358             </option>
00359             <option name="w">
00360                <para>Allow the called party to enable recording of the call by sending
00361                the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
00362             </option>
00363             <option name="W">
00364                <para>Allow the calling party to enable recording of the call by sending
00365                the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
00366             </option>
00367             <option name="x">
00368                <para>Allow the called party to enable recording of the call by sending
00369                the DTMF sequence defined for one-touch automixmonitor in <filename>features.conf</filename>.</para>
00370             </option>
00371             <option name="X">
00372                <para>Allow the calling party to enable recording of the call by sending
00373                the DTMF sequence defined for one-touch automixmonitor in <filename>features.conf</filename>.</para>
00374             </option>
00375             </optionlist>
00376          </parameter>
00377          <parameter name="URL">
00378             <para>The optional URL will be sent to the called party if the channel driver supports it.</para>
00379          </parameter>
00380       </syntax>
00381       <description>
00382          <para>This application will place calls to one or more specified channels. As soon
00383          as one of the requested channels answers, the originating channel will be
00384          answered, if it has not already been answered. These two channels will then
00385          be active in a bridged call. All other channels that were requested will then
00386          be hung up.</para>
00387 
00388          <para>Unless there is a timeout specified, the Dial application will wait
00389          indefinitely until one of the called channels answers, the user hangs up, or
00390          if all of the called channels are busy or unavailable. Dialplan executing will
00391          continue if no requested channels can be called, or if the timeout expires.
00392          This application will report normal termination if the originating channel
00393          hangs up, or if the call is bridged and either of the parties in the bridge
00394          ends the call.</para>
00395 
00396          <para>If the <variable>OUTBOUND_GROUP</variable> variable is set, all peer channels created by this
00397          application will be put into that group (as in Set(GROUP()=...).
00398          If the <variable>OUTBOUND_GROUP_ONCE</variable> variable is set, all peer channels created by this
00399          application will be put into that group (as in Set(GROUP()=...). Unlike OUTBOUND_GROUP,
00400          however, the variable will be unset after use.</para>
00401 
00402          <para>This application sets the following channel variables:</para>
00403          <variablelist>
00404             <variable name="DIALEDTIME">
00405                <para>This is the time from dialing a channel until when it is disconnected.</para>
00406             </variable>
00407             <variable name="ANSWEREDTIME">
00408                <para>This is the amount of time for actual call.</para>
00409             </variable>
00410             <variable name="DIALSTATUS">
00411                <para>This is the status of the call</para>
00412                <value name="CHANUNAVAIL" />
00413                <value name="CONGESTION" />
00414                <value name="NOANSWER" />
00415                <value name="BUSY" />
00416                <value name="ANSWER" />
00417                <value name="CANCEL" />
00418                <value name="DONTCALL">
00419                   For the Privacy and Screening Modes.
00420                   Will be set if the called party chooses to send the calling party to the 'Go Away' script.
00421                </value>
00422                <value name="TORTURE">
00423                   For the Privacy and Screening Modes.
00424                   Will be set if the called party chooses to send the calling party to the 'torture' script.
00425                </value>
00426                <value name="INVALIDARGS" />
00427             </variable>
00428          </variablelist>
00429       </description>
00430    </application>
00431    <application name="RetryDial" language="en_US">
00432       <synopsis>
00433          Place a call, retrying on failure allowing an optional exit extension.
00434       </synopsis>
00435       <syntax>
00436          <parameter name="announce" required="true">
00437             <para>Filename of sound that will be played when no channel can be reached</para>
00438          </parameter>
00439          <parameter name="sleep" required="true">
00440             <para>Number of seconds to wait after a dial attempt failed before a new attempt is made</para>
00441          </parameter>
00442          <parameter name="retries" required="true">
00443             <para>Number of retries</para>
00444             <para>When this is reached flow will continue at the next priority in the dialplan</para>
00445          </parameter>
00446          <parameter name="dialargs" required="true">
00447             <para>Same format as arguments provided to the Dial application</para>
00448          </parameter>
00449       </syntax>
00450       <description>
00451          <para>This application will attempt to place a call using the normal Dial application.
00452          If no channel can be reached, the <replaceable>announce</replaceable> file will be played.
00453          Then, it will wait <replaceable>sleep</replaceable> number of seconds before retrying the call.
00454          After <replaceable>retries</replaceable> number of attempts, the calling channel will continue at the next priority in the dialplan.
00455          If the <replaceable>retries</replaceable> setting is set to 0, this application will retry endlessly.
00456          While waiting to retry a call, a 1 digit extension may be dialed. If that
00457          extension exists in either the context defined in <variable>EXITCONTEXT</variable> or the current
00458          one, The call will jump to that extension immediately.
00459          The <replaceable>dialargs</replaceable> are specified in the same format that arguments are provided
00460          to the Dial application.</para>
00461       </description>
00462    </application>
00463  ***/
00464 
00465 static char *app = "Dial";
00466 static char *rapp = "RetryDial";
00467 
00468 enum {
00469    OPT_ANNOUNCE =          (1 << 0),
00470    OPT_RESETCDR =          (1 << 1),
00471    OPT_DTMF_EXIT =         (1 << 2),
00472    OPT_SENDDTMF =          (1 << 3),
00473    OPT_FORCECLID =         (1 << 4),
00474    OPT_GO_ON =             (1 << 5),
00475    OPT_CALLEE_HANGUP =     (1 << 6),
00476    OPT_CALLER_HANGUP =     (1 << 7),
00477    OPT_DURATION_LIMIT =    (1 << 9),
00478    OPT_MUSICBACK =         (1 << 10),
00479    OPT_CALLEE_MACRO =      (1 << 11),
00480    OPT_SCREEN_NOINTRO =    (1 << 12),
00481    OPT_SCREEN_NOCLID =     (1 << 13),
00482    OPT_ORIGINAL_CLID =     (1 << 14),
00483    OPT_SCREENING =         (1 << 15),
00484    OPT_PRIVACY =           (1 << 16),
00485    OPT_RINGBACK =          (1 << 17),
00486    OPT_DURATION_STOP =     (1 << 18),
00487    OPT_CALLEE_TRANSFER =   (1 << 19),
00488    OPT_CALLER_TRANSFER =   (1 << 20),
00489    OPT_CALLEE_MONITOR =    (1 << 21),
00490    OPT_CALLER_MONITOR =    (1 << 22),
00491    OPT_GOTO =              (1 << 23),
00492    OPT_OPERMODE =          (1 << 24),
00493    OPT_CALLEE_PARK =       (1 << 25),
00494    OPT_CALLER_PARK =       (1 << 26),
00495    OPT_IGNORE_FORWARDING = (1 << 27),
00496    OPT_CALLEE_GOSUB =      (1 << 28),
00497    OPT_CALLEE_MIXMONITOR = (1 << 29),
00498    OPT_CALLER_MIXMONITOR = (1 << 30),
00499 };
00500 
00501 #define DIAL_STILLGOING      (1 << 31)
00502 #define DIAL_NOFORWARDHTML   ((uint64_t)1 << 32) /* flags are now 64 bits, so keep it up! */
00503 #define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 33)
00504 #define OPT_PEER_H           ((uint64_t)1 << 34)
00505 #define OPT_CALLEE_GO_ON     ((uint64_t)1 << 35)
00506 
00507 enum {
00508    OPT_ARG_ANNOUNCE = 0,
00509    OPT_ARG_SENDDTMF,
00510    OPT_ARG_GOTO,
00511    OPT_ARG_DURATION_LIMIT,
00512    OPT_ARG_MUSICBACK,
00513    OPT_ARG_CALLEE_MACRO,
00514    OPT_ARG_CALLEE_GOSUB,
00515    OPT_ARG_CALLEE_GO_ON,
00516    OPT_ARG_PRIVACY,
00517    OPT_ARG_DURATION_STOP,
00518    OPT_ARG_OPERMODE,
00519    OPT_ARG_SCREEN_NOINTRO,
00520    /* note: this entry _MUST_ be the last one in the enum */
00521    OPT_ARG_ARRAY_SIZE,
00522 };
00523 
00524 AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
00525    AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
00526    AST_APP_OPTION('C', OPT_RESETCDR),
00527    AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE),
00528    AST_APP_OPTION('d', OPT_DTMF_EXIT),
00529    AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
00530    AST_APP_OPTION('e', OPT_PEER_H),
00531    AST_APP_OPTION('f', OPT_FORCECLID),
00532    AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
00533    AST_APP_OPTION('g', OPT_GO_ON),
00534    AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO),
00535    AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
00536    AST_APP_OPTION('H', OPT_CALLER_HANGUP),
00537    AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
00538    AST_APP_OPTION('k', OPT_CALLEE_PARK),
00539    AST_APP_OPTION('K', OPT_CALLER_PARK),
00540    AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
00541    AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
00542    AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
00543    AST_APP_OPTION_ARG('n', OPT_SCREEN_NOINTRO, OPT_ARG_SCREEN_NOINTRO),
00544    AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
00545    AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
00546    AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
00547    AST_APP_OPTION('p', OPT_SCREENING),
00548    AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
00549    AST_APP_OPTION('r', OPT_RINGBACK),
00550    AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
00551    AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
00552    AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
00553    AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB),
00554    AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
00555    AST_APP_OPTION('W', OPT_CALLER_MONITOR),
00556    AST_APP_OPTION('x', OPT_CALLEE_MIXMONITOR),
00557    AST_APP_OPTION('X', OPT_CALLER_MIXMONITOR),
00558 END_OPTIONS );
00559 
00560 #define CAN_EARLY_BRIDGE(flags,chan,peer) (!ast_test_flag64(flags, OPT_CALLEE_HANGUP | \
00561    OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \
00562    OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK |  \
00563    OPT_CALLER_PARK | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB) && \
00564    !chan->audiohooks && !peer->audiohooks)
00565 
00566 /*
00567  * The list of active channels
00568  */
00569 struct chanlist {
00570    struct chanlist *next;
00571    struct ast_channel *chan;
00572    uint64_t flags;
00573 };
00574 
00575 static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode);
00576 
00577 static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
00578 {
00579    /* Hang up a tree of stuff */
00580    struct chanlist *oo;
00581    while (outgoing) {
00582       /* Hangup any existing lines we have open */
00583       if (outgoing->chan && (outgoing->chan != exception)) {
00584          if (answered_elsewhere) {
00585             /* The flag is used for local channel inheritance and stuff */
00586             ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE);
00587             /* This is for the channel drivers */
00588             outgoing->chan->hangupcause = AST_CAUSE_ANSWERED_ELSEWHERE;
00589          }
00590          ast_hangup(outgoing->chan);
00591       }
00592       oo = outgoing;
00593       outgoing = outgoing->next;
00594       ast_free(oo);
00595    }
00596 }
00597 
00598 #define AST_MAX_WATCHERS 256
00599 
00600 /*
00601  * argument to handle_cause() and other functions.
00602  */
00603 struct cause_args {
00604    struct ast_channel *chan;
00605    int busy;
00606    int congestion;
00607    int nochan;
00608 };
00609 
00610 static void handle_cause(int cause, struct cause_args *num)
00611 {
00612    struct ast_cdr *cdr = num->chan->cdr;
00613 
00614    switch(cause) {
00615    case AST_CAUSE_BUSY:
00616       if (cdr)
00617          ast_cdr_busy(cdr);
00618       num->busy++;
00619       break;
00620 
00621    case AST_CAUSE_CONGESTION:
00622       if (cdr)
00623          ast_cdr_failed(cdr);
00624       num->congestion++;
00625       break;
00626 
00627    case AST_CAUSE_NO_ROUTE_DESTINATION:
00628    case AST_CAUSE_UNREGISTERED:
00629       if (cdr)
00630          ast_cdr_failed(cdr);
00631       num->nochan++;
00632       break;
00633 
00634    case AST_CAUSE_NO_ANSWER:
00635       if (cdr) {
00636          ast_cdr_noanswer(cdr);
00637       }
00638       break;
00639    case AST_CAUSE_NORMAL_CLEARING:
00640       break;
00641 
00642    default:
00643       num->nochan++;
00644       break;
00645    }
00646 }
00647 
00648 /* free the buffer if allocated, and set the pointer to the second arg */
00649 #define S_REPLACE(s, new_val)    \
00650    do {           \
00651       if (s)         \
00652          ast_free(s);   \
00653       s = (new_val);    \
00654    } while (0)
00655 
00656 static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri)
00657 {
00658    char rexten[2] = { exten, '\0' };
00659 
00660    if (context) {
00661       if (!ast_goto_if_exists(chan, context, rexten, pri))
00662          return 1;
00663    } else {
00664       if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
00665          return 1;
00666       else if (!ast_strlen_zero(chan->macrocontext)) {
00667          if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
00668             return 1;
00669       }
00670    }
00671    return 0;
00672 }
00673 
00674 
00675 static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
00676 {
00677    const char *context = S_OR(chan->macrocontext, chan->context);
00678    const char *exten = S_OR(chan->macroexten, chan->exten);
00679 
00680    return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
00681 }
00682 
00683 static void senddialevent(struct ast_channel *src, struct ast_channel *dst, const char *dialstring)
00684 {
00685    manager_event(EVENT_FLAG_CALL, "Dial",
00686       "SubEvent: Begin\r\n"
00687       "Channel: %s\r\n"
00688       "Destination: %s\r\n"
00689       "CallerIDNum: %s\r\n"
00690       "CallerIDName: %s\r\n"
00691       "UniqueID: %s\r\n"
00692       "DestUniqueID: %s\r\n"
00693       "Dialstring: %s\r\n",
00694       src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"),
00695       S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid,
00696       dst->uniqueid, dialstring ? dialstring : "");
00697 }
00698 
00699 static void senddialendevent(const struct ast_channel *src, const char *dialstatus)
00700 {
00701    manager_event(EVENT_FLAG_CALL, "Dial",
00702       "SubEvent: End\r\n"
00703       "Channel: %s\r\n"
00704       "UniqueID: %s\r\n"
00705       "DialStatus: %s\r\n",
00706       src->name, src->uniqueid, dialstatus);
00707 }
00708 
00709 /*!
00710  * helper function for wait_for_answer()
00711  *
00712  * XXX this code is highly suspicious, as it essentially overwrites
00713  * the outgoing channel without properly deleting it.
00714  */
00715 static void do_forward(struct chanlist *o,
00716    struct cause_args *num, struct ast_flags64 *peerflags, int single)
00717 {
00718    char tmpchan[256];
00719    struct ast_channel *original = o->chan;
00720    struct ast_channel *c = o->chan; /* the winner */
00721    struct ast_channel *in = num->chan; /* the input channel */
00722    char *stuff;
00723    char *tech;
00724    int cause;
00725 
00726    ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
00727    if ((stuff = strchr(tmpchan, '/'))) {
00728       *stuff++ = '\0';
00729       tech = tmpchan;
00730    } else {
00731       const char *forward_context;
00732       ast_channel_lock(c);
00733       forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
00734       if (ast_strlen_zero(forward_context)) {
00735          forward_context = NULL;
00736       }
00737       snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
00738       ast_channel_unlock(c);
00739       stuff = tmpchan;
00740       tech = "Local";
00741    }
00742    /* Before processing channel, go ahead and check for forwarding */
00743    ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
00744    /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
00745    if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
00746       ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
00747       c = o->chan = NULL;
00748       cause = AST_CAUSE_BUSY;
00749    } else {
00750       /* Setup parameters */
00751       c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
00752       if (c) {
00753          if (single)
00754             ast_channel_make_compatible(o->chan, in);
00755          ast_channel_inherit_variables(in, o->chan);
00756          ast_channel_datastore_inherit(in, o->chan);
00757       } else
00758          ast_log(LOG_NOTICE,
00759             "Forwarding failed to create channel to dial '%s/%s' (cause = %d)\n",
00760             tech, stuff, cause);
00761    }
00762    if (!c) {
00763       ast_clear_flag64(o, DIAL_STILLGOING);
00764       handle_cause(cause, num);
00765       ast_hangup(original);
00766    } else {
00767       char *new_cid_num, *new_cid_name;
00768       struct ast_channel *src;
00769 
00770       if (CAN_EARLY_BRIDGE(peerflags, c, in)) {
00771          ast_rtp_make_compatible(c, in, single);
00772       }
00773       if (ast_test_flag64(o, OPT_FORCECLID)) {
00774          new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
00775          new_cid_name = NULL; /* XXX no name ? */
00776          src = c; /* XXX possible bug in previous code, which used 'winner' ? it may have changed */
00777       } else {
00778          new_cid_num = ast_strdup(in->cid.cid_num);
00779          new_cid_name = ast_strdup(in->cid.cid_name);
00780          src = in;
00781       }
00782       ast_string_field_set(c, accountcode, src->accountcode);
00783       c->cdrflags = src->cdrflags;
00784       S_REPLACE(c->cid.cid_num, new_cid_num);
00785       S_REPLACE(c->cid.cid_name, new_cid_name);
00786 
00787       if (in->cid.cid_ani) { /* XXX or maybe unconditional ? */
00788          S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
00789       }
00790       S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
00791       if (ast_call(c, stuff, 0)) {
00792          ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
00793             tech, stuff);
00794          ast_clear_flag64(o, DIAL_STILLGOING);
00795          ast_hangup(original);
00796          ast_hangup(c);
00797          c = o->chan = NULL;
00798          num->nochan++;
00799       } else {
00800          senddialevent(in, c, stuff);
00801          /* After calling, set callerid to extension */
00802          if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
00803             char cidname[AST_MAX_EXTENSION] = "";
00804             ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
00805          }
00806          /* Hangup the original channel now, in case we needed it */
00807          ast_hangup(original);
00808       }
00809       if (single) {
00810          ast_indicate(in, -1);
00811       }
00812    }
00813 }
00814 
00815 /* argument used for some functions. */
00816 struct privacy_args {
00817    int sentringing;
00818    int privdb_val;
00819    char privcid[256];
00820    char privintro[1024];
00821    char status[256];
00822 };
00823 
00824 static struct ast_channel *wait_for_answer(struct ast_channel *in,
00825    struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,
00826    struct privacy_args *pa,
00827    const struct cause_args *num_in, int *result)
00828 {
00829    struct cause_args num = *num_in;
00830    int prestart = num.busy + num.congestion + num.nochan;
00831    int orig = *to;
00832    struct ast_channel *peer = NULL;
00833    /* single is set if only one destination is enabled */
00834    int single = outgoing && !outgoing->next && !ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
00835 #ifdef HAVE_EPOLL
00836    struct chanlist *epollo;
00837 #endif
00838    struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
00839    if (single) {
00840       /* Turn off hold music, etc */
00841       ast_deactivate_generator(in);
00842       /* If we are calling a single channel, make them compatible for in-band tone purpose */
00843       if (ast_channel_make_compatible(outgoing->chan, in) < 0) {
00844          /* If these channels can not be made compatible, 
00845           * there is no point in continuing.  The bridge
00846           * will just fail if it gets that far.
00847           */
00848          *to = -1;
00849          strcpy(pa->status, "CONGESTION");
00850          ast_cdr_failed(in->cdr);
00851          return NULL;
00852       }
00853    }
00854 
00855 #ifdef HAVE_EPOLL
00856    for (epollo = outgoing; epollo; epollo = epollo->next)
00857       ast_poll_channel_add(in, epollo->chan);
00858 #endif
00859 
00860    while (*to && !peer) {
00861       struct chanlist *o;
00862       int pos = 0; /* how many channels do we handle */
00863       int numlines = prestart;
00864       struct ast_channel *winner;
00865       struct ast_channel *watchers[AST_MAX_WATCHERS];
00866 
00867       watchers[pos++] = in;
00868       for (o = outgoing; o; o = o->next) {
00869          /* Keep track of important channels */
00870          if (ast_test_flag64(o, DIAL_STILLGOING) && o->chan)
00871             watchers[pos++] = o->chan;
00872          numlines++;
00873       }
00874       if (pos == 1) { /* only the input channel is available */
00875          if (numlines == (num.busy + num.congestion + num.nochan)) {
00876             ast_verb(2, "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
00877             if (num.busy)
00878                strcpy(pa->status, "BUSY");
00879             else if (num.congestion)
00880                strcpy(pa->status, "CONGESTION");
00881             else if (num.nochan)
00882                strcpy(pa->status, "CHANUNAVAIL");
00883          } else {
00884             ast_verb(3, "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
00885          }
00886          *to = 0;
00887          return NULL;
00888       }
00889       winner = ast_waitfor_n(watchers, pos, to);
00890       for (o = outgoing; o; o = o->next) {
00891          struct ast_frame *f;
00892          struct ast_channel *c = o->chan;
00893 
00894          if (c == NULL)
00895             continue;
00896          if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
00897             if (!peer) {
00898                ast_verb(3, "%s answered %s\n", c->name, in->name);
00899                peer = c;
00900                ast_copy_flags64(peerflags, o,
00901                   OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
00902                   OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
00903                   OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
00904                   OPT_CALLEE_PARK | OPT_CALLER_PARK |
00905                   OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
00906                   DIAL_NOFORWARDHTML);
00907                ast_string_field_set(c, dialcontext, "");
00908                ast_copy_string(c->exten, "", sizeof(c->exten));
00909             }
00910             continue;
00911          }
00912          if (c != winner)
00913             continue;
00914          /* here, o->chan == c == winner */
00915          if (!ast_strlen_zero(c->call_forward)) {
00916             do_forward(o, &num, peerflags, single);
00917             continue;
00918          }
00919          f = ast_read(winner);
00920          if (!f) {
00921             in->hangupcause = c->hangupcause;
00922 #ifdef HAVE_EPOLL
00923             ast_poll_channel_del(in, c);
00924 #endif
00925             ast_hangup(c);
00926             c = o->chan = NULL;
00927             ast_clear_flag64(o, DIAL_STILLGOING);
00928             handle_cause(in->hangupcause, &num);
00929             continue;
00930          }
00931          if (f->frametype == AST_FRAME_CONTROL) {
00932             switch(f->subclass) {
00933             case AST_CONTROL_ANSWER:
00934                /* This is our guy if someone answered. */
00935                if (!peer) {
00936                   ast_verb(3, "%s answered %s\n", c->name, in->name);
00937                   peer = c;
00938                   if (peer->cdr) {
00939                      peer->cdr->answer = ast_tvnow();
00940                      peer->cdr->disposition = AST_CDR_ANSWERED;
00941                   }
00942                   ast_copy_flags64(peerflags, o,
00943                      OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
00944                      OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
00945                      OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
00946                      OPT_CALLEE_PARK | OPT_CALLER_PARK |
00947                      OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
00948                      DIAL_NOFORWARDHTML);
00949                   ast_string_field_set(c, dialcontext, "");
00950                   ast_copy_string(c->exten, "", sizeof(c->exten));
00951                   if (CAN_EARLY_BRIDGE(peerflags, in, peer))
00952                      /* Setup early bridge if appropriate */
00953                      ast_channel_early_bridge(in, peer);
00954                }
00955                /* If call has been answered, then the eventual hangup is likely to be normal hangup */
00956                in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
00957                c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
00958                break;
00959             case AST_CONTROL_BUSY:
00960                ast_verb(3, "%s is busy\n", c->name);
00961                in->hangupcause = c->hangupcause;
00962                ast_hangup(c);
00963                c = o->chan = NULL;
00964                ast_clear_flag64(o, DIAL_STILLGOING);
00965                handle_cause(AST_CAUSE_BUSY, &num);
00966                break;
00967             case AST_CONTROL_CONGESTION:
00968                ast_verb(3, "%s is circuit-busy\n", c->name);
00969                in->hangupcause = c->hangupcause;
00970                ast_hangup(c);
00971                c = o->chan = NULL;
00972                ast_clear_flag64(o, DIAL_STILLGOING);
00973                handle_cause(AST_CAUSE_CONGESTION, &num);
00974                break;
00975             case AST_CONTROL_RINGING:
00976                ast_verb(3, "%s is ringing\n", c->name);
00977                /* Setup early media if appropriate */
00978                if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
00979                   ast_channel_early_bridge(in, c);
00980                if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK)) {
00981                   ast_indicate(in, AST_CONTROL_RINGING);
00982                   pa->sentringing++;
00983                }
00984                break;
00985             case AST_CONTROL_PROGRESS:
00986                ast_verb(3, "%s is making progress passing it to %s\n", c->name, in->name);
00987                /* Setup early media if appropriate */
00988                if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
00989                   ast_channel_early_bridge(in, c);
00990                if (!ast_test_flag64(outgoing, OPT_RINGBACK))
00991                   if (single || (!single && !pa->sentringing)) {
00992                      ast_indicate(in, AST_CONTROL_PROGRESS);
00993                   }
00994                break;
00995             case AST_CONTROL_VIDUPDATE:
00996                ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name);
00997                ast_indicate(in, AST_CONTROL_VIDUPDATE);
00998                break;
00999             case AST_CONTROL_SRCUPDATE:
01000                ast_verb(3, "%s requested a source update, passing it to %s\n", c->name, in->name);
01001                ast_indicate(in, AST_CONTROL_SRCUPDATE);
01002                break;
01003             case AST_CONTROL_PROCEEDING:
01004                ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
01005                if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
01006                   ast_channel_early_bridge(in, c);
01007                if (!ast_test_flag64(outgoing, OPT_RINGBACK))
01008                   ast_indicate(in, AST_CONTROL_PROCEEDING);
01009                break;
01010             case AST_CONTROL_HOLD:
01011                ast_verb(3, "Call on %s placed on hold\n", c->name);
01012                ast_indicate(in, AST_CONTROL_HOLD);
01013                break;
01014             case AST_CONTROL_UNHOLD:
01015                ast_verb(3, "Call on %s left from hold\n", c->name);
01016                ast_indicate(in, AST_CONTROL_UNHOLD);
01017                break;
01018             case AST_CONTROL_OFFHOOK:
01019             case AST_CONTROL_FLASH:
01020                /* Ignore going off hook and flash */
01021                break;
01022             case -1:
01023                if (!ast_test_flag64(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
01024                   ast_verb(3, "%s stopped sounds\n", c->name);
01025                   ast_indicate(in, -1);
01026                   pa->sentringing = 0;
01027                }
01028                break;
01029             default:
01030                ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
01031             }
01032          } else if (single) {
01033             switch (f->frametype) {
01034                case AST_FRAME_VOICE:
01035                case AST_FRAME_IMAGE:
01036                case AST_FRAME_TEXT:
01037                   if (ast_write(in, f)) {
01038                      ast_log(LOG_WARNING, "Unable to write frame\n");
01039                   }
01040                   break;
01041                case AST_FRAME_HTML:
01042                   if (!ast_test_flag64(outgoing, DIAL_NOFORWARDHTML) && ast_channel_sendhtml(in, f->subclass, f->data.ptr, f->datalen) == -1) {
01043                      ast_log(LOG_WARNING, "Unable to send URL\n");
01044                   }
01045                   break;
01046                default:
01047                   break;
01048             }
01049          }
01050          ast_frfree(f);
01051       } /* end for */
01052       if (winner == in) {
01053          struct ast_frame *f = ast_read(in);
01054 #if 0
01055          if (f && (f->frametype != AST_FRAME_VOICE))
01056             printf("Frame type: %d, %d\n", f->frametype, f->subclass);
01057          else if (!f || (f->frametype != AST_FRAME_VOICE))
01058             printf("Hangup received on %s\n", in->name);
01059 #endif
01060          if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
01061             /* Got hung up */
01062             *to = -1;
01063             strcpy(pa->status, "CANCEL");
01064             ast_cdr_noanswer(in->cdr);
01065             if (f) {
01066                if (f->data.uint32) {
01067                   in->hangupcause = f->data.uint32;
01068                }
01069                ast_frfree(f);
01070             }
01071             return NULL;
01072          }
01073 
01074          /* now f is guaranteed non-NULL */
01075          if (f->frametype == AST_FRAME_DTMF) {
01076             if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) {
01077                const char *context;
01078                ast_channel_lock(in);
01079                context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
01080                if (onedigit_goto(in, context, (char) f->subclass, 1)) {
01081                   ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
01082                   *to = 0;
01083                   ast_cdr_noanswer(in->cdr);
01084                   *result = f->subclass;
01085                   strcpy(pa->status, "CANCEL");
01086                   ast_frfree(f);
01087                   ast_channel_unlock(in);
01088                   return NULL;
01089                }
01090                ast_channel_unlock(in);
01091             }
01092 
01093             if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&
01094                detect_disconnect(in, f->subclass, featurecode)) {
01095                ast_verb(3, "User requested call disconnect.\n");
01096                *to = 0;
01097                strcpy(pa->status, "CANCEL");
01098                ast_cdr_noanswer(in->cdr);
01099                ast_frfree(f);
01100                return NULL;
01101             }
01102          }
01103 
01104          /* Forward HTML stuff */
01105          if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag64(outgoing, DIAL_NOFORWARDHTML))
01106             if (ast_channel_sendhtml(outgoing->chan, f->subclass, f->data.ptr, f->datalen) == -1)
01107                ast_log(LOG_WARNING, "Unable to send URL\n");
01108 
01109          if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END)))  {
01110             if (ast_write(outgoing->chan, f))
01111                ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
01112          }
01113          if (single && (f->frametype == AST_FRAME_CONTROL) &&
01114             ((f->subclass == AST_CONTROL_HOLD) ||
01115             (f->subclass == AST_CONTROL_UNHOLD) ||
01116             (f->subclass == AST_CONTROL_VIDUPDATE) ||
01117              (f->subclass == AST_CONTROL_SRCUPDATE))) {
01118             ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
01119             ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
01120          }
01121          ast_frfree(f);
01122       }
01123       if (!*to)
01124          ast_verb(3, "Nobody picked up in %d ms\n", orig);
01125       if (!*to || ast_check_hangup(in))
01126          ast_cdr_noanswer(in->cdr);
01127    }
01128 
01129 #ifdef HAVE_EPOLL
01130    for (epollo = outgoing; epollo; epollo = epollo->next) {
01131       if (epollo->chan)
01132          ast_poll_channel_del(in, epollo->chan);
01133    }
01134 #endif
01135 
01136    return peer;
01137 }
01138 
01139 static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode)
01140 {
01141    struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */
01142    struct ast_call_feature feature = { 0, };
01143    int res;
01144 
01145    ast_str_append(&featurecode, 1, "%c", code);
01146 
01147    res = ast_feature_detect(chan, &features, ast_str_buffer(featurecode), &feature);
01148 
01149    if (res != AST_FEATURE_RETURN_STOREDIGITS) {
01150       ast_str_reset(featurecode);
01151    }
01152    if (feature.feature_mask & AST_FEATURE_DISCONNECT) {
01153       return 1;
01154    }
01155 
01156    return 0;
01157 }
01158 
01159 static void replace_macro_delimiter(char *s)
01160 {
01161    for (; *s; s++)
01162       if (*s == '^')
01163          *s = ',';
01164 }
01165 
01166 /* returns true if there is a valid privacy reply */
01167 static int valid_priv_reply(struct ast_flags64 *opts, int res)
01168 {
01169    if (res < '1')
01170       return 0;
01171    if (ast_test_flag64(opts, OPT_PRIVACY) && res <= '5')
01172       return 1;
01173    if (ast_test_flag64(opts, OPT_SCREENING) && res <= '4')
01174       return 1;
01175    return 0;
01176 }
01177 
01178 static int do_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
01179    char *parse, struct timeval *calldurationlimit)
01180 {
01181    char *stringp = ast_strdupa(parse);
01182    char *limit_str, *warning_str, *warnfreq_str;
01183    const char *var;
01184    int play_to_caller = 0, play_to_callee = 0;
01185    int delta;
01186 
01187    limit_str = strsep(&stringp, ":");
01188    warning_str = strsep(&stringp, ":");
01189    warnfreq_str = strsep(&stringp, ":");
01190 
01191    config->timelimit = atol(limit_str);
01192    if (warning_str)
01193       config->play_warning = atol(warning_str);
01194    if (warnfreq_str)
01195       config->warning_freq = atol(warnfreq_str);
01196 
01197    if (!config->timelimit) {
01198       ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
01199       config->timelimit = config->play_warning = config->warning_freq = 0;
01200       config->warning_sound = NULL;
01201       return -1; /* error */
01202    } else if ( (delta = config->play_warning - config->timelimit) > 0) {
01203       int w = config->warning_freq;
01204 
01205       /* If the first warning is requested _after_ the entire call would end,
01206          and no warning frequency is requested, then turn off the warning. If
01207          a warning frequency is requested, reduce the 'first warning' time by
01208          that frequency until it falls within the call's total time limit.
01209          Graphically:
01210               timelim->|    delta        |<-playwarning
01211          0__________________|_________________|
01212                 | w  |    |    |    |
01213 
01214          so the number of intervals to cut is 1+(delta-1)/w
01215       */
01216 
01217       if (w == 0) {
01218          config->play_warning = 0;
01219       } else {
01220          config->play_warning -= w * ( 1 + (delta-1)/w );
01221          if (config->play_warning < 1)
01222             config->play_warning = config->warning_freq = 0;
01223       }
01224    }
01225    
01226    ast_channel_lock(chan);
01227 
01228    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
01229 
01230    play_to_caller = var ? ast_true(var) : 1;
01231 
01232    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
01233    play_to_callee = var ? ast_true(var) : 0;
01234 
01235    if (!play_to_caller && !play_to_callee)
01236       play_to_caller = 1;
01237 
01238    var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
01239    config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
01240 
01241    /* The code looking at config wants a NULL, not just "", to decide
01242     * that the message should not be played, so we replace "" with NULL.
01243     * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
01244     * not found.
01245     */
01246 
01247    var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
01248    config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
01249 
01250    var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
01251    config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
01252 
01253    ast_channel_unlock(chan);
01254 
01255    /* undo effect of S(x) in case they are both used */
01256    calldurationlimit->tv_sec = 0;
01257    calldurationlimit->tv_usec = 0;
01258 
01259    /* more efficient to do it like S(x) does since no advanced opts */
01260    if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
01261       calldurationlimit->tv_sec = config->timelimit / 1000;
01262       calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
01263       ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
01264          calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
01265       config->timelimit = play_to_caller = play_to_callee =
01266       config->play_warning = config->warning_freq = 0;
01267    } else {
01268       ast_verb(3, "Limit Data for this call:\n");
01269       ast_verb(4, "timelimit      = %ld\n", config->timelimit);
01270       ast_verb(4, "play_warning   = %ld\n", config->play_warning);
01271       ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
01272       ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
01273       ast_verb(4, "warning_freq   = %ld\n", config->warning_freq);
01274       ast_verb(4, "start_sound    = %s\n", S_OR(config->start_sound, ""));
01275       ast_verb(4, "warning_sound  = %s\n", config->warning_sound);
01276       ast_verb(4, "end_sound      = %s\n", S_OR(config->end_sound, ""));
01277    }
01278    if (play_to_caller)
01279       ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
01280    if (play_to_callee)
01281       ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
01282    return 0;
01283 }
01284 
01285 static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
01286    struct ast_flags64 *opts, char **opt_args, struct privacy_args *pa)
01287 {
01288 
01289    int res2;
01290    int loopcount = 0;
01291 
01292    /* Get the user's intro, store it in priv-callerintros/$CID,
01293       unless it is already there-- this should be done before the
01294       call is actually dialed  */
01295 
01296    /* all ring indications and moh for the caller has been halted as soon as the
01297       target extension was picked up. We are going to have to kill some
01298       time and make the caller believe the peer hasn't picked up yet */
01299 
01300    if (ast_test_flag64(opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01301       char *original_moh = ast_strdupa(chan->musicclass);
01302       ast_indicate(chan, -1);
01303       ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01304       ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01305       ast_string_field_set(chan, musicclass, original_moh);
01306    } else if (ast_test_flag64(opts, OPT_RINGBACK)) {
01307       ast_indicate(chan, AST_CONTROL_RINGING);
01308       pa->sentringing++;
01309    }
01310 
01311    /* Start autoservice on the other chan ?? */
01312    res2 = ast_autoservice_start(chan);
01313    /* Now Stream the File */
01314    for (loopcount = 0; loopcount < 3; loopcount++) {
01315       if (res2 && loopcount == 0) /* error in ast_autoservice_start() */
01316          break;
01317       if (!res2) /* on timeout, play the message again */
01318          res2 = ast_play_and_wait(peer, "priv-callpending");
01319       if (!valid_priv_reply(opts, res2))
01320          res2 = 0;
01321       /* priv-callpending script:
01322          "I have a caller waiting, who introduces themselves as:"
01323       */
01324       if (!res2)
01325          res2 = ast_play_and_wait(peer, pa->privintro);
01326       if (!valid_priv_reply(opts, res2))
01327          res2 = 0;
01328       /* now get input from the called party, as to their choice */
01329       if (!res2) {
01330          /* XXX can we have both, or they are mutually exclusive ? */
01331          if (ast_test_flag64(opts, OPT_PRIVACY))
01332             res2 = ast_play_and_wait(peer, "priv-callee-options");
01333          if (ast_test_flag64(opts, OPT_SCREENING))
01334             res2 = ast_play_and_wait(peer, "screen-callee-options");
01335       }
01336       /*! \page DialPrivacy Dial Privacy scripts
01337       \par priv-callee-options script:
01338          "Dial 1 if you wish this caller to reach you directly in the future,
01339             and immediately connect to their incoming call
01340           Dial 2 if you wish to send this caller to voicemail now and
01341             forevermore.
01342           Dial 3 to send this caller to the torture menus, now and forevermore.
01343           Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
01344           Dial 5 to allow this caller to come straight thru to you in the future,
01345             but right now, just this once, send them to voicemail."
01346       \par screen-callee-options script:
01347          "Dial 1 if you wish to immediately connect to the incoming call
01348           Dial 2 if you wish to send this caller to voicemail.
01349           Dial 3 to send this caller to the torture menus.
01350           Dial 4 to send this caller to a simple "go away" menu.
01351       */
01352       if (valid_priv_reply(opts, res2))
01353          break;
01354       /* invalid option */
01355       res2 = ast_play_and_wait(peer, "vm-sorry");
01356    }
01357 
01358    if (ast_test_flag64(opts, OPT_MUSICBACK)) {
01359       ast_moh_stop(chan);
01360    } else if (ast_test_flag64(opts, OPT_RINGBACK)) {
01361       ast_indicate(chan, -1);
01362       pa->sentringing = 0;
01363    }
01364    ast_autoservice_stop(chan);
01365    if (ast_test_flag64(opts, OPT_PRIVACY) && (res2 >= '1' && res2 <= '5')) {
01366       /* map keypresses to various things, the index is res2 - '1' */
01367       static const char *_val[] = { "ALLOW", "DENY", "TORTURE", "KILL", "ALLOW" };
01368       static const int _flag[] = { AST_PRIVACY_ALLOW, AST_PRIVACY_DENY, AST_PRIVACY_TORTURE, AST_PRIVACY_KILL, AST_PRIVACY_ALLOW};
01369       int i = res2 - '1';
01370       ast_verb(3, "--Set privacy database entry %s/%s to %s\n",
01371          opt_args[OPT_ARG_PRIVACY], pa->privcid, _val[i]);
01372       ast_privacy_set(opt_args[OPT_ARG_PRIVACY], pa->privcid, _flag[i]);
01373    }
01374    switch (res2) {
01375    case '1':
01376       break;
01377    case '2':
01378       ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
01379       break;
01380    case '3':
01381       ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
01382       break;
01383    case '4':
01384       ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
01385       break;
01386    case '5':
01387       /* XXX should we set status to DENY ? */
01388       if (ast_test_flag64(opts, OPT_PRIVACY))
01389          break;
01390       /* if not privacy, then 5 is the same as "default" case */
01391    default: /* bad input or -1 if failure to start autoservice */
01392       /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do?  */
01393       /* well, there seems basically two choices. Just patch the caller thru immediately,
01394            or,... put 'em thru to voicemail. */
01395       /* since the callee may have hung up, let's do the voicemail thing, no database decision */
01396       ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
01397       /* XXX should we set status to DENY ? */
01398       /* XXX what about the privacy flags ? */
01399       break;
01400    }
01401 
01402    if (res2 == '1') { /* the only case where we actually connect */
01403       /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll
01404          just clog things up, and it's not useful information, not being tied to a CID */
01405       if (strncmp(pa->privcid, "NOCALLERID", 10) == 0 || ast_test_flag64(opts, OPT_SCREEN_NOINTRO)) {
01406          ast_filedelete(pa->privintro, NULL);
01407          if (ast_fileexists(pa->privintro, NULL, NULL) > 0)
01408             ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
01409          else
01410             ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
01411       }
01412       return 0; /* the good exit path */
01413    } else {
01414       ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
01415       return -1;
01416    }
01417 }
01418 
01419 /*! \brief returns 1 if successful, 0 or <0 if the caller should 'goto out' */
01420 static int setup_privacy_args(struct privacy_args *pa,
01421    struct ast_flags64 *opts, char *opt_args[], struct ast_channel *chan)
01422 {
01423    char callerid[60];
01424    int res;
01425    char *l;
01426    int silencethreshold;
01427 
01428    if (!ast_strlen_zero(chan->cid.cid_num)) {
01429       l = ast_strdupa(chan->cid.cid_num);
01430       ast_shrink_phone_number(l);
01431       if (ast_test_flag64(opts, OPT_PRIVACY) ) {
01432          ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l);
01433          pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
01434       } else {
01435          ast_verb(3, "Privacy Screening, clid is '%s'\n", l);
01436          pa->privdb_val = AST_PRIVACY_UNKNOWN;
01437       }
01438    } else {
01439       char *tnam, *tn2;
01440 
01441       tnam = ast_strdupa(chan->name);
01442       /* clean the channel name so slashes don't try to end up in disk file name */
01443       for (tn2 = tnam; *tn2; tn2++) {
01444          if (*tn2 == '/')  /* any other chars to be afraid of? */
01445             *tn2 = '=';
01446       }
01447       ast_verb(3, "Privacy-- callerid is empty\n");
01448 
01449       snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
01450       l = callerid;
01451       pa->privdb_val = AST_PRIVACY_UNKNOWN;
01452    }
01453 
01454    ast_copy_string(pa->privcid, l, sizeof(pa->privcid));
01455 
01456    if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCLID)) {
01457       /* if callerid is set and OPT_SCREEN_NOCLID is set also */
01458       ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid);
01459       pa->privdb_val = AST_PRIVACY_ALLOW;
01460    } else if (ast_test_flag64(opts, OPT_SCREEN_NOCLID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
01461       ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val);
01462    }
01463    
01464    if (pa->privdb_val == AST_PRIVACY_DENY) {
01465       ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
01466       ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
01467       return 0;
01468    } else if (pa->privdb_val == AST_PRIVACY_KILL) {
01469       ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
01470       return 0; /* Is this right? */
01471    } else if (pa->privdb_val == AST_PRIVACY_TORTURE) {
01472       ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
01473       return 0; /* is this right??? */
01474    } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN) {
01475       /* Get the user's intro, store it in priv-callerintros/$CID,
01476          unless it is already there-- this should be done before the
01477          call is actually dialed  */
01478 
01479       /* make sure the priv-callerintros dir actually exists */
01480       snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
01481       if ((res = ast_mkdir(pa->privintro, 0755))) {
01482          ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res));
01483          return -1;
01484       }
01485 
01486       snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid);
01487       if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) {
01488          /* the DELUX version of this code would allow this caller the
01489             option to hear and retape their previously recorded intro.
01490          */
01491       } else {
01492          int duration; /* for feedback from play_and_wait */
01493          /* the file doesn't exist yet. Let the caller submit his
01494             vocal intro for posterity */
01495          /* priv-recordintro script:
01496 
01497             "At the tone, please say your name:"
01498 
01499          */
01500          silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
01501          ast_answer(chan);
01502          res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "sln", &duration, silencethreshold, 2000, 0);  /* NOTE: I've reduced the total time to 4 sec */
01503                            /* don't think we'll need a lock removed, we took care of
01504                               conflicts by naming the pa.privintro file */
01505          if (res == -1) {
01506             /* Delete the file regardless since they hung up during recording */
01507             ast_filedelete(pa->privintro, NULL);
01508             if (ast_fileexists(pa->privintro, NULL, NULL) > 0)
01509                ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
01510             else
01511                ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
01512             return -1;
01513          }
01514          if (!ast_streamfile(chan, "vm-dialout", chan->language) )
01515             ast_waitstream(chan, "");
01516       }
01517    }
01518    return 1; /* success */
01519 }
01520 
01521 static void end_bridge_callback(void *data)
01522 {
01523    char buf[80];
01524    time_t end;
01525    struct ast_channel *chan = data;
01526 
01527    if (!chan->cdr) {
01528       return;
01529    }
01530 
01531    time(&end);
01532 
01533    ast_channel_lock(chan);
01534    if (chan->cdr->answer.tv_sec) {
01535       snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->answer.tv_sec);
01536       pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf);
01537    }
01538 
01539    if (chan->cdr->start.tv_sec) {
01540       snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->start.tv_sec);
01541       pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf);
01542    }
01543    ast_channel_unlock(chan);
01544 }
01545 
01546 static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) {
01547    bconfig->end_bridge_callback_data = originator;
01548 }
01549 
01550 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags64 *peerflags, int *continue_exec)
01551 {
01552    int res = -1; /* default: error */
01553    char *rest, *cur; /* scan the list of destinations */
01554    struct chanlist *outgoing = NULL; /* list of destinations */
01555    struct ast_channel *peer;
01556    int to; /* timeout */
01557    struct cause_args num = { chan, 0, 0, 0 };
01558    int cause;
01559    char numsubst[256];
01560    char cidname[AST_MAX_EXTENSION] = "";
01561 
01562    struct ast_bridge_config config = { { 0, } };
01563    struct timeval calldurationlimit = { 0, };
01564    char *dtmfcalled = NULL, *dtmfcalling = NULL;
01565    struct privacy_args pa = {
01566       .sentringing = 0,
01567       .privdb_val = 0,
01568       .status = "INVALIDARGS",
01569    };
01570    int sentringing = 0, moh = 0;
01571    const char *outbound_group = NULL;
01572    int result = 0;
01573    char *parse;
01574    int opermode = 0;
01575    int delprivintro = 0;
01576    AST_DECLARE_APP_ARGS(args,
01577       AST_APP_ARG(peers);
01578       AST_APP_ARG(timeout);
01579       AST_APP_ARG(options);
01580       AST_APP_ARG(url);
01581    );
01582    struct ast_flags64 opts = { 0, };
01583    char *opt_args[OPT_ARG_ARRAY_SIZE];
01584    struct ast_datastore *datastore = NULL;
01585    int fulldial = 0, num_dialed = 0;
01586 
01587    /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */
01588    pbx_builtin_setvar_helper(chan, "DIALSTATUS", "");
01589    pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", "");
01590    pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", "");
01591    pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", "");
01592    pbx_builtin_setvar_helper(chan, "DIALEDTIME", "");
01593 
01594    if (ast_strlen_zero(data)) {
01595       ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
01596       pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01597       return -1;
01598    }
01599 
01600    parse = ast_strdupa(data);
01601 
01602    AST_STANDARD_APP_ARGS(args, parse);
01603 
01604    if (!ast_strlen_zero(args.options) &&
01605       ast_app_parse_options64(dial_exec_options, &opts, opt_args, args.options)) {
01606       pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01607       goto done;
01608    }
01609 
01610    if (ast_strlen_zero(args.peers)) {
01611       ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
01612       pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01613       goto done;
01614    }
01615 
01616 
01617    if (ast_test_flag64(&opts, OPT_SCREEN_NOINTRO) && !ast_strlen_zero(opt_args[OPT_ARG_SCREEN_NOINTRO])) {
01618       delprivintro = atoi(opt_args[OPT_ARG_SCREEN_NOINTRO]);
01619 
01620       if (delprivintro < 0 || delprivintro > 1) {
01621          ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro);
01622          delprivintro = 0;
01623       }
01624    }
01625 
01626    if (ast_test_flag64(&opts, OPT_OPERMODE)) {
01627       opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
01628       ast_verb(3, "Setting operator services mode to %d.\n", opermode);
01629    }
01630    
01631    if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
01632       calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]);
01633       if (!calldurationlimit.tv_sec) {
01634          ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
01635          pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01636          goto done;
01637       }
01638       ast_verb(3, "Setting call duration limit to %.3lf seconds.\n", calldurationlimit.tv_sec + calldurationlimit.tv_usec / 1000000.0);
01639    }
01640 
01641    if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
01642       dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
01643       dtmfcalled = strsep(&dtmfcalling, ":");
01644    }
01645 
01646    if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
01647       if (do_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
01648          goto done;
01649    }
01650 
01651    if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr)
01652       ast_cdr_reset(chan->cdr, NULL);
01653    if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
01654       opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
01655 
01656    if (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) {
01657       res = setup_privacy_args(&pa, &opts, opt_args, chan);
01658       if (res <= 0)
01659          goto out;
01660       res = -1; /* reset default */
01661    }
01662 
01663    if (ast_test_flag64(&opts, OPT_DTMF_EXIT) || ast_test_flag64(&opts, OPT_CALLER_HANGUP)) {
01664       __ast_answer(chan, 0, 0);
01665    }
01666 
01667    if (continue_exec)
01668       *continue_exec = 0;
01669 
01670    /* If a channel group has been specified, get it for use when we create peer channels */
01671 
01672    ast_channel_lock(chan);
01673    if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
01674       outbound_group = ast_strdupa(outbound_group);   
01675       pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
01676    } else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) {
01677       outbound_group = ast_strdupa(outbound_group);
01678    }
01679    ast_channel_unlock(chan);  
01680    ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB);
01681 
01682    /* loop through the list of dial destinations */
01683    rest = args.peers;
01684    while ((cur = strsep(&rest, "&")) ) {
01685       struct chanlist *tmp;
01686       struct ast_channel *tc; /* channel for this destination */
01687       /* Get a technology/[device:]number pair */
01688       char *number = cur;
01689       char *interface = ast_strdupa(number);
01690       char *tech = strsep(&number, "/");
01691       /* find if we already dialed this interface */
01692       struct ast_dialed_interface *di;
01693       AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
01694       num_dialed++;
01695       if (ast_strlen_zero(number)) {
01696          ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
01697          goto out;
01698       }
01699       if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01700          goto out;
01701       if (opts.flags) {
01702          ast_copy_flags64(tmp, &opts,
01703             OPT_CANCEL_ELSEWHERE |
01704             OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
01705             OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
01706             OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
01707             OPT_CALLEE_PARK | OPT_CALLER_PARK |
01708             OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
01709             OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
01710          ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML);
01711       }
01712       ast_copy_string(numsubst, number, sizeof(numsubst));
01713       /* Request the peer */
01714 
01715       ast_channel_lock(chan);
01716       datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL);
01717       ast_channel_unlock(chan);
01718 
01719       if (datastore)
01720          dialed_interfaces = datastore->data;
01721       else {
01722          if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
01723             ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n");
01724             ast_free(tmp);
01725             goto out;
01726          }
01727 
01728          datastore->inheritance = DATASTORE_INHERIT_FOREVER;
01729 
01730          if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
01731             ast_datastore_free(datastore);
01732             ast_free(tmp);
01733             goto out;
01734          }
01735 
01736          datastore->data = dialed_interfaces;
01737          AST_LIST_HEAD_INIT(dialed_interfaces);
01738 
01739          ast_channel_lock(chan);
01740          ast_channel_datastore_add(chan, datastore);
01741          ast_channel_unlock(chan);
01742       }
01743 
01744       AST_LIST_LOCK(dialed_interfaces);
01745       AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
01746          if (!strcasecmp(di->interface, interface)) {
01747             ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n",
01748                di->interface);
01749             break;
01750          }
01751       }
01752       AST_LIST_UNLOCK(dialed_interfaces);
01753 
01754       if (di) {
01755          fulldial++;
01756          ast_free(tmp);
01757          continue;
01758       }
01759 
01760       /* It is always ok to dial a Local interface.  We only keep track of
01761        * which "real" interfaces have been dialed.  The Local channel will
01762        * inherit this list so that if it ends up dialing a real interface,
01763        * it won't call one that has already been called. */
01764       if (strcasecmp(tech, "Local")) {
01765          if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) {
01766             AST_LIST_UNLOCK(dialed_interfaces);
01767             ast_free(tmp);
01768             goto out;
01769          }
01770          strcpy(di->interface, interface);
01771 
01772          AST_LIST_LOCK(dialed_interfaces);
01773          AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
01774          AST_LIST_UNLOCK(dialed_interfaces);
01775       }
01776 
01777       tc = ast_request(tech, chan->nativeformats, numsubst, &cause);
01778       if (!tc) {
01779          /* If we can't, just go on to the next call */
01780          ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n",
01781             tech, cause, ast_cause2str(cause));
01782          handle_cause(cause, &num);
01783          if (!rest) /* we are on the last destination */
01784             chan->hangupcause = cause;
01785          ast_free(tmp);
01786          continue;
01787       }
01788       pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
01789 
01790       /* Setup outgoing SDP to match incoming one */
01791       if (CAN_EARLY_BRIDGE(peerflags, chan, tc)) {
01792          ast_rtp_make_compatible(tc, chan, !outgoing && !rest);
01793       }
01794       
01795       /* Inherit specially named variables from parent channel */
01796       ast_channel_inherit_variables(chan, tc);
01797       ast_channel_datastore_inherit(chan, tc);
01798 
01799       tc->appl = "AppDial";
01800       tc->data = "(Outgoing Line)";
01801       memset(&tc->whentohangup, 0, sizeof(tc->whentohangup));
01802 
01803       S_REPLACE(tc->cid.cid_num, ast_strdup(chan->cid.cid_num));
01804       S_REPLACE(tc->cid.cid_name, ast_strdup(chan->cid.cid_name));
01805       S_REPLACE(tc->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
01806       S_REPLACE(tc->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
01807       
01808       ast_string_field_set(tc, accountcode, chan->accountcode);
01809       tc->cdrflags = chan->cdrflags;
01810       if (ast_strlen_zero(tc->musicclass))
01811          ast_string_field_set(tc, musicclass, chan->musicclass);
01812       /* Pass callingpres, type of number, tns, ADSI CPE, transfer capability */
01813       tc->cid.cid_pres = chan->cid.cid_pres;
01814       tc->cid.cid_ton = chan->cid.cid_ton;
01815       tc->cid.cid_tns = chan->cid.cid_tns;
01816       tc->cid.cid_ani2 = chan->cid.cid_ani2;
01817       tc->adsicpe = chan->adsicpe;
01818       tc->transfercapability = chan->transfercapability;
01819 
01820       /* If we have an outbound group, set this peer channel to it */
01821       if (outbound_group)
01822          ast_app_group_set_channel(tc, outbound_group);
01823       /* If the calling channel has the ANSWERED_ELSEWHERE flag set, inherit it. This is to support local channels */
01824       if (ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE))
01825          ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE);
01826 
01827       /* Check if we're forced by configuration */
01828       if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE))
01829           ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE);
01830 
01831 
01832       /* Inherit context and extension */
01833       ast_string_field_set(tc, dialcontext, ast_strlen_zero(chan->macrocontext) ? chan->context : chan->macrocontext);
01834       if (!ast_strlen_zero(chan->macroexten))
01835          ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten));
01836       else
01837          ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten));
01838 
01839       res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */
01840 
01841       /* Save the info in cdr's that we called them */
01842       if (chan->cdr)
01843          ast_cdr_setdestchan(chan->cdr, tc->name);
01844 
01845       /* check the results of ast_call */
01846       if (res) {
01847          /* Again, keep going even if there's an error */
01848          ast_debug(1, "ast call on peer returned %d\n", res);
01849          ast_verb(3, "Couldn't call %s\n", numsubst);
01850          if (tc->hangupcause) {
01851             chan->hangupcause = tc->hangupcause;
01852          }
01853          ast_hangup(tc);
01854          tc = NULL;
01855          ast_free(tmp);
01856          continue;
01857       } else {
01858          senddialevent(chan, tc, numsubst);
01859          ast_verb(3, "Called %s\n", numsubst);
01860          if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID))
01861             ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
01862       }
01863       /* Put them in the list of outgoing thingies...  We're ready now.
01864          XXX If we're forcibly removed, these outgoing calls won't get
01865          hung up XXX */
01866       ast_set_flag64(tmp, DIAL_STILLGOING);
01867       tmp->chan = tc;
01868       tmp->next = outgoing;
01869       outgoing = tmp;
01870       /* If this line is up, don't try anybody else */
01871       if (outgoing->chan->_state == AST_STATE_UP)
01872          break;
01873    }
01874    
01875    if (ast_strlen_zero(args.timeout)) {
01876       to = -1;
01877    } else {
01878       to = atoi(args.timeout);
01879       if (to > 0)
01880          to *= 1000;
01881       else {
01882          ast_log(LOG_WARNING, "Invalid timeout specified: '%s'. Setting timeout to infinite\n", args.timeout);
01883          to = -1;
01884       }
01885    }
01886 
01887    if (!outgoing) {
01888       strcpy(pa.status, "CHANUNAVAIL");
01889       if (fulldial == num_dialed) {
01890          res = -1;
01891          goto out;
01892       }
01893    } else {
01894       /* Our status will at least be NOANSWER */
01895       strcpy(pa.status, "NOANSWER");
01896       if (ast_test_flag64(outgoing, OPT_MUSICBACK)) {
01897          moh = 1;
01898          if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01899             char *original_moh = ast_strdupa(chan->musicclass);
01900             ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01901             ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01902             ast_string_field_set(chan, musicclass, original_moh);
01903          } else {
01904             ast_moh_start(chan, NULL, NULL);
01905          }
01906          ast_indicate(chan, AST_CONTROL_PROGRESS);
01907       } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) {
01908          ast_indicate(chan, AST_CONTROL_RINGING);
01909          sentringing++;
01910       }
01911    }
01912 
01913    peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result);
01914 
01915    /* The ast_channel_datastore_remove() function could fail here if the
01916     * datastore was moved to another channel during a masquerade. If this is
01917     * the case, don't free the datastore here because later, when the channel
01918     * to which the datastore was moved hangs up, it will attempt to free this
01919     * datastore again, causing a crash
01920     */
01921    ast_channel_lock(chan);
01922    if (!ast_channel_datastore_remove(chan, datastore)) {
01923       ast_datastore_free(datastore);
01924    }
01925    ast_channel_unlock(chan);
01926    if (!peer) {
01927       if (result) {
01928          res = result;
01929       } else if (to) { /* Musta gotten hung up */
01930          res = -1;
01931       } else { /* Nobody answered, next please? */
01932          res = 0;
01933       }
01934 
01935       /* SIP, in particular, sends back this error code to indicate an
01936        * overlap dialled number needs more digits. */
01937       if (chan->hangupcause == AST_CAUSE_INVALID_NUMBER_FORMAT) {
01938          res = AST_PBX_INCOMPLETE;
01939       }
01940 
01941       /* almost done, although the 'else' block is 400 lines */
01942    } else {
01943       const char *number;
01944 
01945       strcpy(pa.status, "ANSWER");
01946       pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01947       /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
01948          we will always return with -1 so that it is hung up properly after the
01949          conversation.  */
01950       hanguptree(outgoing, peer, 1);
01951       outgoing = NULL;
01952       /* If appropriate, log that we have a destination channel */
01953       if (chan->cdr)
01954          ast_cdr_setdestchan(chan->cdr, peer->name);
01955       if (peer->name)
01956          pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
01957       
01958       ast_channel_lock(peer);
01959       number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER"); 
01960       if (!number)
01961          number = numsubst;
01962       pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
01963       ast_channel_unlock(peer);
01964 
01965       if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
01966          ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
01967          ast_channel_sendurl( peer, args.url );
01968       }
01969       if ( (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) {
01970          if (do_privacy(chan, peer, &opts, opt_args, &pa)) {
01971             res = 0;
01972             goto out;
01973          }
01974       }
01975       if (!ast_test_flag64(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
01976          res = 0;
01977       } else {
01978          int digit = 0;
01979          struct ast_channel *chans[2];
01980          struct ast_channel *active_chan;
01981 
01982          chans[0] = chan;
01983          chans[1] = peer;
01984 
01985          /* we need to stream the announcment while monitoring the caller for a hangup */
01986 
01987          /* stream the file */
01988          res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
01989          if (res) {
01990             res = 0;
01991             ast_log(LOG_ERROR, "error streaming file '%s' to callee\n", opt_args[OPT_ARG_ANNOUNCE]);
01992          }
01993 
01994          ast_set_flag(peer, AST_FLAG_END_DTMF_ONLY);
01995          while (peer->stream) {
01996             int ms;
01997 
01998             ms = ast_sched_wait(peer->sched);
01999 
02000             if (ms < 0 && !peer->timingfunc) {
02001                ast_stopstream(peer);
02002                break;
02003             }
02004             if (ms < 0)
02005                ms = 1000;
02006 
02007             active_chan = ast_waitfor_n(chans, 2, &ms);
02008             if (active_chan) {
02009                struct ast_frame *fr = ast_read(active_chan);
02010                if (!fr) {
02011                   ast_hangup(peer);
02012                   res = -1;
02013                   goto done;
02014                }
02015                switch(fr->frametype) {
02016                   case AST_FRAME_DTMF_END:
02017                      digit = fr->subclass;
02018                      if (active_chan == peer && strchr(AST_DIGIT_ANY, res)) {
02019                         ast_stopstream(peer);
02020                         res = ast_senddigit(chan, digit, 0);
02021                      }
02022                      break;
02023                   case AST_FRAME_CONTROL:
02024                      switch (fr->subclass) {
02025                         case AST_CONTROL_HANGUP:
02026                            ast_frfree(fr);
02027                            ast_hangup(peer);
02028                            res = -1;
02029                            goto done;
02030                         default:
02031                            break;
02032                      }
02033                      break;
02034                   default:
02035                      /* Ignore all others */
02036                      break;
02037                }
02038                ast_frfree(fr);
02039             }
02040             ast_sched_runq(peer->sched);
02041          }
02042          ast_clear_flag(peer, AST_FLAG_END_DTMF_ONLY);
02043       }
02044 
02045       if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
02046          /* chan and peer are going into the PBX, they both
02047           * should probably get CDR records. */
02048          ast_clear_flag(chan->cdr, AST_CDR_FLAG_DIALED);
02049          ast_clear_flag(peer->cdr, AST_CDR_FLAG_DIALED);
02050 
02051          replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
02052          ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
02053          /* peer goes to the same context and extension as chan, so just copy info from chan*/
02054          ast_copy_string(peer->context, chan->context, sizeof(peer->context));
02055          ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
02056          peer->priority = chan->priority + 2;
02057          ast_pbx_start(peer);
02058          hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0);
02059          if (continue_exec)
02060             *continue_exec = 1;
02061          res = 0;
02062          goto done;
02063       }
02064 
02065       if (ast_test_flag64(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
02066          struct ast_app *theapp;
02067          const char *macro_result;
02068 
02069          res = ast_autoservice_start(chan);
02070          if (res) {
02071             ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
02072             res = -1;
02073          }
02074 
02075          theapp = pbx_findapp("Macro");
02076 
02077          if (theapp && !res) { /* XXX why check res here ? */
02078             /* Set peer->exten and peer->context so that MACRO_EXTEN and MACRO_CONTEXT get set */
02079             ast_copy_string(peer->context, chan->context, sizeof(peer->context));
02080             ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
02081 
02082             replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
02083             res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
02084             ast_debug(1, "Macro exited with status %d\n", res);
02085             res = 0;
02086          } else {
02087             ast_log(LOG_ERROR, "Could not find application Macro\n");
02088             res = -1;
02089          }
02090 
02091          if (ast_autoservice_stop(chan) < 0) {
02092             res = -1;
02093          }
02094 
02095          ast_channel_lock(peer);
02096 
02097          if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
02098             char *macro_transfer_dest;
02099 
02100             if (!strcasecmp(macro_result, "BUSY")) {
02101                ast_copy_string(pa.status, macro_result, sizeof(pa.status));
02102                ast_set_flag64(peerflags, OPT_GO_ON);
02103                res = -1;
02104             } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
02105                ast_copy_string(pa.status, macro_result, sizeof(pa.status));
02106                ast_set_flag64(peerflags, OPT_GO_ON);
02107                res = -1;
02108             } else if (!strcasecmp(macro_result, "CONTINUE")) {
02109                /* hangup peer and keep chan alive assuming the macro has changed
02110                   the context / exten / priority or perhaps
02111                   the next priority in the current exten is desired.
02112                */
02113                ast_set_flag64(peerflags, OPT_GO_ON);
02114                res = -1;
02115             } else if (!strcasecmp(macro_result, "ABORT")) {
02116                /* Hangup both ends unless the caller has the g flag */
02117                res = -1;
02118             } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
02119                res = -1;
02120                /* perform a transfer to a new extension */
02121                if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
02122                   replace_macro_delimiter(macro_transfer_dest);
02123                   if (!ast_parseable_goto(chan, macro_transfer_dest))
02124                      ast_set_flag64(peerflags, OPT_GO_ON);
02125                }
02126             }
02127          }
02128 
02129          ast_channel_unlock(peer);
02130       }
02131 
02132       if (ast_test_flag64(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) {
02133          struct ast_app *theapp;
02134          const char *gosub_result;
02135          char *gosub_args, *gosub_argstart;
02136          int res9 = -1;
02137 
02138          res9 = ast_autoservice_start(chan);
02139          if (res9) {
02140             ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
02141             res9 = -1;
02142          }
02143 
02144          theapp = pbx_findapp("Gosub");
02145 
02146          if (theapp && !res9) {
02147             replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]);
02148 
02149             /* Set where we came from */
02150             ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context));
02151             ast_copy_string(peer->exten, "s", sizeof(peer->exten));
02152             peer->priority = 0;
02153 
02154             gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], ',');
02155             if (gosub_argstart) {
02156                *gosub_argstart = 0;
02157                if (asprintf(&gosub_args, "%s,s,1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], gosub_argstart + 1) < 0) {
02158                   ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
02159                   gosub_args = NULL;
02160                }
02161                *gosub_argstart = ',';
02162             } else {
02163                if (asprintf(&gosub_args, "%s,s,1", opt_args[OPT_ARG_CALLEE_GOSUB]) < 0) {
02164                   ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
02165                   gosub_args = NULL;
02166                }
02167             }
02168 
02169             if (gosub_args) {
02170                res9 = pbx_exec(peer, theapp, gosub_args);
02171                if (!res9) {
02172                   struct ast_pbx_args args;
02173                   /* A struct initializer fails to compile for this case ... */
02174                   memset(&args, 0, sizeof(args));
02175                   args.no_hangup_chan = 1;
02176                   ast_pbx_run_args(peer, &args);
02177                }
02178                ast_free(gosub_args);
02179                ast_debug(1, "Gosub exited with status %d\n", res9);
02180             } else {
02181                ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
02182             }
02183 
02184          } else if (!res9) {
02185             ast_log(LOG_ERROR, "Could not find application Gosub\n");
02186             res9 = -1;
02187          }
02188 
02189          if (ast_autoservice_stop(chan) < 0) {
02190             ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
02191             res9 = -1;
02192          }
02193          
02194          ast_channel_lock(peer);
02195 
02196          if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) {
02197             char *gosub_transfer_dest;
02198 
02199             if (!strcasecmp(gosub_result, "BUSY")) {
02200                ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
02201                ast_set_flag64(peerflags, OPT_GO_ON);
02202                res = -1;
02203             } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) {
02204                ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
02205                ast_set_flag64(peerflags, OPT_GO_ON);
02206                res = -1;
02207             } else if (!strcasecmp(gosub_result, "CONTINUE")) {
02208                /* hangup peer and keep chan alive assuming the macro has changed
02209                   the context / exten / priority or perhaps
02210                   the next priority in the current exten is desired.
02211                */
02212                ast_set_flag64(peerflags, OPT_GO_ON);
02213                res = -1;
02214             } else if (!strcasecmp(gosub_result, "ABORT")) {
02215                /* Hangup both ends unless the caller has the g flag */
02216                res = -1;
02217             } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) {
02218                res = -1;
02219                /* perform a transfer to a new extension */
02220                if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/
02221                   replace_macro_delimiter(gosub_transfer_dest);
02222                   if (!ast_parseable_goto(chan, gosub_transfer_dest))
02223                      ast_set_flag64(peerflags, OPT_GO_ON);
02224                }
02225             }
02226          }
02227 
02228          ast_channel_unlock(peer);  
02229       }
02230 
02231       if (!res) {
02232          if (!ast_tvzero(calldurationlimit)) {
02233             struct timeval whentohangup = calldurationlimit;
02234             peer->whentohangup = ast_tvadd(ast_tvnow(), whentohangup);
02235          }
02236          if (!ast_strlen_zero(dtmfcalled)) {
02237             ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled);
02238             res = ast_dtmf_stream(peer, chan, dtmfcalled, 250, 0);
02239          }
02240          if (!ast_strlen_zero(dtmfcalling)) {
02241             ast_verb(3, "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
02242             res = ast_dtmf_stream(chan, peer, dtmfcalling, 250, 0);
02243          }
02244       }
02245 
02246       if (res) { /* some error */
02247          res = -1;
02248       } else {
02249          if (ast_test_flag64(peerflags, OPT_CALLEE_TRANSFER))
02250             ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02251          if (ast_test_flag64(peerflags, OPT_CALLER_TRANSFER))
02252             ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02253          if (ast_test_flag64(peerflags, OPT_CALLEE_HANGUP))
02254             ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
02255          if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP))
02256             ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
02257          if (ast_test_flag64(peerflags, OPT_CALLEE_MONITOR))
02258             ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
02259          if (ast_test_flag64(peerflags, OPT_CALLER_MONITOR))
02260             ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
02261          if (ast_test_flag64(peerflags, OPT_CALLEE_PARK))
02262             ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
02263          if (ast_test_flag64(peerflags, OPT_CALLER_PARK))
02264             ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
02265          if (ast_test_flag64(peerflags, OPT_CALLEE_MIXMONITOR))
02266             ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMIXMON);
02267          if (ast_test_flag64(peerflags, OPT_CALLER_MIXMONITOR))
02268             ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMIXMON);
02269          if (ast_test_flag64(peerflags, OPT_GO_ON))
02270             ast_set_flag(&(config.features_caller), AST_FEATURE_NO_H_EXTEN);
02271 
02272          config.end_bridge_callback = end_bridge_callback;
02273          config.end_bridge_callback_data = chan;
02274          config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
02275          
02276          if (moh) {
02277             moh = 0;
02278             ast_moh_stop(chan);
02279          } else if (sentringing) {
02280             sentringing = 0;
02281             ast_indicate(chan, -1);
02282          }
02283          /* Be sure no generators are left on it and reset the visible indication */
02284          ast_deactivate_generator(chan);
02285          chan->visible_indication = 0;
02286          /* Make sure channels are compatible */
02287          res = ast_channel_make_compatible(chan, peer);
02288          if (res < 0) {
02289             ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
02290             ast_hangup(peer);
02291             res = -1;
02292             goto done;
02293          }
02294          if (opermode) {
02295             struct oprmode oprmode;
02296 
02297             oprmode.peer = peer;
02298             oprmode.mode = opermode;
02299 
02300             ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0);
02301          }
02302          res = ast_bridge_call(chan, peer, &config);
02303       }
02304 
02305       strcpy(peer->context, chan->context);
02306 
02307       if (ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
02308          int autoloopflag;
02309          int found;
02310          int res9;
02311          
02312          strcpy(peer->exten, "h");
02313          peer->priority = 1;
02314          autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
02315          ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP);
02316 
02317          while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num, &found, 1)) == 0)
02318             peer->priority++;
02319 
02320          if (found && res9) {
02321             /* Something bad happened, or a hangup has been requested. */
02322             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
02323             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
02324          }
02325          ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP);  /* set it back the way it was */
02326       }
02327       if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {      
02328          replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
02329          ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
02330          ast_pbx_start(peer);
02331       } else {
02332          if (!ast_check_hangup(chan))
02333             chan->hangupcause = peer->hangupcause;
02334          ast_hangup(peer);
02335       }
02336    }
02337 out:
02338    if (moh) {
02339       moh = 0;
02340       ast_moh_stop(chan);
02341    } else if (sentringing) {
02342       sentringing = 0;
02343       ast_indicate(chan, -1);
02344    }
02345 
02346    if (delprivintro && ast_fileexists(pa.privintro, NULL, NULL) > 0) {
02347       ast_filedelete(pa.privintro, NULL);
02348       if (ast_fileexists(pa.privintro, NULL, NULL) > 0) {
02349          ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa.privintro);
02350       } else {
02351          ast_verb(3, "Successfully deleted %s intro file\n", pa.privintro);
02352       }
02353    }
02354 
02355    ast_channel_early_bridge(chan, NULL);
02356    hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */
02357    pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
02358    senddialendevent(chan, pa.status);
02359    ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
02360    
02361    if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) {
02362       if (!ast_tvzero(calldurationlimit))
02363          memset(&chan->whentohangup, 0, sizeof(chan->whentohangup));
02364       res = 0;
02365    }
02366 
02367 done:
02368    if (config.warning_sound) {
02369       ast_free((char *)config.warning_sound);
02370    }
02371    if (config.end_sound) {
02372       ast_free((char *)config.end_sound);
02373    }
02374    if (config.start_sound) {
02375       ast_free((char *)config.start_sound);
02376    }
02377    return res;
02378 }
02379 
02380 static int dial_exec(struct ast_channel *chan, void *data)
02381 {
02382    struct ast_flags64 peerflags;
02383 
02384    memset(&peerflags, 0, sizeof(peerflags));
02385 
02386    return dial_exec_full(chan, data, &peerflags, NULL);
02387 }
02388 
02389 static int retrydial_exec(struct ast_channel *chan, void *data)
02390 {
02391    char *parse;
02392    const char *context = NULL;
02393    int sleepms = 0, loops = 0, res = -1;
02394    struct ast_flags64 peerflags = { 0, };
02395    AST_DECLARE_APP_ARGS(args,
02396       AST_APP_ARG(announce);
02397       AST_APP_ARG(sleep);
02398       AST_APP_ARG(retries);
02399       AST_APP_ARG(dialdata);
02400    );
02401 
02402    if (ast_strlen_zero(data)) {
02403       ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
02404       return -1;
02405    }
02406 
02407    parse = ast_strdupa(data);
02408    AST_STANDARD_APP_ARGS(args, parse);
02409 
02410    if (!ast_strlen_zero(args.sleep) && (sleepms = atoi(args.sleep)))
02411       sleepms *= 1000;
02412 
02413    if (!ast_strlen_zero(args.retries)) {
02414       loops = atoi(args.retries);
02415    }
02416 
02417    if (!args.dialdata) {
02418       ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp);
02419       goto done;
02420    }
02421 
02422    if (sleepms < 1000)
02423       sleepms = 10000;
02424 
02425    if (!loops)
02426       loops = -1; /* run forever */
02427 
02428    ast_channel_lock(chan);
02429    context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
02430    context = !ast_strlen_zero(context) ? ast_strdupa(context) : NULL;
02431    ast_channel_unlock(chan);
02432 
02433    res = 0;
02434    while (loops) {
02435       int continue_exec;
02436 
02437       chan->data = "Retrying";
02438       if (ast_test_flag(chan, AST_FLAG_MOH))
02439          ast_moh_stop(chan);
02440 
02441       res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec);
02442       if (continue_exec)
02443          break;
02444 
02445       if (res == 0) {
02446          if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) {
02447             if (!ast_strlen_zero(args.announce)) {
02448                if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
02449                   if (!(res = ast_streamfile(chan, args.announce, chan->language)))
02450                      ast_waitstream(chan, AST_DIGIT_ANY);
02451                } else
02452                   ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
02453             }
02454             if (!res && sleepms) {
02455                if (!ast_test_flag(chan, AST_FLAG_MOH))
02456                   ast_moh_start(chan, NULL, NULL);
02457                res = ast_waitfordigit(chan, sleepms);
02458             }
02459          } else {
02460             if (!ast_strlen_zero(args.announce)) {
02461                if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
02462                   if (!(res = ast_streamfile(chan, args.announce, chan->language)))
02463                      res = ast_waitstream(chan, "");
02464                } else
02465                   ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
02466             }
02467             if (sleepms) {
02468                if (!ast_test_flag(chan, AST_FLAG_MOH))
02469                   ast_moh_start(chan, NULL, NULL);
02470                if (!res)
02471                   res = ast_waitfordigit(chan, sleepms);
02472             }
02473          }
02474       }
02475 
02476       if (res < 0 || res == AST_PBX_INCOMPLETE) {
02477          break;
02478       } else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
02479          if (onedigit_goto(chan, context, (char) res, 1)) {
02480             res = 0;
02481             break;
02482          }
02483       }
02484       loops--;
02485    }
02486    if (loops == 0)
02487       res = 0;
02488    else if (res == 1)
02489       res = 0;
02490 
02491    if (ast_test_flag(chan, AST_FLAG_MOH))
02492       ast_moh_stop(chan);
02493  done:
02494    return res;
02495 }
02496 
02497 static int unload_module(void)
02498 {
02499    int res;
02500    struct ast_context *con;
02501 
02502    res = ast_unregister_application(app);
02503    res |= ast_unregister_application(rapp);
02504 
02505    if ((con = ast_context_find("app_dial_gosub_virtual_context"))) {
02506       ast_context_remove_extension2(con, "s", 1, NULL, 0);
02507       ast_context_destroy(con, "app_dial"); /* leave nothing behind */
02508    }
02509 
02510    return res;
02511 }
02512 
02513 static int load_module(void)
02514 {
02515    int res;
02516    struct ast_context *con;
02517 
02518    con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial");
02519    if (!con)
02520       ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
02521    else
02522       ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial");
02523 
02524    res = ast_register_application_xml(app, dial_exec);
02525    res |= ast_register_application_xml(rapp, retrydial_exec);
02526 
02527    return res;
02528 }
02529 
02530 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");