Fri Nov 12 11:45:19 2010

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

Generated by  doxygen 1.6.2