Sat Feb 11 06:33:14 2012

Asterisk developer's documentation


features.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 Routines implementing call features as call pickup, parking and transfer
00022  *
00023  * \author Mark Spencer <markster@digium.com> 
00024  */
00025 
00026 /*** MODULEINFO
00027    <support_level>core</support_level>
00028  ***/
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 354120 $")
00033 
00034 #include "asterisk/_private.h"
00035 
00036 #include <pthread.h>
00037 #include <signal.h>
00038 #include <sys/time.h>
00039 #include <sys/signal.h>
00040 #include <netinet/in.h>
00041 
00042 #include "asterisk/lock.h"
00043 #include "asterisk/file.h"
00044 #include "asterisk/channel.h"
00045 #include "asterisk/pbx.h"
00046 #include "asterisk/causes.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/translate.h"
00049 #include "asterisk/app.h"
00050 #include "asterisk/say.h"
00051 #include "asterisk/features.h"
00052 #include "asterisk/musiconhold.h"
00053 #include "asterisk/config.h"
00054 #include "asterisk/cli.h"
00055 #include "asterisk/manager.h"
00056 #include "asterisk/utils.h"
00057 #include "asterisk/adsi.h"
00058 #include "asterisk/devicestate.h"
00059 #include "asterisk/monitor.h"
00060 #include "asterisk/audiohook.h"
00061 #include "asterisk/global_datastores.h"
00062 #include "asterisk/astobj2.h"
00063 #include "asterisk/cel.h"
00064 #include "asterisk/test.h"
00065 
00066 /*
00067  * Party A - transferee
00068  * Party B - transferer
00069  * Party C - target of transfer
00070  *
00071  * DTMF attended transfer works within the channel bridge.
00072  * Unfortunately, when either party A or B in the channel bridge
00073  * hangs up, that channel is not completely hung up until the
00074  * transfer completes.  This is a real problem depending upon
00075  * the channel technology involved.
00076  *
00077  * For chan_dahdi, the channel is crippled until the hangup is
00078  * complete.  Either the channel is not useable (analog) or the
00079  * protocol disconnect messages are held up (PRI/BRI/SS7) and
00080  * the media is not released.
00081  *
00082  * For chan_sip, a call limit of one is going to block that
00083  * endpoint from any further calls until the hangup is complete.
00084  *
00085  * For party A this is a minor problem.  The party A channel
00086  * will only be in this condition while party B is dialing and
00087  * when party B and C are conferring.  The conversation between
00088  * party B and C is expected to be a short one.  Party B is
00089  * either asking a question of party C or announcing party A.
00090  * Also party A does not have much incentive to hangup at this
00091  * point.
00092  *
00093  * For party B this can be a major problem during a blonde
00094  * transfer.  (A blonde transfer is our term for an attended
00095  * transfer that is converted into a blind transfer. :))  Party
00096  * B could be the operator.  When party B hangs up, he assumes
00097  * that he is out of the original call entirely.  The party B
00098  * channel will be in this condition while party C is ringing,
00099  * while attempting to recall party B, and while waiting between
00100  * call attempts.
00101  *
00102  * WARNING:
00103  * The ATXFER_NULL_TECH conditional is a hack to fix the
00104  * problem.  It will replace the party B channel technology with
00105  * a NULL channel driver.  The consequences of this code is that
00106  * the 'h' extension will not be able to access any channel
00107  * technology specific information like SIP statistics for the
00108  * call.
00109  *
00110  * Uncomment the ATXFER_NULL_TECH define below to replace the
00111  * party B channel technology in the channel bridge to complete
00112  * hanging up the channel technology.
00113  */
00114 //#define ATXFER_NULL_TECH 1
00115 
00116 /*** DOCUMENTATION
00117    <application name="Bridge" language="en_US">
00118       <synopsis>
00119          Bridge two channels.
00120       </synopsis>
00121       <syntax>
00122          <parameter name="channel" required="true">
00123             <para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
00124          </parameter>
00125          <parameter name="options">
00126             <optionlist>
00127                <option name="p">
00128                   <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
00129                </option>
00130                <option name="h">
00131                   <para>Allow the called party to hang up by sending the
00132                   <replaceable>*</replaceable> DTMF digit.</para>
00133                </option>
00134                <option name="H">
00135                   <para>Allow the calling party to hang up by pressing the
00136                   <replaceable>*</replaceable> DTMF digit.</para>
00137                </option>
00138                <option name="k">
00139                   <para>Allow the called party to enable parking of the call by sending
00140                   the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
00141                </option>
00142                <option name="K">
00143                   <para>Allow the calling party to enable parking of the call by sending
00144                    the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
00145                </option>
00146                <option name="L(x[:y][:z])">
00147                   <para>Limit the call to <replaceable>x</replaceable> ms. Play a warning
00148                   when <replaceable>y</replaceable> ms are left. Repeat the warning every
00149                   <replaceable>z</replaceable> ms. The following special variables can be
00150                   used with this option:</para>
00151                   <variablelist>
00152                      <variable name="LIMIT_PLAYAUDIO_CALLER">
00153                         <para>Play sounds to the caller. yes|no (default yes)</para>
00154                      </variable>
00155                      <variable name="LIMIT_PLAYAUDIO_CALLEE">   
00156                         <para>Play sounds to the callee. yes|no</para>
00157                      </variable>
00158                      <variable name="LIMIT_TIMEOUT_FILE">
00159                         <para>File to play when time is up.</para>
00160                      </variable>
00161                      <variable name="LIMIT_CONNECT_FILE">
00162                         <para>File to play when call begins.</para>
00163                      </variable>
00164                      <variable name="LIMIT_WARNING_FILE">
00165                         <para>File to play as warning if <replaceable>y</replaceable> is
00166                         defined. The default is to say the time remaining.</para>
00167                      </variable>
00168                   </variablelist>
00169                </option>
00170                <option name="S(x)">
00171                   <para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
00172                </option>
00173                <option name="t">
00174                   <para>Allow the called party to transfer the calling party by sending the
00175                   DTMF sequence defined in <filename>features.conf</filename>.</para>
00176                </option>
00177                <option name="T">
00178                   <para>Allow the calling party to transfer the called party by sending the
00179                   DTMF sequence defined in <filename>features.conf</filename>.</para>
00180                </option>
00181                <option name="w">
00182                   <para>Allow the called party to enable recording of the call by sending
00183                   the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
00184                </option>
00185                <option name="W">
00186                   <para>Allow the calling party to enable recording of the call by sending
00187                   the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
00188                </option>
00189                <option name="x">
00190                   <para>Cause the called party to be hung up after the bridge, instead of being
00191                   restarted in the dialplan.</para>
00192                </option>
00193             </optionlist>
00194          </parameter>
00195       </syntax>
00196       <description>
00197          <para>Allows the ability to bridge two channels via the dialplan.</para>
00198          <para>This application sets the following channel variable upon completion:</para>
00199          <variablelist>
00200             <variable name="BRIDGERESULT">
00201                <para>The result of the bridge attempt as a text string.</para>
00202                <value name="SUCCESS" />
00203                <value name="FAILURE" />
00204                <value name="LOOP" />
00205                <value name="NONEXISTENT" />
00206                <value name="INCOMPATIBLE" />
00207             </variable>
00208          </variablelist>
00209       </description>
00210    </application>
00211    <application name="ParkedCall" language="en_US">
00212       <synopsis>
00213          Retrieve a parked call.
00214       </synopsis>
00215       <syntax>
00216          <parameter name="exten">
00217             <para>Parking space extension to retrieve a parked call.
00218             If not provided then the first available parked call in the
00219             parking lot will be retrieved.</para>
00220          </parameter>
00221          <parameter name="parking_lot_name">
00222             <para>Specify from which parking lot to retrieve a parked call.</para>
00223             <para>The parking lot used is selected in the following order:</para>
00224             <para>1) parking_lot_name option</para>
00225             <para>2) <variable>PARKINGLOT</variable> variable</para>
00226             <para>3) <literal>CHANNEL(parkinglot)</literal> function
00227             (Possibly preset by the channel driver.)</para>
00228             <para>4) Default parking lot.</para>
00229          </parameter>
00230       </syntax>
00231       <description>
00232          <para>Used to retrieve a parked call from a parking lot.</para>
00233          <note>
00234             <para>Parking lots automatically create and manage dialplan extensions in
00235             the parking lot context.  You do not need to explicitly use this
00236             application in your dialplan.  Instead, all you should do is include the
00237             parking lot context in your dialplan.</para>
00238          </note>
00239       </description>
00240       <see-also>
00241          <ref type="application">Park</ref>
00242          <ref type="application">ParkAndAnnounce</ref>
00243       </see-also>
00244    </application>
00245    <application name="Park" language="en_US">
00246       <synopsis>
00247          Park yourself.
00248       </synopsis>
00249       <syntax>
00250          <parameter name="timeout">
00251             <para>A custom parking timeout for this parked call. Value in milliseconds.</para>
00252          </parameter>
00253          <parameter name="return_context">
00254             <para>The context to return the call to after it times out.</para>
00255          </parameter>
00256          <parameter name="return_exten">
00257             <para>The extension to return the call to after it times out.</para>
00258          </parameter>
00259          <parameter name="return_priority">
00260             <para>The priority to return the call to after it times out.</para>
00261          </parameter>
00262          <parameter name="options">
00263             <para>A list of options for this parked call.</para>
00264             <optionlist>
00265                <option name="r">
00266                   <para>Send ringing instead of MOH to the parked call.</para>
00267                </option>
00268                <option name="R">
00269                   <para>Randomize the selection of a parking space.</para>
00270                </option>
00271                <option name="s">
00272                   <para>Silence announcement of the parking space number.</para>
00273                </option>
00274             </optionlist>
00275          </parameter>
00276          <parameter name="parking_lot_name">
00277             <para>Specify in which parking lot to park a call.</para>
00278             <para>The parking lot used is selected in the following order:</para>
00279             <para>1) parking_lot_name option</para>
00280             <para>2) <variable>PARKINGLOT</variable> variable</para>
00281             <para>3) <literal>CHANNEL(parkinglot)</literal> function
00282             (Possibly preset by the channel driver.)</para>
00283             <para>4) Default parking lot.</para>
00284          </parameter>
00285       </syntax>
00286       <description>
00287          <para>Used to park yourself (typically in combination with a supervised
00288          transfer to know the parking space).</para>
00289          <para>If you set the <variable>PARKINGEXTEN</variable> variable to a
00290          parking space extension in the parking lot, Park() will attempt to park the call
00291          on that extension.  If the extension is already is in use then execution
00292          will continue at the next priority.</para>
00293          <para>If the <literal>parkeddynamic</literal> option is enabled in <filename>features.conf</filename>
00294          the following variables can be used to dynamically create new parking lots.</para>
00295          <para>If you set the <variable>PARKINGDYNAMIC</variable> variable and this parking lot
00296          exists then it will be used as a template for the newly created dynamic lot.  Otherwise,
00297          the default parking lot will be used.</para>
00298          <para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable then the newly created dynamic
00299          parking lot will use this context.</para>
00300          <para>If you set the <variable>PARKINGDYNEXTEN</variable> variable then the newly created dynamic
00301          parking lot will use this extension to access the parking lot.</para>
00302          <para>If you set the <variable>PARKINGDYNPOS</variable> variable then the newly created dynamic parking lot
00303          will use those parking postitions.</para>
00304          <note>
00305             <para>This application must be used as the first extension priority
00306             to be recognized as a parking access extension.  DTMF transfers
00307             and some channel drivers need this distinction to operate properly.
00308             The parking access extension in this case is treated like a dialplan
00309             hint.</para>
00310          </note>
00311          <note>
00312             <para>Parking lots automatically create and manage dialplan extensions in
00313             the parking lot context.  You do not need to explicitly use this
00314             application in your dialplan.  Instead, all you should do is include the
00315             parking lot context in your dialplan.</para>
00316          </note>
00317       </description>
00318       <see-also>
00319          <ref type="application">ParkAndAnnounce</ref>
00320          <ref type="application">ParkedCall</ref>
00321       </see-also>
00322    </application>
00323    <manager name="ParkedCalls" language="en_US">
00324       <synopsis>
00325          List parked calls.
00326       </synopsis>
00327       <syntax>
00328          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00329       </syntax>
00330       <description>
00331          <para>List parked calls.</para>
00332       </description>
00333    </manager>
00334    <manager name="Park" language="en_US">
00335       <synopsis>
00336          Park a channel.
00337       </synopsis>
00338       <syntax>
00339          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00340          <parameter name="Channel" required="true">
00341             <para>Channel name to park.</para>
00342          </parameter>
00343          <parameter name="Channel2" required="true">
00344             <para>Channel to return to if timeout.</para>
00345          </parameter>
00346          <parameter name="Timeout">
00347             <para>Number of milliseconds to wait before callback.</para>
00348          </parameter>
00349          <parameter name="Parkinglot">
00350             <para>Specify in which parking lot to park the channel.</para>
00351          </parameter>
00352       </syntax>
00353       <description>
00354          <para>Park a channel.</para>
00355       </description>
00356    </manager>
00357    <manager name="Bridge" language="en_US">
00358       <synopsis>
00359          Bridge two channels already in the PBX.
00360       </synopsis>
00361       <syntax>
00362          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00363          <parameter name="Channel1" required="true">
00364             <para>Channel to Bridge to Channel2.</para>
00365          </parameter>
00366          <parameter name="Channel2" required="true">
00367             <para>Channel to Bridge to Channel1.</para>
00368          </parameter>
00369          <parameter name="Tone">
00370             <para>Play courtesy tone to Channel 2.</para>
00371             <enumlist>
00372                <enum name="yes" />
00373                <enum name="no" />
00374             </enumlist>
00375          </parameter>
00376       </syntax>
00377       <description>
00378          <para>Bridge together two channels already in the PBX.</para>
00379       </description>
00380    </manager>
00381  ***/
00382 
00383 #define DEFAULT_PARK_TIME                    45000 /*!< ms */
00384 #define DEFAULT_PARK_EXTENSION                  "700"
00385 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT          3000  /*!< ms */
00386 #define DEFAULT_FEATURE_DIGIT_TIMEOUT           1000  /*!< ms */
00387 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000 /*!< ms */
00388 #define DEFAULT_ATXFER_DROP_CALL             0     /*!< Do not drop call. */
00389 #define DEFAULT_ATXFER_LOOP_DELAY               10000 /*!< ms */
00390 #define DEFAULT_ATXFER_CALLBACK_RETRIES            2
00391 #define DEFAULT_COMEBACK_CONTEXT             "parkedcallstimeout"
00392 #define DEFAULT_COMEBACK_TO_ORIGIN              1
00393 #define DEFAULT_COMEBACK_DIAL_TIME              30
00394 
00395 #define AST_MAX_WATCHERS 256
00396 #define MAX_DIAL_FEATURE_OPTIONS 30
00397 
00398 struct feature_group_exten {
00399    AST_LIST_ENTRY(feature_group_exten) entry;
00400    AST_DECLARE_STRING_FIELDS(
00401       AST_STRING_FIELD(exten);
00402    );
00403    struct ast_call_feature *feature;
00404 };
00405 
00406 struct feature_group {
00407    AST_LIST_ENTRY(feature_group) entry;
00408    AST_DECLARE_STRING_FIELDS(
00409       AST_STRING_FIELD(gname);
00410    );
00411    AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
00412 };
00413 
00414 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
00415 
00416 typedef enum {
00417    FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
00418    FEATURE_INTERPRET_DO,     /* Used by feature_interpret */
00419    FEATURE_INTERPRET_CHECK,  /* Used by feature_check */
00420 } feature_interpret_op;
00421 
00422 static const char *parkedcall = "ParkedCall";
00423 
00424 static char pickup_ext[AST_MAX_EXTENSION];                 /*!< Call pickup extension */
00425 
00426 /*! Parking lot access ramp dialplan usage entry. */
00427 struct parking_dp_ramp {
00428    /*! Next node in the parking lot spaces dialplan list. */
00429    AST_LIST_ENTRY(parking_dp_ramp) node;
00430    /*! TRUE if the parking lot access extension is exclusive. */
00431    unsigned int exclusive:1;
00432    /*! Parking lot access extension */
00433    char exten[1];
00434 };
00435 
00436 /*! Parking lot dialplan access ramp map */
00437 AST_LIST_HEAD_NOLOCK(parking_dp_ramp_map, parking_dp_ramp);
00438 
00439 /*! Parking lot spaces dialplan usage entry. */
00440 struct parking_dp_spaces {
00441    /*! Next node in the parking lot spaces dialplan list. */
00442    AST_LIST_ENTRY(parking_dp_spaces) node;
00443    /*! First parking space */
00444    int start;
00445    /*! Last parking space */
00446    int stop;
00447 };
00448 
00449 /*! Parking lot dialplan context space map */
00450 AST_LIST_HEAD_NOLOCK(parking_dp_space_map, parking_dp_spaces);
00451 
00452 /*! Parking lot context dialplan usage entry. */
00453 struct parking_dp_context {
00454    /*! Next node in the parking lot contexts dialplan list. */
00455    AST_LIST_ENTRY(parking_dp_context) node;
00456    /*! Parking access extensions defined in this context. */
00457    struct parking_dp_ramp_map access_extens;
00458    /*! Parking spaces defined in this context. */
00459    struct parking_dp_space_map spaces;
00460    /*! Parking hints defined in this context. */
00461    struct parking_dp_space_map hints;
00462    /*! Parking lot context name */
00463    char context[1];
00464 };
00465 
00466 /*! Parking lot dialplan usage map. */
00467 AST_LIST_HEAD_NOLOCK(parking_dp_map, parking_dp_context);
00468 
00469 /*!
00470  * \brief Description of one parked call, added to a list while active, then removed.
00471  * The list belongs to a parkinglot.
00472  */
00473 struct parkeduser {
00474    struct ast_channel *chan;                   /*!< Parked channel */
00475    struct timeval start;                       /*!< Time the park started */
00476    int parkingnum;                             /*!< Parking lot space used */
00477    char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
00478    char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
00479    char exten[AST_MAX_EXTENSION];
00480    int priority;
00481    int parkingtime;                            /*!< Maximum length in parking lot before return */
00482    /*! Method to entertain the caller when parked: AST_CONTROL_RINGING, AST_CONTROL_HOLD, or 0(none) */
00483    enum ast_control_frame_type hold_method;
00484    unsigned int notquiteyet:1;
00485    unsigned int options_specified:1;
00486    char peername[AST_CHANNEL_NAME];
00487    unsigned char moh_trys;
00488    /*! Parking lot this entry belongs to.  Holds a parking lot reference. */
00489    struct ast_parkinglot *parkinglot;
00490    AST_LIST_ENTRY(parkeduser) list;
00491 };
00492 
00493 /*! Parking lot configuration options. */
00494 struct parkinglot_cfg {
00495    /*! Music class used for parking */
00496    char mohclass[MAX_MUSICCLASS];
00497    /*! Extension to park calls in this parking lot. */
00498    char parkext[AST_MAX_EXTENSION];
00499    /*! Context for which parking is made accessible */
00500    char parking_con[AST_MAX_CONTEXT];
00501    /*! Context that timed-out parked calls are called back on when comebacktoorigin=no */
00502    char comebackcontext[AST_MAX_CONTEXT];
00503    /*! First available extension for parking */
00504    int parking_start;
00505    /*! Last available extension for parking */
00506    int parking_stop;
00507    /*! Default parking time in ms. */
00508    int parkingtime;
00509    /*!
00510     * \brief Enable DTMF based transfers on bridge when picking up parked calls.
00511     *
00512     * \details
00513     * none(0)
00514     * AST_FEATURE_FLAG_BYCALLEE
00515     * AST_FEATURE_FLAG_BYCALLER
00516     * AST_FEATURE_FLAG_BYBOTH
00517     */
00518    int parkedcalltransfers;
00519    /*!
00520     * \brief Enable DTMF based parking on bridge when picking up parked calls.
00521     *
00522     * \details
00523     * none(0)
00524     * AST_FEATURE_FLAG_BYCALLEE
00525     * AST_FEATURE_FLAG_BYCALLER
00526     * AST_FEATURE_FLAG_BYBOTH
00527     */
00528    int parkedcallreparking;
00529    /*!
00530     * \brief Enable DTMF based hangup on a bridge when pickup up parked calls.
00531     *
00532     * \details
00533     * none(0)
00534     * AST_FEATURE_FLAG_BYCALLEE
00535     * AST_FEATURE_FLAG_BYCALLER
00536     * AST_FEATURE_FLAG_BYBOTH
00537     */
00538    int parkedcallhangup;
00539    /*!
00540     * \brief Enable DTMF based recording on a bridge when picking up parked calls.
00541     *
00542     * \details
00543     * none(0)
00544     * AST_FEATURE_FLAG_BYCALLEE
00545     * AST_FEATURE_FLAG_BYCALLER
00546     * AST_FEATURE_FLAG_BYBOTH
00547     */
00548    int parkedcallrecording;
00549 
00550    /*! Time in seconds to dial the device that parked a timedout parked call */
00551    unsigned int comebackdialtime;
00552    /*! TRUE if findslot is set to next */
00553    unsigned int parkfindnext:1;
00554    /*! TRUE if the parking lot is exclusively accessed by parkext */
00555    unsigned int parkext_exclusive:1;
00556    /*! Add parking hints automatically */
00557    unsigned int parkaddhints:1;
00558    /*! TRUE if configuration is invalid and the parking lot should not be used. */
00559    unsigned int is_invalid:1;
00560    /*! TRUE if a timed out parked call goes back to the parker */
00561    unsigned int comebacktoorigin:1;
00562 };
00563 
00564 /*! \brief Structure for parking lots which are put in a container. */
00565 struct ast_parkinglot {
00566    /*! Name of the parking lot. */
00567    char name[AST_MAX_CONTEXT];
00568    /*! Parking lot user configuration. */
00569    struct parkinglot_cfg cfg;
00570 
00571    /*! Parking space to start next park search. */
00572    int next_parking_space;
00573 
00574    /*! That which bears the_mark shall be deleted if parking lot empty! (Used during reloads.) */
00575    unsigned int the_mark:1;
00576    /*! TRUE if the parking lot is disabled. */
00577    unsigned int disabled:1;
00578 
00579    /*! List of active parkings in this parkinglot */
00580    AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings;
00581 };
00582 
00583 /*! \brief The configured parking lots container. Always at least one  - the default parking lot */
00584 static struct ao2_container *parkinglots;
00585 
00586 /*!
00587  * \brief Default parking lot.
00588  * \note Holds a parkinglot reference.
00589  * \note Will not be NULL while running.
00590  */
00591 static struct ast_parkinglot *default_parkinglot;
00592 
00593 /*! Force a config reload to reload regardless of config file timestamp. */
00594 static int force_reload_load;
00595 
00596 static int parkedplay = 0;                                 /*!< Who to play courtesytone to when someone picks up a parked call. */
00597 static int parkeddynamic = 0;                              /*!< Enable creation of parkinglots dynamically */
00598 static char courtesytone[256];                             /*!< Courtesy tone used to pickup parked calls and on-touch-record */
00599 static char xfersound[256];                                /*!< Call transfer sound */
00600 static char xferfailsound[256];                            /*!< Call transfer failure sound */
00601 static char pickupsound[256];                              /*!< Pickup sound */
00602 static char pickupfailsound[256];                          /*!< Pickup failure sound */
00603 
00604 /*!
00605  * \brief Context for parking dialback to parker.
00606  * \note The need for the context is a KLUDGE.
00607  *
00608  * \todo Might be able to eliminate the parking_con_dial context
00609  * kludge by running app_dial directly in its own thread to
00610  * simulate a PBX.
00611  */
00612 static char parking_con_dial[] = "park-dial";
00613 
00614 /*! Ensure that features.conf reloads on one thread at a time. */
00615 AST_MUTEX_DEFINE_STATIC(features_reload_lock);
00616 
00617 static int adsipark;
00618 
00619 static int transferdigittimeout;
00620 static int featuredigittimeout;
00621 
00622 static int atxfernoanswertimeout;
00623 static unsigned int atxferdropcall;
00624 static unsigned int atxferloopdelay;
00625 static unsigned int atxfercallbackretries;
00626 
00627 static char *registrar = "features";         /*!< Registrar for operations */
00628 
00629 /*! PARK_APP_NAME application arguments */
00630 AST_DEFINE_APP_ARGS_TYPE(park_app_args,
00631    AST_APP_ARG(timeout);      /*!< Time in ms to remain in the parking lot. */
00632    AST_APP_ARG(return_con);   /*!< Context to return parked call if timeout. */
00633    AST_APP_ARG(return_ext);   /*!< Exten to return parked call if timeout. */
00634    AST_APP_ARG(return_pri);   /*!< Priority to return parked call if timeout. */
00635    AST_APP_ARG(options);      /*!< Parking option flags. */
00636    AST_APP_ARG(pl_name);      /*!< Parking lot name to use if present. */
00637    AST_APP_ARG(dummy);        /*!< Place to put any remaining args string. */
00638    );
00639 
00640 /* module and CLI command definitions */
00641 static const char *parkcall = "Park";
00642 
00643 static struct ast_app *monitor_app = NULL;
00644 static int monitor_ok = 1;
00645 
00646 static struct ast_app *mixmonitor_app = NULL;
00647 static int mixmonitor_ok = 1;
00648 
00649 static struct ast_app *stopmixmonitor_app = NULL;
00650 static int stopmixmonitor_ok = 1;
00651 
00652 static pthread_t parking_thread;
00653 struct ast_dial_features {
00654    struct ast_flags features_caller;
00655    struct ast_flags features_callee;
00656    int is_caller;
00657 };
00658 
00659 #if defined(ATXFER_NULL_TECH)
00660 /*!
00661  * \internal
00662  * \brief Set the channel technology to the kill technology.
00663  *
00664  * \param chan Channel to change technology.
00665  *
00666  * \return Nothing
00667  */
00668 static void set_kill_chan_tech(struct ast_channel *chan)
00669 {
00670    int idx;
00671 
00672    ast_channel_lock(chan);
00673 
00674    /* Hangup the channel's physical side */
00675    if (chan->tech->hangup) {
00676       chan->tech->hangup(chan);
00677    }
00678    if (chan->tech_pvt) {
00679       ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n",
00680          ast_channel_name(chan));
00681       ast_free(chan->tech_pvt);
00682       chan->tech_pvt = NULL;
00683    }
00684 
00685    /* Install the kill technology and wake up anyone waiting on it. */
00686    chan->tech = &ast_kill_tech;
00687    for (idx = 0; idx < AST_MAX_FDS; ++idx) {
00688       switch (idx) {
00689       case AST_ALERT_FD:
00690       case AST_TIMING_FD:
00691       case AST_GENERATOR_FD:
00692          /* Don't clear these fd's. */
00693          break;
00694       default:
00695          ast_channel_set_fd(chan, idx, -1);
00696          break;
00697       }
00698    }
00699    ast_queue_frame(chan, &ast_null_frame);
00700 
00701    ast_channel_unlock(chan);
00702 }
00703 #endif   /* defined(ATXFER_NULL_TECH) */
00704 
00705 #if defined(ATXFER_NULL_TECH)
00706 /*!
00707  * \internal
00708  * \brief Set the channel name to something unique.
00709  *
00710  * \param chan Channel to change name.
00711  *
00712  * \return Nothing
00713  */
00714 static void set_new_chan_name(struct ast_channel *chan)
00715 {
00716    static int seq_num_last;
00717    int seq_num;
00718    int len;
00719    char *chan_name;
00720    char dummy[1];
00721 
00722    /* Create the new channel name string. */
00723    ast_channel_lock(chan);
00724    seq_num = ast_atomic_fetchadd_int(&seq_num_last, +1);
00725    len = snprintf(dummy, sizeof(dummy), "%s<XFER_%x>", ast_channel_name(chan), seq_num) + 1;
00726    chan_name = alloca(len);
00727    snprintf(chan_name, len, "%s<XFER_%x>", ast_channel_name(chan), seq_num);
00728    ast_channel_unlock(chan);
00729 
00730    ast_change_name(chan, chan_name);
00731 }
00732 #endif   /* defined(ATXFER_NULL_TECH) */
00733 
00734 static void *dial_features_duplicate(void *data)
00735 {
00736    struct ast_dial_features *df = data, *df_copy;
00737  
00738    if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
00739       return NULL;
00740    }
00741  
00742    memcpy(df_copy, df, sizeof(*df));
00743  
00744    return df_copy;
00745 }
00746 
00747 static void dial_features_destroy(void *data)
00748 {
00749    struct ast_dial_features *df = data;
00750    if (df) {
00751       ast_free(df);
00752    }
00753 }
00754 
00755 static const struct ast_datastore_info dial_features_info = {
00756    .type = "dial-features",
00757    .destroy = dial_features_destroy,
00758    .duplicate = dial_features_duplicate,
00759 };
00760  
00761 /* Forward declarations */
00762 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
00763 static void parkinglot_unref(struct ast_parkinglot *parkinglot);
00764 static struct ast_parkinglot *find_parkinglot(const char *name);
00765 static struct ast_parkinglot *create_parkinglot(const char *name);
00766 static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
00767 static int parkinglot_activate(struct ast_parkinglot *parkinglot);
00768 static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile);
00769 
00770 /*!
00771  * \internal
00772  * \brief Get the parking extension if it exists.
00773  *
00774  * \param exten_str Parking extension to see if exists.
00775  * \param chan Channel to autoservice while looking for exten.  (Could be NULL)
00776  * \param context Parking context to look in for exten.
00777  *
00778  * \retval exten on success.
00779  * \retval NULL on error or exten does not exist.
00780  */
00781 static struct ast_exten *get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
00782 {
00783    struct ast_exten *exten;
00784    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
00785    const char *app_at_exten;
00786 
00787    exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL,
00788       E_MATCH);
00789    if (!exten) {
00790       return NULL;
00791    }
00792 
00793    app_at_exten = ast_get_extension_app(exten);
00794    if (!app_at_exten || strcasecmp(parkcall, app_at_exten)) {
00795       return NULL;
00796    }
00797 
00798    return exten;
00799 }
00800 
00801 int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
00802 {
00803    return get_parking_exten(exten_str, chan, context) ? 1 : 0;
00804 }
00805 
00806 const char *ast_pickup_ext(void)
00807 {
00808    return pickup_ext;
00809 }
00810 
00811 struct ast_bridge_thread_obj 
00812 {
00813    struct ast_bridge_config bconfig;
00814    struct ast_channel *chan;
00815    struct ast_channel *peer;
00816    unsigned int return_to_pbx:1;
00817 };
00818 
00819 static int parkinglot_hash_cb(const void *obj, const int flags)
00820 {
00821    const struct ast_parkinglot *parkinglot = obj;
00822 
00823    return ast_str_case_hash(parkinglot->name);
00824 }
00825 
00826 static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
00827 {
00828    struct ast_parkinglot *parkinglot = obj;
00829    struct ast_parkinglot *parkinglot2 = arg;
00830 
00831    return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
00832 }
00833 
00834 /*!
00835  * \brief store context, extension and priority 
00836  * \param chan, context, ext, pri
00837  */
00838 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
00839 {
00840    ast_copy_string(chan->context, context, sizeof(chan->context));
00841    ast_copy_string(chan->exten, ext, sizeof(chan->exten));
00842    chan->priority = pri;
00843 }
00844 
00845 /*!
00846  * \brief Check goto on transfer
00847  * \param chan
00848  *
00849  * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
00850  * When found make sure the types are compatible. Check if channel is valid
00851  * if so start the new channel else hangup the call. 
00852  */
00853 static void check_goto_on_transfer(struct ast_channel *chan) 
00854 {
00855    struct ast_channel *xferchan;
00856    const char *val;
00857    char *goto_on_transfer;
00858    char *x;
00859 
00860    ast_channel_lock(chan);
00861    val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
00862    if (ast_strlen_zero(val)) {
00863       ast_channel_unlock(chan);
00864       return;
00865    }
00866    goto_on_transfer = ast_strdupa(val);
00867    ast_channel_unlock(chan);
00868 
00869    ast_debug(1, "Attempting GOTO_ON_BLINDXFR=%s for %s.\n", val, ast_channel_name(chan));
00870 
00871    xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", ast_channel_linkedid(chan), 0,
00872       "%s", ast_channel_name(chan));
00873    if (!xferchan) {
00874       return;
00875    }
00876 
00877    /* Make formats okay */
00878    xferchan->readformat = chan->readformat;
00879    xferchan->writeformat = chan->writeformat;
00880 
00881    if (ast_channel_masquerade(xferchan, chan)) {
00882       /* Failed to setup masquerade. */
00883       ast_hangup(xferchan);
00884       return;
00885    }
00886 
00887    for (x = goto_on_transfer; *x; ++x) {
00888       if (*x == '^') {
00889          *x = ',';
00890       }
00891    }
00892    ast_parseable_goto(xferchan, goto_on_transfer);
00893    xferchan->_state = AST_STATE_UP;
00894    ast_clear_flag(xferchan, AST_FLAGS_ALL);  
00895    ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
00896 
00897    if (ast_do_masquerade(xferchan) || ast_pbx_start(xferchan)) {
00898       /* Failed to do masquerade or could not start PBX. */
00899       ast_hangup(xferchan);
00900    }
00901 }
00902 
00903 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
00904    const char *caller_name, struct ast_channel *requestor,
00905    struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, const char *addr,
00906    int timeout, int *outstate, const char *language);
00907 
00908 /*!
00909  * \brief bridge the call 
00910  * \param data thread bridge.
00911  *
00912  * Set Last Data for respective channels, reset cdr for channels
00913  * bridge call, check if we're going back to dialplan
00914  * if not hangup both legs of the call
00915  */
00916 static void *bridge_call_thread(void *data)
00917 {
00918    struct ast_bridge_thread_obj *tobj = data;
00919    int res;
00920 
00921    tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
00922    tobj->chan->data = ast_channel_name(tobj->peer);
00923    tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
00924    tobj->peer->data = ast_channel_name(tobj->chan);
00925 
00926    ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
00927 
00928    if (tobj->return_to_pbx) {
00929       if (!ast_check_hangup(tobj->peer)) {
00930          ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", ast_channel_name(tobj->peer));
00931          res = ast_pbx_start(tobj->peer);
00932          if (res != AST_PBX_SUCCESS)
00933             ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", ast_channel_name(tobj->peer));
00934       } else
00935          ast_hangup(tobj->peer);
00936       if (!ast_check_hangup(tobj->chan)) {
00937          ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", ast_channel_name(tobj->chan));
00938          res = ast_pbx_start(tobj->chan);
00939          if (res != AST_PBX_SUCCESS)
00940             ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", ast_channel_name(tobj->chan));
00941       } else
00942          ast_hangup(tobj->chan);
00943    } else {
00944       ast_hangup(tobj->chan);
00945       ast_hangup(tobj->peer);
00946    }
00947 
00948    ast_free(tobj);
00949 
00950    return NULL;
00951 }
00952 
00953 /*!
00954  * \brief create thread for the parked call
00955  * \param data
00956  *
00957  * Create thread and attributes, call bridge_call_thread
00958  */
00959 static void bridge_call_thread_launch(void *data) 
00960 {
00961    pthread_t thread;
00962    pthread_attr_t attr;
00963    struct sched_param sched;
00964 
00965    pthread_attr_init(&attr);
00966    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00967    ast_pthread_create(&thread, &attr, bridge_call_thread, data);
00968    pthread_attr_destroy(&attr);
00969    memset(&sched, 0, sizeof(sched));
00970    pthread_setschedparam(thread, SCHED_RR, &sched);
00971 }
00972 
00973 /*!
00974  * \brief Announce call parking by ADSI
00975  * \param chan .
00976  * \param parkingexten .
00977  * Create message to show for ADSI, display message.
00978  * \retval 0 on success.
00979  * \retval -1 on failure.
00980  */
00981 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
00982 {
00983    int res;
00984    int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
00985    char tmp[256];
00986    char *message[5] = {NULL, NULL, NULL, NULL, NULL};
00987 
00988    snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
00989    message[0] = tmp;
00990    res = ast_adsi_load_session(chan, NULL, 0, 1);
00991    if (res == -1)
00992       return res;
00993    return ast_adsi_print(chan, message, justify, 1);
00994 }
00995 
00996 /*!
00997  * \brief Find parking lot name from channel
00998  * \note Channel needs to be locked while the returned string is in use.
00999  */
01000 static const char *findparkinglotname(struct ast_channel *chan)
01001 {
01002    const char *name;
01003 
01004    /* The channel variable overrides everything */
01005    name = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
01006    if (!name && !ast_strlen_zero(ast_channel_parkinglot(chan))) {
01007       /* Use the channel's parking lot. */
01008       name = ast_channel_parkinglot(chan);
01009    }
01010    return name;
01011 }
01012 
01013 /*! \brief Notify metermaids that we've changed an extension */
01014 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
01015 {
01016    ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
01017       exten, context, ast_devstate2str(state));
01018 
01019    ast_devstate_changed(state, "park:%s@%s", exten, context);
01020 }
01021 
01022 /*! \brief metermaids callback from devicestate.c */
01023 static enum ast_device_state metermaidstate(const char *data)
01024 {
01025    char *context;
01026    char *exten;
01027 
01028    context = ast_strdupa(data);
01029 
01030    exten = strsep(&context, "@");
01031    if (!context)
01032       return AST_DEVICE_INVALID;
01033 
01034    ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
01035 
01036    if (!ast_exists_extension(NULL, context, exten, 1, NULL))
01037       return AST_DEVICE_NOT_INUSE;
01038 
01039    return AST_DEVICE_INUSE;
01040 }
01041 
01042 /*! Options to pass to park_call_full */
01043 enum ast_park_call_options {
01044    /*! Provide ringing to the parked caller instead of music on hold */
01045    AST_PARK_OPT_RINGING =   (1 << 0),
01046    /*! Randomly choose a parking spot for the caller instead of choosing
01047     *  the first one that is available. */
01048    AST_PARK_OPT_RANDOMIZE = (1 << 1),
01049    /*! Do not announce the parking number */
01050    AST_PARK_OPT_SILENCE = (1 << 2),
01051 };
01052 
01053 /*! Optional additional parking options when parking a call. */
01054 struct ast_park_call_args {
01055    /*! How long to wait in the parking lot before the call gets sent back
01056     *  to the specified return extension (or a best guess at where it came
01057     *  from if not explicitly specified). */
01058    int timeout;
01059    /*! An output parameter to store the parking space where the parked caller
01060     *  was placed. */
01061    int *extout;
01062    const char *orig_chan_name;
01063    const char *return_con;
01064    const char *return_ext;
01065    int return_pri;
01066    uint32_t flags;
01067    /*! Parked user that has already obtained a parking space */
01068    struct parkeduser *pu;
01069    /*! \brief Parkinglot to be parked in */
01070    struct ast_parkinglot *parkinglot;
01071 };
01072 
01073 /*!
01074  * \internal
01075  * \brief Create a dynamic parking lot.
01076  *
01077  * \param name Dynamic parking lot name to create.
01078  * \param chan Channel to get dynamic parking lot parameters.
01079  *
01080  * \retval parkinglot on success.
01081  * \retval NULL on error.
01082  */
01083 static struct ast_parkinglot *create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
01084 {
01085    const char *dyn_context;
01086    const char *dyn_exten;
01087    const char *dyn_range;
01088    const char *template_name;
01089    struct ast_parkinglot *template_parkinglot = NULL;
01090    struct ast_parkinglot *parkinglot;
01091    int dyn_start;
01092    int dyn_end;
01093 
01094    ast_channel_lock(chan);
01095    template_name = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
01096    dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
01097    dyn_exten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNEXTEN"), ""));
01098    dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
01099    ast_channel_unlock(chan);
01100 
01101    if (!ast_strlen_zero(template_name)) {
01102       template_parkinglot = find_parkinglot(template_name);
01103       if (!template_parkinglot) {
01104          ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
01105             template_name);
01106       } else if (template_parkinglot->cfg.is_invalid) {
01107          ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
01108             template_name);
01109          parkinglot_unref(template_parkinglot);
01110          template_parkinglot = NULL;
01111       }
01112    }
01113    if (!template_parkinglot) {
01114       template_parkinglot = parkinglot_addref(default_parkinglot);
01115       ast_debug(1, "Using default parking lot for template\n");
01116    }
01117 
01118    parkinglot = copy_parkinglot(name, template_parkinglot);
01119    if (!parkinglot) {
01120       ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
01121    } else {
01122       /* Configure the dynamic parking lot. */
01123       if (!ast_strlen_zero(dyn_context)) {
01124          ast_copy_string(parkinglot->cfg.parking_con, dyn_context,
01125             sizeof(parkinglot->cfg.parking_con));
01126       }
01127       if (!ast_strlen_zero(dyn_exten)) {
01128          ast_copy_string(parkinglot->cfg.parkext, dyn_exten,
01129             sizeof(parkinglot->cfg.parkext));
01130       }
01131       if (!ast_strlen_zero(dyn_range)) {
01132          if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
01133             ast_log(LOG_WARNING,
01134                "Format for parking positions is a-b, where a and b are numbers\n");
01135          } else if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
01136             ast_log(LOG_WARNING,
01137                "Format for parking positions is a-b, where a <= b\n");
01138          } else {
01139             parkinglot->cfg.parking_start = dyn_start;
01140             parkinglot->cfg.parking_stop = dyn_end;
01141          }
01142       }
01143 
01144       /*
01145        * Sanity check for dynamic parking lot configuration.
01146        *
01147        * XXX It may be desirable to instead check if the dynamic
01148        * parking lot overlaps any existing lots like what is done for
01149        * a reload.
01150        */
01151       if (!strcmp(parkinglot->cfg.parking_con, template_parkinglot->cfg.parking_con)) {
01152          if (!strcmp(parkinglot->cfg.parkext, template_parkinglot->cfg.parkext)
01153             && parkinglot->cfg.parkext_exclusive) {
01154             ast_log(LOG_WARNING,
01155                "Parking lot '%s' conflicts with template parking lot '%s'!\n"
01156                "Change either PARKINGDYNCONTEXT or PARKINGDYNEXTEN.\n",
01157                parkinglot->name, template_parkinglot->name);
01158          }
01159          if ((template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_start
01160                && parkinglot->cfg.parking_start <= template_parkinglot->cfg.parking_stop)
01161             || (template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_stop
01162                && parkinglot->cfg.parking_stop <= template_parkinglot->cfg.parking_stop)
01163             || (parkinglot->cfg.parking_start < template_parkinglot->cfg.parking_start
01164                && template_parkinglot->cfg.parking_stop < parkinglot->cfg.parking_stop)) {
01165             ast_log(LOG_WARNING,
01166                "Parking lot '%s' parking spaces overlap template parking lot '%s'!\n"
01167                "Change PARKINGDYNPOS.\n",
01168                parkinglot->name, template_parkinglot->name);
01169          }
01170       }
01171 
01172       parkinglot_activate(parkinglot);
01173       ao2_link(parkinglots, parkinglot);
01174    }
01175    parkinglot_unref(template_parkinglot);
01176 
01177    return parkinglot;
01178 }
01179 
01180 /*!
01181  * \internal
01182  * \brief Abort parking a call that has not completed parking yet.
01183  *
01184  * \param pu Parked user item to clean up.
01185  *
01186  * \note The parking lot parkings list is locked on entry.
01187  *
01188  * \return Nothing
01189  */
01190 static void park_space_abort(struct parkeduser *pu)
01191 {
01192    struct ast_parkinglot *parkinglot;
01193 
01194    parkinglot = pu->parkinglot;
01195 
01196    /* Put back the parking space just allocated. */
01197    --parkinglot->next_parking_space;
01198 
01199    AST_LIST_REMOVE(&parkinglot->parkings, pu, list);
01200 
01201    AST_LIST_UNLOCK(&parkinglot->parkings);
01202    parkinglot_unref(parkinglot);
01203    ast_free(pu);
01204 }
01205 
01206 /*!
01207  * \internal
01208  * \brief Reserve a parking space in a parking lot for a call being parked.
01209  *
01210  * \param park_me Channel being parked.
01211  * \param parker Channel parking the call.
01212  * \param args Optional additional parking options when parking a call.
01213  *
01214  * \return Parked call descriptor or NULL if failed.
01215  * \note The parking lot list is locked if successful.
01216  */
01217 static struct parkeduser *park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
01218 {
01219    struct parkeduser *pu;
01220    int i;
01221    int parking_space = -1;
01222    const char *parkinglotname;
01223    const char *parkingexten;
01224    struct parkeduser *cur;
01225    struct ast_parkinglot *parkinglot = NULL;
01226 
01227    if (args->parkinglot) {
01228       parkinglot = parkinglot_addref(args->parkinglot);
01229       parkinglotname = parkinglot->name;
01230    } else {
01231       if (parker) {
01232          parkinglotname = findparkinglotname(parker);
01233       } else { /* parker was NULL, check park_me (ParkAndAnnounce / res_agi) */
01234          parkinglotname = findparkinglotname(park_me);
01235       }
01236       if (!ast_strlen_zero(parkinglotname)) {
01237          parkinglot = find_parkinglot(parkinglotname);
01238       } else {
01239          /* Parking lot is not specified, so use the default parking lot. */
01240          ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
01241          parkinglot = parkinglot_addref(default_parkinglot);
01242       }
01243    }
01244 
01245    /* Dynamically create parkinglot */
01246    if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
01247       parkinglot = create_dynamic_parkinglot(parkinglotname, park_me);
01248    }
01249 
01250    if (!parkinglot) {
01251       ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", ast_channel_name(park_me));
01252       return NULL;
01253    }
01254 
01255    ast_debug(1, "Parking lot: %s\n", parkinglot->name);
01256    if (parkinglot->disabled || parkinglot->cfg.is_invalid) {
01257       ast_log(LOG_WARNING, "Parking lot %s is not in a useable state.\n",
01258          parkinglot->name);
01259       parkinglot_unref(parkinglot);
01260       return NULL;
01261    }
01262 
01263    /* Allocate memory for parking data */
01264    if (!(pu = ast_calloc(1, sizeof(*pu)))) {
01265       parkinglot_unref(parkinglot);
01266       return NULL;
01267    }
01268 
01269    /* Lock parking list */
01270    AST_LIST_LOCK(&parkinglot->parkings);
01271 
01272    /* Check for channel variable PARKINGEXTEN */
01273    parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(park_me, "PARKINGEXTEN"), ""));
01274    if (!ast_strlen_zero(parkingexten)) {
01275       /*!
01276        * \note The API forces us to specify a numeric parking slot, even
01277        * though the architecture would tend to support non-numeric extensions
01278        * (as are possible with SIP, for example).  Hence, we enforce that
01279        * limitation here.  If extout was not numeric, we could permit
01280        * arbitrary non-numeric extensions.
01281        */
01282       if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space <= 0) {
01283          ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n",
01284             parkingexten);
01285          AST_LIST_UNLOCK(&parkinglot->parkings);
01286          parkinglot_unref(parkinglot);
01287          ast_free(pu);
01288          return NULL;
01289       }
01290 
01291       if (parking_space < parkinglot->cfg.parking_start
01292          || parkinglot->cfg.parking_stop < parking_space) {
01293          /*
01294           * Cannot allow park because parking lots are not setup for
01295           * spaces outside of the lot.  (Things like dialplan hints don't
01296           * exist for outside lot space.)
01297           */
01298          ast_log(LOG_WARNING, "PARKINGEXTEN=%d is not in %s (%d-%d).\n",
01299             parking_space, parkinglot->name, parkinglot->cfg.parking_start,
01300             parkinglot->cfg.parking_stop);
01301          AST_LIST_UNLOCK(&parkinglot->parkings);
01302          parkinglot_unref(parkinglot);
01303          ast_free(pu);
01304          return NULL;
01305       }
01306 
01307       /* Check if requested parking space is in use. */
01308       AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
01309          if (cur->parkingnum == parking_space) {
01310             ast_log(LOG_WARNING, "PARKINGEXTEN=%d is already in use in %s\n",
01311                parking_space, parkinglot->name);
01312             AST_LIST_UNLOCK(&parkinglot->parkings);
01313             parkinglot_unref(parkinglot);
01314             ast_free(pu);
01315             return NULL;
01316          }
01317       }
01318    } else {
01319       /* PARKINGEXTEN is empty, so find a usable extension in the lot to park the call */
01320       int start; /* The first slot we look in the parkinglot. It can be randomized. */
01321       int start_checked = 0; /* flag raised once the first slot is checked */
01322 
01323       /* If using randomize mode, set start to random position on parking range */
01324       if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
01325          start = ast_random() % (parkinglot->cfg.parking_stop - parkinglot->cfg.parking_start + 1);
01326          start += parkinglot->cfg.parking_start;
01327       } else if (parkinglot->cfg.parkfindnext
01328          && parkinglot->cfg.parking_start <= parkinglot->next_parking_space
01329          && parkinglot->next_parking_space <= parkinglot->cfg.parking_stop) {
01330          /* Start looking with the next parking space in the lot. */
01331          start = parkinglot->next_parking_space;
01332       } else {
01333          /* Otherwise, just set it to the start position. */
01334          start = parkinglot->cfg.parking_start;
01335       }
01336 
01337       /* free parking extension linear search: O(n^2) */
01338       for (i = start; ; i++) {
01339          /* If we are past the end, wrap around to the first parking slot*/
01340          if (i == parkinglot->cfg.parking_stop + 1) {
01341             i = parkinglot->cfg.parking_start;
01342          }
01343 
01344          if (i == start) {
01345             /* At this point, if start_checked, we've exhausted all the possible slots. */
01346             if (start_checked) {
01347                break;
01348             } else {
01349                start_checked = 1;
01350             }
01351          }
01352 
01353          /* Search the list of parked calls already in use for i. If we find it, it's in use. */
01354          AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
01355             if (cur->parkingnum == i) {
01356                break;
01357             }
01358          }
01359          if (!cur) {
01360             /* We found a parking space. */
01361             parking_space = i;
01362             break;
01363          }
01364       }
01365       if (parking_space == -1) {
01366          /* We did not find a parking space.  Lot is full. */
01367          ast_log(LOG_WARNING, "No more parking spaces in %s\n", parkinglot->name);
01368          AST_LIST_UNLOCK(&parkinglot->parkings);
01369          parkinglot_unref(parkinglot);
01370          ast_free(pu);
01371          return NULL;
01372       }
01373    }
01374 
01375    /* Prepare for next parking space search. */
01376    parkinglot->next_parking_space = parking_space + 1;
01377 
01378    snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
01379    pu->notquiteyet = 1;
01380    pu->parkingnum = parking_space;
01381    pu->parkinglot = parkinglot;
01382    AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
01383 
01384    return pu;
01385 }
01386 
01387 /* Park a call */
01388 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
01389 {
01390    struct parkeduser *pu = args->pu;
01391    const char *event_from;
01392    char app_data[AST_MAX_EXTENSION + AST_MAX_CONTEXT];
01393 
01394    if (pu == NULL) {
01395       args->pu = pu = park_space_reserve(chan, peer, args);
01396       if (pu == NULL) {
01397          return -1;
01398       }
01399    }
01400 
01401    chan->appl = "Parked Call";
01402    chan->data = NULL;
01403 
01404    pu->chan = chan;
01405 
01406    /* Put the parked channel on hold if we have two different channels */
01407    if (chan != peer) {
01408       if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
01409          pu->hold_method = AST_CONTROL_RINGING;
01410          ast_indicate(pu->chan, AST_CONTROL_RINGING);
01411       } else {
01412          pu->hold_method = AST_CONTROL_HOLD;
01413          ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
01414             S_OR(pu->parkinglot->cfg.mohclass, NULL),
01415             !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
01416       }
01417    }
01418    
01419    pu->start = ast_tvnow();
01420    pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->cfg.parkingtime;
01421    if (args->extout)
01422       *(args->extout) = pu->parkingnum;
01423 
01424    if (peer) { 
01425       /*
01426        * This is so ugly that it hurts, but implementing
01427        * get_base_channel() on local channels could have ugly side
01428        * effects.  We could have
01429        * transferer<->local,1<->local,2<->parking and we need the
01430        * callback name to be that of transferer.  Since local,1/2 have
01431        * the same name we can be tricky and just grab the bridged
01432        * channel from the other side of the local.
01433        */
01434       if (!strcasecmp(peer->tech->type, "Local")) {
01435          struct ast_channel *tmpchan, *base_peer;
01436          char other_side[AST_CHANNEL_NAME];
01437          char *c;
01438 
01439          ast_copy_string(other_side, S_OR(args->orig_chan_name, ast_channel_name(peer)), sizeof(other_side));
01440          if ((c = strrchr(other_side, ';'))) {
01441             *++c = '1';
01442          }
01443          if ((tmpchan = ast_channel_get_by_name(other_side))) {
01444             ast_channel_lock(tmpchan);
01445             if ((base_peer = ast_bridged_channel(tmpchan))) {
01446                ast_copy_string(pu->peername, ast_channel_name(base_peer), sizeof(pu->peername));
01447             }
01448             ast_channel_unlock(tmpchan);
01449             tmpchan = ast_channel_unref(tmpchan);
01450          }
01451       } else {
01452          ast_copy_string(pu->peername, S_OR(args->orig_chan_name, ast_channel_name(peer)), sizeof(pu->peername));
01453       }
01454    }
01455 
01456    /*
01457     * Remember what had been dialed, so that if the parking
01458     * expires, we try to come back to the same place
01459     */
01460    pu->options_specified = (!ast_strlen_zero(args->return_con) || !ast_strlen_zero(args->return_ext) || args->return_pri);
01461 
01462    /*
01463     * If extension has options specified, they override all other
01464     * possibilities such as the returntoorigin flag and transferred
01465     * context.  Information on extension options is lost here, so
01466     * we set a flag
01467     */
01468    ast_copy_string(pu->context, 
01469       S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)), 
01470       sizeof(pu->context));
01471    ast_copy_string(pu->exten, 
01472       S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)), 
01473       sizeof(pu->exten));
01474    pu->priority = args->return_pri ? args->return_pri : 
01475       (chan->macropriority ? chan->macropriority : chan->priority);
01476 
01477    /*
01478     * If parking a channel directly, don't quite yet get parking
01479     * running on it.  All parking lot entries are put into the
01480     * parking lot with notquiteyet on.
01481     */
01482    if (peer != chan) {
01483       pu->notquiteyet = 0;
01484    }
01485 
01486    /* Wake up the (presumably select()ing) thread */
01487    pthread_kill(parking_thread, SIGURG);
01488    ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n",
01489       ast_channel_name(pu->chan), pu->parkingnum, pu->parkinglot->name,
01490       pu->context, pu->exten, pu->priority, (pu->parkingtime / 1000));
01491 
01492    ast_cel_report_event(pu->chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
01493 
01494    if (peer) {
01495       event_from = ast_channel_name(peer);
01496    } else {
01497       event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
01498    }
01499 
01500    ast_manager_event(pu->chan, EVENT_FLAG_CALL, "ParkedCall",
01501       "Exten: %s\r\n"
01502       "Channel: %s\r\n"
01503       "Parkinglot: %s\r\n"
01504       "From: %s\r\n"
01505       "Timeout: %ld\r\n"
01506       "CallerIDNum: %s\r\n"
01507       "CallerIDName: %s\r\n"
01508       "ConnectedLineNum: %s\r\n"
01509       "ConnectedLineName: %s\r\n"
01510       "Uniqueid: %s\r\n",
01511       pu->parkingexten, ast_channel_name(pu->chan), pu->parkinglot->name, event_from ? event_from : "",
01512       (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
01513       S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
01514       S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
01515       S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
01516       S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
01517       ast_channel_uniqueid(pu->chan)
01518       );
01519 
01520    if (peer && adsipark && ast_adsi_available(peer)) {
01521       adsi_announce_park(peer, pu->parkingexten);  /* Only supports parking numbers */
01522       ast_adsi_unload_session(peer);
01523    }
01524 
01525    snprintf(app_data, sizeof(app_data), "%s,%s", pu->parkingexten,
01526       pu->parkinglot->name);
01527    if (ast_add_extension(pu->parkinglot->cfg.parking_con, 1, pu->parkingexten, 1,
01528       NULL, NULL, parkedcall, ast_strdup(app_data), ast_free_ptr, registrar)) {
01529       ast_log(LOG_ERROR, "Could not create parked call exten: %s@%s\n",
01530          pu->parkingexten, pu->parkinglot->cfg.parking_con);
01531    } else {
01532       notify_metermaids(pu->parkingexten, pu->parkinglot->cfg.parking_con, AST_DEVICE_INUSE);
01533    }
01534 
01535    AST_LIST_UNLOCK(&pu->parkinglot->parkings);
01536 
01537    /* Only say number if it's a number and the channel hasn't been masqueraded away */
01538    if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE)
01539       && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(ast_channel_name(peer), args->orig_chan_name))) {
01540       /*
01541        * If a channel is masqueraded into peer while playing back the
01542        * parking space number do not continue playing it back.  This
01543        * is the case if an attended transfer occurs.
01544        */
01545       ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
01546       /* Tell the peer channel the number of the parking space */
01547       ast_say_digits(peer, pu->parkingnum, "", ast_channel_language(peer));
01548       ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
01549    }
01550    if (peer == chan) { /* pu->notquiteyet = 1 */
01551       /* Wake up parking thread if we're really done */
01552       pu->hold_method = AST_CONTROL_HOLD;
01553       ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
01554          S_OR(pu->parkinglot->cfg.mohclass, NULL),
01555          !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
01556       pu->notquiteyet = 0;
01557       pthread_kill(parking_thread, SIGURG);
01558    }
01559    return 0;
01560 }
01561 
01562 int ast_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
01563 {
01564    int res;
01565    char *parse;
01566    const char *app_data;
01567    struct ast_exten *exten;
01568    struct park_app_args app_args;
01569    struct ast_park_call_args args = {
01570       .timeout = timeout,
01571       .extout = extout,
01572    };
01573 
01574    if (!park_exten || !park_context) {
01575       return park_call_full(park_me, parker, &args);
01576    }
01577 
01578    /*
01579     * Determiine if the specified park extension has an exclusive
01580     * parking lot to use.
01581     */
01582    if (parker && parker != park_me) {
01583       ast_autoservice_start(park_me);
01584    }
01585    exten = get_parking_exten(park_exten, parker, park_context);
01586    if (exten) {
01587       app_data = ast_get_extension_app_data(exten);
01588       if (!app_data) {
01589          app_data = "";
01590       }
01591       parse = ast_strdupa(app_data);
01592       AST_STANDARD_APP_ARGS(app_args, parse);
01593    
01594       if (!ast_strlen_zero(app_args.pl_name)) {
01595          /* Find the specified exclusive parking lot */
01596          args.parkinglot = find_parkinglot(app_args.pl_name);
01597          if (!args.parkinglot && parkeddynamic) {
01598             args.parkinglot = create_dynamic_parkinglot(app_args.pl_name, park_me);
01599          }
01600       }
01601    }
01602    if (parker && parker != park_me) {
01603       ast_autoservice_stop(park_me);
01604    }
01605 
01606    res = park_call_full(park_me, parker, &args);
01607    if (args.parkinglot) {
01608       parkinglot_unref(args.parkinglot);
01609    }
01610    return res;
01611 }
01612 
01613 int ast_park_call(struct ast_channel *park_me, struct ast_channel *parker, int timeout, const char *park_exten, int *extout)
01614 {
01615    struct ast_park_call_args args = {
01616       .timeout = timeout,
01617       .extout = extout,
01618    };
01619 
01620    return park_call_full(park_me, parker, &args);
01621 }
01622 
01623 /*!
01624  * \brief Park call via masqueraded channel and announce parking spot on peer channel.
01625  *
01626  * \param rchan the real channel to be parked
01627  * \param peer the channel to have the parking read to.
01628  * \param args Additional parking options when parking a call.
01629  *
01630  * \retval 0 on success.
01631  * \retval -1 on failure.
01632  */
01633 static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
01634 {
01635    struct ast_channel *chan;
01636 
01637    /* Make a new, channel that we'll use to masquerade in the real one */
01638    chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, ast_channel_accountcode(rchan), rchan->exten,
01639       rchan->context, ast_channel_linkedid(rchan), rchan->amaflags, "Parked/%s", ast_channel_name(rchan));
01640    if (!chan) {
01641       ast_log(LOG_WARNING, "Unable to create parked channel\n");
01642       if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
01643          if (peer == rchan) {
01644             /* Only have one channel to worry about. */
01645             ast_stream_and_wait(peer, "pbx-parkingfailed", "");
01646          } else if (peer) {
01647             /* Have two different channels to worry about. */
01648             play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
01649          }
01650       }
01651       return -1;
01652    }
01653 
01654    args->pu = park_space_reserve(rchan, peer, args);
01655    if (!args->pu) {
01656       ast_hangup(chan);
01657       if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
01658          if (peer == rchan) {
01659             /* Only have one channel to worry about. */
01660             ast_stream_and_wait(peer, "pbx-parkingfailed", "");
01661          } else if (peer) {
01662             /* Have two different channels to worry about. */
01663             play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
01664          }
01665       }
01666       return -1;
01667    }
01668 
01669    /* Make formats okay */
01670    chan->readformat = rchan->readformat;
01671    chan->writeformat = rchan->writeformat;
01672 
01673    if (ast_channel_masquerade(chan, rchan)) {
01674       park_space_abort(args->pu);
01675       args->pu = NULL;
01676       ast_hangup(chan);
01677       if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
01678          if (peer == rchan) {
01679             /* Only have one channel to worry about. */
01680             ast_stream_and_wait(peer, "pbx-parkingfailed", "");
01681          } else if (peer) {
01682             /* Have two different channels to worry about. */
01683             play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
01684          }
01685       }
01686       return -1;
01687    }
01688 
01689    /* Setup the extensions and such */
01690    set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
01691 
01692    /* Setup the macro extension and such */
01693    ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
01694    ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
01695    chan->macropriority = rchan->macropriority;
01696 
01697    /* Manually do the masquerade to make sure it is complete. */
01698    ast_do_masquerade(chan);
01699 
01700    if (peer == rchan) {
01701       peer = chan;
01702    }
01703 
01704    /* parking space reserved, return code check unnecessary */
01705    park_call_full(chan, peer, args);
01706 
01707    return 0;
01708 }
01709 
01710 int ast_masq_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
01711 {
01712    int res;
01713    char *parse;
01714    const char *app_data;
01715    struct ast_exten *exten;
01716    struct park_app_args app_args;
01717    struct ast_park_call_args args = {
01718       .timeout = timeout,
01719       .extout = extout,
01720    };
01721 
01722    if (parker) {
01723       args.orig_chan_name = ast_strdupa(ast_channel_name(parker));
01724    }
01725    if (!park_exten || !park_context) {
01726       return masq_park_call(park_me, parker, &args);
01727    }
01728 
01729    /*
01730     * Determiine if the specified park extension has an exclusive
01731     * parking lot to use.
01732     */
01733    if (parker && parker != park_me) {
01734       ast_autoservice_start(park_me);
01735    }
01736    exten = get_parking_exten(park_exten, parker, park_context);
01737    if (exten) {
01738       app_data = ast_get_extension_app_data(exten);
01739       if (!app_data) {
01740          app_data = "";
01741       }
01742       parse = ast_strdupa(app_data);
01743       AST_STANDARD_APP_ARGS(app_args, parse);
01744    
01745       if (!ast_strlen_zero(app_args.pl_name)) {
01746          /* Find the specified exclusive parking lot */
01747          args.parkinglot = find_parkinglot(app_args.pl_name);
01748          if (!args.parkinglot && parkeddynamic) {
01749             args.parkinglot = create_dynamic_parkinglot(app_args.pl_name, park_me);
01750          }
01751       }
01752    }
01753    if (parker && parker != park_me) {
01754       ast_autoservice_stop(park_me);
01755    }
01756 
01757    res = masq_park_call(park_me, parker, &args);
01758    if (args.parkinglot) {
01759       parkinglot_unref(args.parkinglot);
01760    }
01761    return res;
01762 }
01763 
01764 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
01765 {
01766    struct ast_park_call_args args = {
01767       .timeout = timeout,
01768       .extout = extout,
01769    };
01770 
01771    if (peer) {
01772       args.orig_chan_name = ast_strdupa(ast_channel_name(peer));
01773    }
01774    return masq_park_call(rchan, peer, &args);
01775 }
01776 
01777 static int finishup(struct ast_channel *chan)
01778 {
01779    ast_indicate(chan, AST_CONTROL_UNHOLD);
01780 
01781    return ast_autoservice_stop(chan);
01782 }
01783 
01784 /*!
01785  * \internal
01786  * \brief Builtin transfer park call helper.
01787  *
01788  * \param park_me Channel to be parked.
01789  * \param parker Channel parking the call.
01790  * \param park_exten Parking lot dialplan access ramp extension.
01791  *
01792  * \note Assumes park_me is on hold and in autoservice.
01793  *
01794  * \retval -1 on successful park.
01795  * \retval -1 on park_me hangup.
01796  * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
01797  */
01798 static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
01799 {
01800    char *parse;
01801    const char *app_data;
01802    const char *pl_name;
01803    struct ast_park_call_args args = { 0, };
01804    struct park_app_args app_args;
01805    int res;
01806 
01807    app_data = ast_get_extension_app_data(park_exten);
01808    if (!app_data) {
01809       app_data = "";
01810    }
01811    parse = ast_strdupa(app_data);
01812    AST_STANDARD_APP_ARGS(app_args, parse);
01813 
01814    /* Find the parking lot */
01815    if (!ast_strlen_zero(app_args.pl_name)) {
01816       pl_name = app_args.pl_name;
01817    } else {
01818       pl_name = findparkinglotname(parker);
01819    }
01820    if (ast_strlen_zero(pl_name)) {
01821       /* Parking lot is not specified, so use the default parking lot. */
01822       args.parkinglot = parkinglot_addref(default_parkinglot);
01823    } else {
01824       args.parkinglot = find_parkinglot(pl_name);
01825       if (!args.parkinglot && parkeddynamic) {
01826          args.parkinglot = create_dynamic_parkinglot(pl_name, park_me);
01827       }
01828    }
01829 
01830    if (args.parkinglot) {
01831       /* Park the call */
01832       res = finishup(park_me);
01833       if (res) {
01834          /* park_me hungup on us. */
01835          parkinglot_unref(args.parkinglot);
01836          return -1;
01837       }
01838       res = masq_park_call(park_me, parker, &args);
01839       parkinglot_unref(args.parkinglot);
01840    } else {
01841       /* Parking failed because parking lot does not exist. */
01842       if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
01843          ast_stream_and_wait(parker, "pbx-parkingfailed", "");
01844       }
01845       finishup(park_me);
01846       res = -1;
01847    }
01848 
01849    return res ? AST_FEATURE_RETURN_SUCCESS : -1;
01850 }
01851 
01852 /*!
01853  * \brief set caller and callee according to the direction
01854  * \param caller, callee, peer, chan, sense
01855  *
01856  * Detect who triggered feature and set callee/caller variables accordingly
01857  */
01858 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
01859    struct ast_channel *peer, struct ast_channel *chan, int sense)
01860 {
01861    if (sense == FEATURE_SENSE_PEER) {
01862       *caller = peer;
01863       *callee = chan;
01864    } else {
01865       *callee = peer;
01866       *caller = chan;
01867    }
01868 }
01869 
01870 /*!
01871  * \brief support routing for one touch call parking
01872  * \param chan channel parking call
01873  * \param peer channel to be parked
01874  * \param config unsed
01875  * \param code unused
01876  * \param sense feature options
01877  * \param data unused
01878  *
01879  * \retval -1 on successful park.
01880  * \retval -1 on chan hangup.
01881  * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
01882  */
01883 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
01884 {
01885    struct ast_channel *parker;
01886    struct ast_channel *parkee;
01887    struct ast_park_call_args args = { 0, };
01888 
01889    /*
01890     * We used to set chan's exten and priority to "s" and 1 here,
01891     * but this generates (in some cases) an invalid extension, and
01892     * if "s" exists, could errantly cause execution of extensions
01893     * you don't expect.  It makes more sense to let nature take its
01894     * course when chan finishes, and let the pbx do its thing and
01895     * hang up when the park is over.
01896     */
01897 
01898    /* Answer if call is not up */
01899    if (chan->_state != AST_STATE_UP) {
01900       /*
01901        * XXX Why are we doing this?  Both of the channels should be up
01902        * since you cannot do DTMF features unless you are bridged.
01903        */
01904       if (ast_answer(chan)) {
01905          return -1;
01906       }
01907 
01908       /* Sleep to allow VoIP streams to settle down */
01909       if (ast_safe_sleep(chan, 1000)) {
01910          return -1;
01911       }
01912    }
01913 
01914    /* one direction used to call park_call.... */
01915    set_peers(&parker, &parkee, peer, chan, sense);
01916    return masq_park_call(parkee, parker, &args) ? AST_FEATURE_RETURN_SUCCESS : -1;
01917 }
01918 
01919 /*!
01920  * \internal
01921  * \brief Play file to specified channel.
01922  *
01923  * \param play_to Channel to play audiofile to.
01924  * \param other Channel to put in autoservice while playing file.
01925  * \param msg Descriptive name of message type being played.
01926  * \param audiofile Audio file to play.
01927  *
01928  * \retval 0 on success.
01929  * \retval -1 on error. (Couldn't play file, a channel hung up,...)
01930  */
01931 static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
01932 {
01933    /* Put other channel in autoservice. */
01934    if (ast_autoservice_start(other)) {
01935       return -1;
01936    }
01937    ast_autoservice_ignore(other, AST_FRAME_DTMF_BEGIN);
01938    ast_autoservice_ignore(other, AST_FRAME_DTMF_END);
01939    if (ast_stream_and_wait(play_to, audiofile, "")) {
01940       ast_log(LOG_WARNING, "Failed to play %s '%s'!\n", msg, audiofile);
01941       ast_autoservice_stop(other);
01942       return -1;
01943    }
01944    if (ast_autoservice_stop(other)) {
01945       return -1;
01946    }
01947    return 0;
01948 }
01949 
01950 /*!
01951  * \internal
01952  * \brief Play file to specified channels.
01953  *
01954  * \param left Channel on left to play file.
01955  * \param right Channel on right to play file.
01956  * \param which Play file on indicated channels: which < 0 play left, which == 0 play both, which > 0 play right
01957  * \param msg Descriptive name of message type being played.
01958  * \param audiofile Audio file to play to channels.
01959  *
01960  * \note Plays file to the indicated channels in turn so please
01961  * don't use this for very long messages.
01962  *
01963  * \retval 0 on success.
01964  * \retval -1 on error. (Couldn't play file, channel hung up,...)
01965  */
01966 static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
01967 {
01968    /* First play the file to the left channel if requested. */
01969    if (which <= 0 && play_message_on_chan(left, right, msg, audiofile)) {
01970       return -1;
01971    }
01972 
01973    /* Then play the file to the right channel if requested. */
01974    if (which >= 0 && play_message_on_chan(right, left, msg, audiofile)) {
01975       return -1;
01976    }
01977 
01978    return 0;
01979 }
01980 
01981 /*!
01982  * \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
01983  * other channel during the message, so please don't use this for very long messages
01984  */
01985 static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
01986 {
01987    return play_message_to_chans(caller_chan, callee_chan, 0, "automon message",
01988       audiofile);
01989 }
01990 
01991 /*!
01992  * \brief Monitor a channel by DTMF
01993  * \param chan channel requesting monitor
01994  * \param peer channel to be monitored
01995  * \param config
01996  * \param code
01997  * \param sense feature options
01998  *
01999  * \param data
02000  * Check monitor app enabled, setup channels, both caller/callee chans not null
02001  * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
02002  * \retval AST_FEATURE_RETURN_SUCCESS on success.
02003  * \retval -1 on error.
02004  */
02005 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
02006 {
02007    char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
02008    int x = 0;
02009    size_t len;
02010    struct ast_channel *caller_chan, *callee_chan;
02011    const char *automon_message_start = NULL;
02012    const char *automon_message_stop = NULL;
02013 
02014    if (!monitor_ok) {
02015       ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
02016       return -1;
02017    }
02018 
02019    if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
02020       monitor_ok = 0;
02021       ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
02022       return -1;
02023    }
02024 
02025    set_peers(&caller_chan, &callee_chan, peer, chan, sense);
02026    if (caller_chan) {   /* Find extra messages */
02027       automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
02028       automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
02029    }
02030 
02031    if (!ast_strlen_zero(courtesytone)) {  /* Play courtesy tone if configured */
02032       if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
02033          return -1;
02034       }
02035    }
02036    
02037    if (callee_chan->monitor) {
02038       ast_verb(4, "User hit '%s' to stop recording call.\n", code);
02039       if (!ast_strlen_zero(automon_message_stop)) {
02040          play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
02041       }
02042       callee_chan->monitor->stop(callee_chan, 1);
02043       return AST_FEATURE_RETURN_SUCCESS;
02044    }
02045 
02046    if (caller_chan && callee_chan) {
02047       const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
02048       const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
02049       const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
02050 
02051       if (!touch_format)
02052          touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
02053 
02054       if (!touch_monitor)
02055          touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
02056    
02057       if (!touch_monitor_prefix)
02058          touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
02059    
02060       if (touch_monitor) {
02061          len = strlen(touch_monitor) + 50;
02062          args = alloca(len);
02063          touch_filename = alloca(len);
02064          snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
02065          snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
02066       } else {
02067          caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
02068             caller_chan->caller.id.number.str, ast_channel_name(caller_chan)));
02069          callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
02070             callee_chan->caller.id.number.str, ast_channel_name(callee_chan)));
02071          len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
02072          args = alloca(len);
02073          touch_filename = alloca(len);
02074          snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
02075          snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
02076       }
02077 
02078       for(x = 0; x < strlen(args); x++) {
02079          if (args[x] == '/')
02080             args[x] = '-';
02081       }
02082       
02083       ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
02084 
02085       pbx_exec(callee_chan, monitor_app, args);
02086       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
02087       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
02088 
02089       if (!ast_strlen_zero(automon_message_start)) {  /* Play start message for both channels */
02090          play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
02091       }
02092    
02093       return AST_FEATURE_RETURN_SUCCESS;
02094    }
02095    
02096    ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");  
02097    return -1;
02098 }
02099 
02100 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
02101 {
02102    char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
02103    int x = 0;
02104    size_t len;
02105    struct ast_channel *caller_chan, *callee_chan;
02106    const char *mixmonitor_spy_type = "MixMonitor";
02107    int count = 0;
02108 
02109    if (!mixmonitor_ok) {
02110       ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
02111       return -1;
02112    }
02113 
02114    if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
02115       mixmonitor_ok = 0;
02116       ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
02117       return -1;
02118    }
02119 
02120    set_peers(&caller_chan, &callee_chan, peer, chan, sense);
02121 
02122    if (!ast_strlen_zero(courtesytone)) {
02123       if (ast_autoservice_start(callee_chan))
02124          return -1;
02125       ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
02126       if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
02127          ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
02128          ast_autoservice_stop(callee_chan);
02129          return -1;
02130       }
02131       if (ast_autoservice_stop(callee_chan))
02132          return -1;
02133    }
02134 
02135    ast_channel_lock(callee_chan);
02136    count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
02137    ast_channel_unlock(callee_chan);
02138 
02139    /* This means a mixmonitor is attached to the channel, running or not is unknown. */
02140    if (count > 0) {
02141       
02142       ast_verb(3, "User hit '%s' to stop recording call.\n", code);
02143 
02144       /* Make sure they are running */
02145       ast_channel_lock(callee_chan);
02146       count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
02147       ast_channel_unlock(callee_chan);
02148       if (count > 0) {
02149          if (!stopmixmonitor_ok) {
02150             ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
02151             return -1;
02152          }
02153          if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
02154             stopmixmonitor_ok = 0;
02155             ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
02156             return -1;
02157          } else {
02158             pbx_exec(callee_chan, stopmixmonitor_app, "");
02159             return AST_FEATURE_RETURN_SUCCESS;
02160          }
02161       }
02162       
02163       ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n"); 
02164    }        
02165 
02166    if (caller_chan && callee_chan) {
02167       const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
02168       const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
02169 
02170       if (!touch_format)
02171          touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
02172 
02173       if (!touch_monitor)
02174          touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
02175 
02176       if (touch_monitor) {
02177          len = strlen(touch_monitor) + 50;
02178          args = alloca(len);
02179          touch_filename = alloca(len);
02180          snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
02181          snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
02182       } else {
02183          caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
02184             caller_chan->caller.id.number.str, ast_channel_name(caller_chan)));
02185          callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
02186             callee_chan->caller.id.number.str, ast_channel_name(callee_chan)));
02187          len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
02188          args = alloca(len);
02189          touch_filename = alloca(len);
02190          snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
02191          snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
02192       }
02193 
02194       for( x = 0; x < strlen(args); x++) {
02195          if (args[x] == '/')
02196             args[x] = '-';
02197       }
02198 
02199       ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
02200 
02201       pbx_exec(callee_chan, mixmonitor_app, args);
02202       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
02203       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
02204       return AST_FEATURE_RETURN_SUCCESS;
02205    
02206    }
02207 
02208    ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
02209    return -1;
02210 
02211 }
02212 
02213 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
02214 {
02215    ast_verb(4, "User hit '%s' to disconnect call.\n", code);
02216    return AST_FEATURE_RETURN_HANGUP;
02217 }
02218 
02219 /*!
02220  * \brief Find the context for the transfer
02221  * \param transferer
02222  * \param transferee
02223  * 
02224  * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
02225  * \return a context string
02226  */
02227 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
02228 {
02229    const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
02230    if (ast_strlen_zero(s)) {
02231       s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
02232    }
02233    if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
02234       s = transferer->macrocontext;
02235    }
02236    if (ast_strlen_zero(s)) {
02237       s = transferer->context;
02238    }
02239    return s;  
02240 }
02241 
02242 /*!
02243  * \brief Blind transfer user to another extension
02244  * \param chan channel to be transfered
02245  * \param peer channel initiated blind transfer
02246  * \param config
02247  * \param code
02248  * \param data
02249  * \param sense  feature options
02250  * 
02251  * Place chan on hold, check if transferred to parkinglot extension,
02252  * otherwise check extension exists and transfer caller.
02253  * \retval AST_FEATURE_RETURN_SUCCESS.
02254  * \retval -1 on failure.
02255  */
02256 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
02257 {
02258    struct ast_channel *transferer;
02259    struct ast_channel *transferee;
02260    struct ast_exten *park_exten;
02261    const char *transferer_real_context;
02262    char xferto[256] = "";
02263    int res;
02264 
02265    ast_debug(1, "Executing Blind Transfer %s, %s (sense=%d) \n", ast_channel_name(chan), ast_channel_name(peer), sense);
02266    set_peers(&transferer, &transferee, peer, chan, sense);
02267    transferer_real_context = real_ctx(transferer, transferee);
02268 
02269    /* Start autoservice on transferee while we talk to the transferer */
02270    ast_autoservice_start(transferee);
02271    ast_indicate(transferee, AST_CONTROL_HOLD);
02272 
02273    /* Transfer */
02274    res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
02275    if (res < 0) {
02276       finishup(transferee);
02277       return -1; /* error ? */
02278    }
02279    if (res > 0) { /* If they've typed a digit already, handle it */
02280       xferto[0] = (char) res;
02281    }
02282 
02283    res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
02284    if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
02285       finishup(transferee);
02286       return -1;
02287    }
02288    if (res == 0) {
02289       if (xferto[0]) {
02290          ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
02291             xferto, transferer_real_context);
02292       } else {
02293          /* Does anyone care about this case? */
02294          ast_log(LOG_WARNING, "No digits dialed.\n");
02295       }
02296       ast_stream_and_wait(transferer, "pbx-invalid", "");
02297       finishup(transferee);
02298       return AST_FEATURE_RETURN_SUCCESS;
02299    }
02300 
02301    park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
02302    if (park_exten) {
02303       /* We are transfering the transferee to a parking lot. */
02304       return xfer_park_call_helper(transferee, transferer, park_exten);
02305    }
02306 
02307    /* Do blind transfer. */
02308    ast_verb(3, "Blind transferring %s to '%s' (context %s) priority 1\n",
02309       ast_channel_name(transferee), xferto, transferer_real_context);
02310    ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
02311    pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", ast_channel_name(transferee));
02312    pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", ast_channel_name(transferer));
02313    finishup(transferee);
02314    ast_channel_lock(transferer);
02315    if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
02316       transferer->cdr = ast_cdr_alloc();
02317       if (transferer->cdr) {
02318          ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
02319          ast_cdr_start(transferer->cdr);
02320       }
02321    }
02322    ast_channel_unlock(transferer);
02323    if (transferer->cdr) {
02324       struct ast_cdr *swap = transferer->cdr;
02325 
02326       ast_debug(1,
02327          "transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
02328          ast_channel_name(transferer), ast_channel_name(transferee), transferer->cdr->lastapp,
02329          transferer->cdr->lastdata, transferer->cdr->channel,
02330          transferer->cdr->dstchannel);
02331       ast_debug(1, "TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
02332          transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel,
02333          transferee->cdr->dstchannel);
02334       ast_debug(1, "transferer_real_context=%s; xferto=%s\n",
02335          transferer_real_context, xferto);
02336       /* swap cdrs-- it will save us some time & work */
02337       transferer->cdr = transferee->cdr;
02338       transferee->cdr = swap;
02339    }
02340    if (!transferee->pbx) {
02341       /* Doh!  Use our handy async_goto functions */
02342       ast_debug(1, "About to ast_async_goto %s.\n", ast_channel_name(transferee));
02343       if (ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
02344          ast_log(LOG_WARNING, "Async goto failed :-(\n");
02345       }
02346 
02347       /* The transferee is masqueraded and the original bridged channels can be hungup. */
02348       res = -1;
02349    } else {
02350       /* Set the transferee's new extension, since it exists, using transferer context */
02351       ast_debug(1, "About to explicit goto %s, it has a PBX.\n", ast_channel_name(transferee));
02352       ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
02353       set_c_e_p(transferee, transferer_real_context, xferto, 0);
02354 
02355       /*
02356        * Break the bridge.  The transferee needs to resume executing
02357        * dialplan at the xferto location.
02358        */
02359       res = AST_FEATURE_RETURN_SUCCESSBREAK;
02360    }
02361    check_goto_on_transfer(transferer);
02362    return res;
02363 }
02364 
02365 /*!
02366  * \brief make channels compatible
02367  * \param c
02368  * \param newchan
02369  * \retval 0 on success.
02370  * \retval -1 on failure.
02371  */
02372 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
02373 {
02374    if (ast_channel_make_compatible(c, newchan) < 0) {
02375       ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
02376          ast_channel_name(c), ast_channel_name(newchan));
02377       ast_hangup(newchan);
02378       return -1;
02379    }
02380    return 0;
02381 }
02382 
02383 /*!
02384  * \internal
02385  * \brief Builtin attended transfer failed cleanup.
02386  * \since 10.0
02387  *
02388  * \param transferee Party A in the transfer.
02389  * \param transferer Party B in the transfer.
02390  * \param connected_line Saved connected line info about party A.
02391  *
02392  * \note The connected_line data is freed.
02393  *
02394  * \return Nothing
02395  */
02396 static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
02397 {
02398    finishup(transferee);
02399 
02400    /*
02401     * Restore party B connected line info about party A.
02402     *
02403     * Party B was the caller to party C and is the last known mode
02404     * for party B.
02405     */
02406    if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
02407       ast_channel_update_connected_line(transferer, connected_line, NULL);
02408    }
02409    ast_party_connected_line_free(connected_line);
02410 }
02411 
02412 /*!
02413  * \brief Attended transfer
02414  * \param chan transfered user
02415  * \param peer person transfering call
02416  * \param config
02417  * \param code
02418  * \param sense feature options
02419  *
02420  * \param data
02421  * Get extension to transfer to, if you cannot generate channel (or find extension)
02422  * return to host channel. After called channel answered wait for hangup of transferer,
02423  * bridge call between transfer peer (taking them off hold) to attended transfer channel.
02424  *
02425  * \return -1 on failure
02426  */
02427 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
02428 {
02429    struct ast_channel *transferer;/* Party B */
02430    struct ast_channel *transferee;/* Party A */
02431    struct ast_exten *park_exten;
02432    const char *transferer_real_context;
02433    char xferto[256] = "";
02434    int res;
02435    int outstate=0;
02436    struct ast_channel *newchan;
02437    struct ast_channel *xferchan;
02438    struct ast_bridge_thread_obj *tobj;
02439    struct ast_bridge_config bconfig;
02440    int l;
02441    struct ast_party_connected_line connected_line;
02442    struct ast_datastore *features_datastore;
02443    struct ast_dial_features *dialfeatures = NULL;
02444    char *transferer_tech;
02445    char *transferer_name;
02446    char *transferer_name_orig;
02447    char *dash;
02448 
02449    ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", ast_channel_name(chan), ast_channel_name(peer), sense);
02450    set_peers(&transferer, &transferee, peer, chan, sense);
02451    transferer_real_context = real_ctx(transferer, transferee);
02452 
02453    /* Start autoservice on transferee while we talk to the transferer */
02454    ast_autoservice_start(transferee);
02455    ast_indicate(transferee, AST_CONTROL_HOLD);
02456 
02457    /* Transfer */
02458    res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
02459    if (res < 0) {
02460       finishup(transferee);
02461       return -1;
02462    }
02463    if (res > 0) { /* If they've typed a digit already, handle it */
02464       xferto[0] = (char) res;
02465    }
02466 
02467    /* this is specific of atxfer */
02468    res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
02469    if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
02470       finishup(transferee);
02471       return -1;
02472    }
02473    l = strlen(xferto);
02474    if (res == 0) {
02475       if (l) {
02476          ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
02477             xferto, transferer_real_context);
02478       } else {
02479          /* Does anyone care about this case? */
02480          ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
02481       }
02482       ast_stream_and_wait(transferer, "pbx-invalid", "");
02483       finishup(transferee);
02484       return AST_FEATURE_RETURN_SUCCESS;
02485    }
02486 
02487    park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
02488    if (park_exten) {
02489       /* We are transfering the transferee to a parking lot. */
02490       return xfer_park_call_helper(transferee, transferer, park_exten);
02491    }
02492 
02493    /* Append context to dialed transfer number. */
02494    snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
02495 
02496    /* If we are performing an attended transfer and we have two channels involved then
02497       copy sound file information to play upon attended transfer completion */
02498    if (transferee) {
02499       const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
02500       const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
02501 
02502       if (!ast_strlen_zero(chan1_attended_sound)) {
02503          pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
02504       }
02505       if (!ast_strlen_zero(chan2_attended_sound)) {
02506          pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
02507       }
02508    }
02509 
02510    /* Extract redial transferer information from the channel name. */
02511    transferer_name_orig = ast_strdupa(ast_channel_name(transferer));
02512    transferer_name = ast_strdupa(transferer_name_orig);
02513    transferer_tech = strsep(&transferer_name, "/");
02514    dash = strrchr(transferer_name, '-');
02515    if (dash) {
02516       /* Trim off channel name sequence/serial number. */
02517       *dash = '\0';
02518    }
02519 
02520    /* Stop autoservice so we can monitor all parties involved in the transfer. */
02521    if (ast_autoservice_stop(transferee) < 0) {
02522       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02523       return -1;
02524    }
02525 
02526    /* Save connected line info for party B about party A in case transfer fails. */
02527    ast_party_connected_line_init(&connected_line);
02528    ast_channel_lock(transferer);
02529    ast_party_connected_line_copy(&connected_line, &transferer->connected);
02530    ast_channel_unlock(transferer);
02531    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02532 
02533    /* Dial party C */
02534    newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
02535       transferee, "Local", transferer->nativeformats, xferto,
02536       atxfernoanswertimeout, &outstate, ast_channel_language(transferer));
02537    ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
02538 
02539    if (!ast_check_hangup(transferer)) {
02540       int hangup_dont = 0;
02541 
02542       /* Transferer (party B) is up */
02543       ast_debug(1, "Actually doing an attended transfer.\n");
02544 
02545       /* Start autoservice on transferee while the transferer deals with party C. */
02546       ast_autoservice_start(transferee);
02547 
02548       ast_indicate(transferer, -1);
02549       if (!newchan) {
02550          /* any reason besides user requested cancel and busy triggers the failed sound */
02551          switch (outstate) {
02552          case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
02553          case AST_CONTROL_BUSY:
02554          case AST_CONTROL_CONGESTION:
02555             if (ast_stream_and_wait(transferer, xfersound, "")) {
02556                ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02557             }
02558             break;
02559          default:
02560             if (ast_stream_and_wait(transferer, xferfailsound, "")) {
02561                ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
02562             }
02563             break;
02564          }
02565          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02566          return AST_FEATURE_RETURN_SUCCESS;
02567       }
02568 
02569       if (check_compat(transferer, newchan)) {
02570          if (ast_stream_and_wait(transferer, xferfailsound, "")) {
02571             ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
02572          }
02573          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02574          return AST_FEATURE_RETURN_SUCCESS;
02575       }
02576       memset(&bconfig,0,sizeof(struct ast_bridge_config));
02577       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
02578       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
02579 
02580       /* ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we don't
02581          want that to happen here because we're also in another bridge already
02582        */
02583       if (ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)) {
02584          hangup_dont = 1;
02585       }
02586       /* Let party B and party C talk as long as they want. */
02587       ast_bridge_call(transferer, newchan, &bconfig);
02588       if (hangup_dont) {
02589          ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
02590       }
02591 
02592       if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
02593          ast_hangup(newchan);
02594          if (ast_stream_and_wait(transferer, xfersound, "")) {
02595             ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02596          }
02597          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02598          return AST_FEATURE_RETURN_SUCCESS;
02599       }
02600 
02601       /* Transferer (party B) is confirmed hung up at this point. */
02602       if (check_compat(transferee, newchan)) {
02603          finishup(transferee);
02604          ast_party_connected_line_free(&connected_line);
02605          return -1;
02606       }
02607 
02608       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02609       if ((ast_autoservice_stop(transferee) < 0)
02610          || (ast_waitfordigit(transferee, 100) < 0)
02611          || (ast_waitfordigit(newchan, 100) < 0)
02612          || ast_check_hangup(transferee)
02613          || ast_check_hangup(newchan)) {
02614          ast_hangup(newchan);
02615          ast_party_connected_line_free(&connected_line);
02616          return -1;
02617       }
02618    } else if (!ast_check_hangup(transferee)) {
02619       /* Transferer (party B) has hung up at this point.  Doing blonde transfer. */
02620       ast_debug(1, "Actually doing a blonde transfer.\n");
02621 
02622       if (!newchan && !atxferdropcall) {
02623          /* Party C is not available, try to call party B back. */
02624          unsigned int tries = 0;
02625 
02626          if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
02627             ast_log(LOG_WARNING,
02628                "Transferer channel name: '%s' cannot be used for callback.\n",
02629                transferer_name_orig);
02630             ast_indicate(transferee, AST_CONTROL_UNHOLD);
02631             ast_party_connected_line_free(&connected_line);
02632             return -1;
02633          }
02634 
02635          tries = 0;
02636          for (;;) {
02637             /* Try to get party B back. */
02638             ast_debug(1, "We're trying to callback %s/%s\n",
02639                transferer_tech, transferer_name);
02640             newchan = feature_request_and_dial(transferer, transferer_name_orig,
02641                transferee, transferee, transferer_tech,
02642                transferee->nativeformats, transferer_name,
02643                atxfernoanswertimeout, &outstate, ast_channel_language(transferer));
02644             ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
02645                !!newchan, outstate);
02646             if (newchan || ast_check_hangup(transferee)) {
02647                break;
02648             }
02649 
02650             ++tries;
02651             if (atxfercallbackretries <= tries) {
02652                /* No more callback tries remaining. */
02653                break;
02654             }
02655 
02656             if (atxferloopdelay) {
02657                /* Transfer failed, sleeping */
02658                ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
02659                   atxferloopdelay);
02660                ast_safe_sleep(transferee, atxferloopdelay);
02661                if (ast_check_hangup(transferee)) {
02662                   ast_party_connected_line_free(&connected_line);
02663                   return -1;
02664                }
02665             }
02666 
02667             /* Retry dialing party C. */
02668             ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
02669             newchan = feature_request_and_dial(transferer, transferer_name_orig,
02670                transferer, transferee, "Local",
02671                transferee->nativeformats, xferto,
02672                atxfernoanswertimeout, &outstate, ast_channel_language(transferer));
02673             ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
02674                !!newchan, outstate);
02675             if (newchan || ast_check_hangup(transferee)) {
02676                break;
02677             }
02678          }
02679       }
02680       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02681       if (!newchan) {
02682          /* No party C or could not callback party B. */
02683          ast_party_connected_line_free(&connected_line);
02684          return -1;
02685       }
02686 
02687       /* newchan is up, we should prepare transferee and bridge them */
02688       if (ast_check_hangup(newchan)) {
02689          ast_hangup(newchan);
02690          ast_party_connected_line_free(&connected_line);
02691          return -1;
02692       }
02693       if (check_compat(transferee, newchan)) {
02694          ast_party_connected_line_free(&connected_line);
02695          return -1;
02696       }
02697    } else {
02698       /*
02699        * Both the transferer and transferee have hungup.  If newchan
02700        * is up, hang it up as it has no one to talk to.
02701        */
02702       ast_debug(1, "Everyone is hungup.\n");
02703       if (newchan) {
02704          ast_hangup(newchan);
02705       }
02706       ast_party_connected_line_free(&connected_line);
02707       return -1;
02708    }
02709 
02710    /* Initiate the channel transfer of party A to party C (or recalled party B). */
02711    ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
02712 
02713    xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", ast_channel_linkedid(transferee), 0, "Transfered/%s", ast_channel_name(transferee));
02714    if (!xferchan) {
02715       ast_hangup(newchan);
02716       ast_party_connected_line_free(&connected_line);
02717       return -1;
02718    }
02719 
02720    /* Give party A a momentary ringback tone during transfer. */
02721    xferchan->visible_indication = AST_CONTROL_RINGING;
02722 
02723    /* Make formats okay */
02724    xferchan->readformat = transferee->readformat;
02725    xferchan->writeformat = transferee->writeformat;
02726 
02727    ast_channel_masquerade(xferchan, transferee);
02728    ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
02729    xferchan->_state = AST_STATE_UP;
02730    ast_clear_flag(xferchan, AST_FLAGS_ALL);
02731 
02732    /* Do the masquerade manually to make sure that is is completed. */
02733    ast_do_masquerade(xferchan);
02734 
02735    newchan->_state = AST_STATE_UP;
02736    ast_clear_flag(newchan, AST_FLAGS_ALL);
02737    tobj = ast_calloc(1, sizeof(*tobj));
02738    if (!tobj) {
02739       ast_hangup(xferchan);
02740       ast_hangup(newchan);
02741       ast_party_connected_line_free(&connected_line);
02742       return -1;
02743    }
02744 
02745    ast_channel_lock(newchan);
02746    if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
02747       dialfeatures = features_datastore->data;
02748    }
02749    ast_channel_unlock(newchan);
02750 
02751    if (dialfeatures) {
02752       /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
02753          I don't currently understand, the abilities of newchan seem to be stored on the caller side */
02754       ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
02755       dialfeatures = NULL;
02756    }
02757 
02758    ast_channel_lock(xferchan);
02759    if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
02760       dialfeatures = features_datastore->data;
02761    }
02762    ast_channel_unlock(xferchan);
02763 
02764    if (dialfeatures) {
02765       ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
02766    }
02767 
02768    tobj->chan = newchan;
02769    tobj->peer = xferchan;
02770    tobj->bconfig = *config;
02771 
02772    if (tobj->bconfig.end_bridge_callback_data_fixup) {
02773       tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
02774    }
02775 
02776    /*
02777     * xferchan is transferee, and newchan is the transfer target
02778     * So...in a transfer, who is the caller and who is the callee?
02779     *
02780     * When the call is originally made, it is clear who is caller and callee.
02781     * When a transfer occurs, it is my humble opinion that the transferee becomes
02782     * the caller, and the transfer target is the callee.
02783     *
02784     * The problem is that these macros were set with the intention of the original
02785     * caller and callee taking those roles.  A transfer can totally mess things up,
02786     * to be technical.  What sucks even more is that you can't effectively change
02787     * the macros in the dialplan during the call from the transferer to the transfer
02788     * target because the transferee is stuck with whatever role he originally had.
02789     *
02790     * I think the answer here is just to make sure that it is well documented that
02791     * during a transfer, the transferee is the "caller" and the transfer target
02792     * is the "callee."
02793     *
02794     * This means that if party B calls party A, and party B transfers party A to
02795     * party C, then A has switched roles for the call.  Now party A will have the
02796     * caller macro called on his channel instead of the callee macro.
02797     *
02798     * Luckily, the method by which the party B to party C bridge is
02799     * launched above ensures that the transferee is the "chan" on
02800     * the bridge and the transfer target is the "peer," so my idea
02801     * for the roles post-transfer does not require extensive code
02802     * changes.
02803     */
02804 
02805    /* Transfer party C connected line to party A */
02806    ast_channel_lock(transferer);
02807    /*
02808     * Due to a limitation regarding when callerID is set on a Local channel,
02809     * we use the transferer's connected line information here.
02810     */
02811    ast_party_connected_line_copy(&connected_line, &transferer->connected);
02812    ast_channel_unlock(transferer);
02813    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02814    if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
02815       ast_channel_update_connected_line(xferchan, &connected_line, NULL);
02816    }
02817 
02818    /* Transfer party A connected line to party C */
02819    ast_channel_lock(xferchan);
02820    ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
02821    ast_channel_unlock(xferchan);
02822    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02823    if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
02824       ast_channel_update_connected_line(newchan, &connected_line, NULL);
02825    }
02826 
02827    if (ast_stream_and_wait(newchan, xfersound, ""))
02828       ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02829    bridge_call_thread_launch(tobj);
02830 
02831    ast_party_connected_line_free(&connected_line);
02832    return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
02833 }
02834 
02835 /* add atxfer and automon as undefined so you can only use em if you configure them */
02836 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
02837 
02838 AST_RWLOCK_DEFINE_STATIC(features_lock);
02839 
02840 static struct ast_call_feature builtin_features[] = {
02841    { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02842    { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02843    { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02844    { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02845    { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02846    { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02847 };
02848 
02849 
02850 static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
02851 
02852 /*! \brief register new feature into feature_list*/
02853 void ast_register_feature(struct ast_call_feature *feature)
02854 {
02855    if (!feature) {
02856       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
02857       return;
02858    }
02859   
02860    AST_RWLIST_WRLOCK(&feature_list);
02861    AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
02862    AST_RWLIST_UNLOCK(&feature_list);
02863 
02864    ast_verb(2, "Registered Feature '%s'\n",feature->sname);
02865 }
02866 
02867 /*! 
02868  * \brief Add new feature group
02869  * \param fgname feature group name.
02870  *
02871  * Add new feature group to the feature group list insert at head of list.
02872  * \note This function MUST be called while feature_groups is locked.
02873  */
02874 static struct feature_group *register_group(const char *fgname)
02875 {
02876    struct feature_group *fg;
02877 
02878    if (!fgname) {
02879       ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
02880       return NULL;
02881    }
02882 
02883    if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
02884       return NULL;
02885    }
02886 
02887    ast_string_field_set(fg, gname, fgname);
02888 
02889    AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
02890 
02891    ast_verb(2, "Registered group '%s'\n", fg->gname);
02892 
02893    return fg;
02894 }
02895 
02896 /*! 
02897  * \brief Add feature to group
02898  * \param fg feature group
02899  * \param exten
02900  * \param feature feature to add.
02901  *
02902  * Check fg and feature specified, add feature to list
02903  * \note This function MUST be called while feature_groups is locked. 
02904  */
02905 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
02906 {
02907    struct feature_group_exten *fge;
02908 
02909    if (!fg) {
02910       ast_log(LOG_NOTICE, "You didn't pass a group!\n");
02911       return;
02912    }
02913 
02914    if (!feature) {
02915       ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
02916       return;
02917    }
02918 
02919    if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
02920       return;
02921    }
02922 
02923    ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
02924 
02925    fge->feature = feature;
02926 
02927    AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
02928 
02929    ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
02930                feature->sname, fg->gname, fge->exten);
02931 }
02932 
02933 void ast_unregister_feature(struct ast_call_feature *feature)
02934 {
02935    if (!feature) {
02936       return;
02937    }
02938 
02939    AST_RWLIST_WRLOCK(&feature_list);
02940    AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
02941    AST_RWLIST_UNLOCK(&feature_list);
02942 
02943    ast_free(feature);
02944 }
02945 
02946 /*! \brief Remove all features in the list */
02947 static void ast_unregister_features(void)
02948 {
02949    struct ast_call_feature *feature;
02950 
02951    AST_RWLIST_WRLOCK(&feature_list);
02952    while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
02953       ast_free(feature);
02954    }
02955    AST_RWLIST_UNLOCK(&feature_list);
02956 }
02957 
02958 /*! \brief find a call feature by name */
02959 static struct ast_call_feature *find_dynamic_feature(const char *name)
02960 {
02961    struct ast_call_feature *tmp;
02962 
02963    AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
02964       if (!strcasecmp(tmp->sname, name)) {
02965          break;
02966       }
02967    }
02968 
02969    return tmp;
02970 }
02971 
02972 /*! \brief Remove all feature groups in the list */
02973 static void ast_unregister_groups(void)
02974 {
02975    struct feature_group *fg;
02976    struct feature_group_exten *fge;
02977 
02978    AST_RWLIST_WRLOCK(&feature_groups);
02979    while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
02980       while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
02981          ast_string_field_free_memory(fge);
02982          ast_free(fge);
02983       }
02984 
02985       ast_string_field_free_memory(fg);
02986       ast_free(fg);
02987    }
02988    AST_RWLIST_UNLOCK(&feature_groups);
02989 }
02990 
02991 /*! 
02992  * \brief Find a group by name 
02993  * \param name feature name
02994  * \retval feature group on success.
02995  * \retval NULL on failure.
02996  */
02997 static struct feature_group *find_group(const char *name)
02998 {
02999    struct feature_group *fg = NULL;
03000 
03001    AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
03002       if (!strcasecmp(fg->gname, name))
03003          break;
03004    }
03005 
03006    return fg;
03007 }
03008 
03009 void ast_rdlock_call_features(void)
03010 {
03011    ast_rwlock_rdlock(&features_lock);
03012 }
03013 
03014 void ast_unlock_call_features(void)
03015 {
03016    ast_rwlock_unlock(&features_lock);
03017 }
03018 
03019 struct ast_call_feature *ast_find_call_feature(const char *name)
03020 {
03021    int x;
03022    for (x = 0; x < FEATURES_COUNT; x++) {
03023       if (!strcasecmp(name, builtin_features[x].sname))
03024          return &builtin_features[x];
03025    }
03026 
03027    return find_dynamic_feature(name);
03028 }
03029 
03030 /*!
03031  * \brief exec an app by feature 
03032  * \param chan,peer,config,code,sense,data
03033  *
03034  * Find a feature, determine which channel activated
03035  * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
03036  * \retval -1 error.
03037  * \retval -2 when an application cannot be found.
03038  */
03039 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
03040 {
03041    struct ast_app *app;
03042    struct ast_call_feature *feature = data;
03043    struct ast_channel *work, *idle;
03044    int res;
03045 
03046    if (!feature) { /* shouldn't ever happen! */
03047       ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
03048       return -1; 
03049    }
03050 
03051    if (sense == FEATURE_SENSE_CHAN) {
03052       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
03053          return AST_FEATURE_RETURN_KEEPTRYING;
03054       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
03055          work = chan;
03056          idle = peer;
03057       } else {
03058          work = peer;
03059          idle = chan;
03060       }
03061    } else {
03062       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
03063          return AST_FEATURE_RETURN_KEEPTRYING;
03064       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
03065          work = peer;
03066          idle = chan;
03067       } else {
03068          work = chan;
03069          idle = peer;
03070       }
03071    }
03072 
03073    if (!(app = pbx_findapp(feature->app))) {
03074       ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
03075       return -2;
03076    }
03077 
03078    ast_autoservice_start(idle);
03079    ast_autoservice_ignore(idle, AST_FRAME_DTMF_END);
03080    
03081    if(work && idle) {
03082       pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", ast_channel_name(idle));
03083       pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", ast_channel_name(work));
03084       pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
03085       pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
03086    }
03087 
03088    if (!ast_strlen_zero(feature->moh_class))
03089       ast_moh_start(idle, feature->moh_class, NULL);
03090 
03091    res = pbx_exec(work, app, feature->app_args);
03092 
03093    if (!ast_strlen_zero(feature->moh_class))
03094       ast_moh_stop(idle);
03095 
03096    ast_autoservice_stop(idle);
03097 
03098    if (res) {
03099       return AST_FEATURE_RETURN_SUCCESSBREAK;
03100    }
03101    return AST_FEATURE_RETURN_SUCCESS;  /*! \todo XXX should probably return res */
03102 }
03103 
03104 static void unmap_features(void)
03105 {
03106    int x;
03107 
03108    ast_rwlock_wrlock(&features_lock);
03109    for (x = 0; x < FEATURES_COUNT; x++)
03110       strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
03111    ast_rwlock_unlock(&features_lock);
03112 }
03113 
03114 static int remap_feature(const char *name, const char *value)
03115 {
03116    int x, res = -1;
03117 
03118    ast_rwlock_wrlock(&features_lock);
03119    for (x = 0; x < FEATURES_COUNT; x++) {
03120       if (strcasecmp(builtin_features[x].sname, name))
03121          continue;
03122 
03123       ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
03124       res = 0;
03125       break;
03126    }
03127    ast_rwlock_unlock(&features_lock);
03128 
03129    return res;
03130 }
03131 
03132 /*!
03133  * \brief Helper function for feature_interpret and ast_feature_detect
03134  * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
03135  *
03136  * Lock features list, browse for code, unlock list
03137  * If a feature is found and the operation variable is set, that feature's
03138  * operation is executed.  The first feature found is copied to the feature parameter.
03139  * \retval res on success.
03140  * \retval -1 on failure.
03141  */
03142 static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
03143    struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
03144    struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
03145 {
03146    int x;
03147    struct feature_group *fg = NULL;
03148    struct feature_group_exten *fge;
03149    struct ast_call_feature *tmpfeature;
03150    char *tmp, *tok;
03151    int res = AST_FEATURE_RETURN_PASSDIGITS;
03152    int feature_detected = 0;
03153 
03154    if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
03155       return -1; /* can not run feature operation */
03156    }
03157 
03158    ast_rwlock_rdlock(&features_lock);
03159    for (x = 0; x < FEATURES_COUNT; x++) {
03160       if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
03161           !ast_strlen_zero(builtin_features[x].exten)) {
03162          /* Feature is up for consideration */
03163          if (!strcmp(builtin_features[x].exten, code)) {
03164             ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
03165             if (operation == FEATURE_INTERPRET_CHECK) {
03166                res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
03167             } else if (operation == FEATURE_INTERPRET_DO) {
03168                res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
03169             }
03170             if (feature) {
03171                memcpy(feature, &builtin_features[x], sizeof(feature));
03172             }
03173             feature_detected = 1;
03174             break;
03175          } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
03176             if (res == AST_FEATURE_RETURN_PASSDIGITS) {
03177                res = AST_FEATURE_RETURN_STOREDIGITS;
03178             }
03179          }
03180       }
03181    }
03182    ast_rwlock_unlock(&features_lock);
03183 
03184    if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
03185       return res;
03186    }
03187 
03188    tmp = dynamic_features_buf;
03189 
03190    while ((tok = strsep(&tmp, "#"))) {
03191       AST_RWLIST_RDLOCK(&feature_groups);
03192 
03193       fg = find_group(tok);
03194 
03195       if (fg) {
03196          AST_LIST_TRAVERSE(&fg->features, fge, entry) {
03197             if (!strcmp(fge->exten, code)) {
03198                if (operation) {
03199                   res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
03200                }
03201                memcpy(feature, fge->feature, sizeof(feature));
03202                if (res != AST_FEATURE_RETURN_KEEPTRYING) {
03203                   AST_RWLIST_UNLOCK(&feature_groups);
03204                   break;
03205                }
03206                res = AST_FEATURE_RETURN_PASSDIGITS;
03207             } else if (!strncmp(fge->exten, code, strlen(code))) {
03208                res = AST_FEATURE_RETURN_STOREDIGITS;
03209             }
03210          }
03211          if (fge) {
03212             break;
03213          }
03214       }
03215 
03216       AST_RWLIST_UNLOCK(&feature_groups);
03217 
03218       AST_RWLIST_RDLOCK(&feature_list);
03219 
03220       if (!(tmpfeature = find_dynamic_feature(tok))) {
03221          AST_RWLIST_UNLOCK(&feature_list);
03222          continue;
03223       }
03224 
03225       /* Feature is up for consideration */
03226       if (!strcmp(tmpfeature->exten, code)) {
03227          ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
03228          if (operation == FEATURE_INTERPRET_CHECK) {
03229             res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
03230          } else if (operation == FEATURE_INTERPRET_DO) {
03231             res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
03232          }
03233          if (feature) {
03234             memcpy(feature, tmpfeature, sizeof(feature));
03235          }
03236          if (res != AST_FEATURE_RETURN_KEEPTRYING) {
03237             AST_RWLIST_UNLOCK(&feature_list);
03238             break;
03239          }
03240          res = AST_FEATURE_RETURN_PASSDIGITS;
03241       } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
03242          res = AST_FEATURE_RETURN_STOREDIGITS;
03243 
03244       AST_RWLIST_UNLOCK(&feature_list);
03245    }
03246 
03247    return res;
03248 }
03249 
03250 /*!
03251  * \brief Check the dynamic features
03252  * \param chan,peer,config,code,sense
03253  *
03254  * \retval res on success.
03255  * \retval -1 on failure.
03256  */
03257 static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense) {
03258 
03259    char dynamic_features_buf[128];
03260    const char *peer_dynamic_features, *chan_dynamic_features;
03261    struct ast_flags features;
03262    struct ast_call_feature feature;
03263    if (sense == FEATURE_SENSE_CHAN) {
03264       ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
03265    }
03266    else {
03267       ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
03268    }
03269 
03270    ast_channel_lock(peer);
03271    peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
03272    ast_channel_unlock(peer);
03273 
03274    ast_channel_lock(chan);
03275    chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
03276    ast_channel_unlock(chan);
03277 
03278    snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
03279 
03280    ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", ast_channel_name(chan), ast_channel_name(peer), code, sense, features.flags, dynamic_features_buf);
03281 
03282    return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, FEATURE_INTERPRET_DO, &feature);
03283 }
03284 
03285 
03286 int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
03287 
03288    return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature);
03289 }
03290 
03291 /*! \brief Check if a feature exists */
03292 static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code) {
03293    char *chan_dynamic_features;
03294    ast_channel_lock(chan);
03295    chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
03296    ast_channel_unlock(chan);
03297 
03298    return feature_interpret_helper(chan, NULL, NULL, code, 0, chan_dynamic_features, features, FEATURE_INTERPRET_CHECK, NULL);
03299 }
03300 
03301 static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config *config)
03302 {
03303    int x;
03304 
03305    ast_clear_flag(config, AST_FLAGS_ALL);
03306 
03307    ast_rwlock_rdlock(&features_lock);
03308    for (x = 0; x < FEATURES_COUNT; x++) {
03309       if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
03310          continue;
03311 
03312       if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
03313          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
03314 
03315       if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
03316          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
03317    }
03318    ast_rwlock_unlock(&features_lock);
03319 
03320    if (!(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
03321       const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
03322 
03323       if (dynamic_features) {
03324          char *tmp = ast_strdupa(dynamic_features);
03325          char *tok;
03326          struct ast_call_feature *feature;
03327 
03328          /* while we have a feature */
03329          while ((tok = strsep(&tmp, "#"))) {
03330             struct feature_group *fg;
03331 
03332             AST_RWLIST_RDLOCK(&feature_groups);
03333             AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
03334                struct feature_group_exten *fge;
03335 
03336                AST_LIST_TRAVERSE(&fg->features, fge, entry) {
03337                   if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLER)) {
03338                      ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
03339                   }
03340                   if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLEE)) {
03341                      ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
03342                   }
03343                }
03344             }
03345             AST_RWLIST_UNLOCK(&feature_groups);
03346 
03347             AST_RWLIST_RDLOCK(&feature_list);
03348             if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
03349                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
03350                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
03351                }
03352                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE)) {
03353                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
03354                }
03355             }
03356             AST_RWLIST_UNLOCK(&feature_list);
03357          }
03358       }
03359    }
03360 }
03361 
03362 /*!
03363  * \internal
03364  * \brief Get feature and dial.
03365  *
03366  * \param caller Channel to represent as the calling channel for the dialed channel.
03367  * \param caller_name Original caller channel name.
03368  * \param requestor Channel to say is requesting the dial (usually the caller).
03369  * \param transferee Channel that the dialed channel will be transferred to.
03370  * \param type Channel technology type to dial.
03371  * \param format Codec formats for dialed channel.
03372  * \param addr destination of the call
03373  * \param timeout Time limit for dialed channel to answer in ms. Must be greater than zero.
03374  * \param outstate Status of dialed channel if unsuccessful.
03375  * \param language Language of the caller.
03376  *
03377  * \note
03378  * outstate can be:
03379  * 0, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION,
03380  * AST_CONTROL_ANSWER, or AST_CONTROL_UNHOLD.  If
03381  * AST_CONTROL_UNHOLD then the caller channel cancelled the
03382  * transfer or the dialed channel did not answer before the
03383  * timeout.
03384  *
03385  * \details
03386  * Request channel, set channel variables, initiate call,
03387  * check if they want to disconnect, go into loop, check if timeout has elapsed,
03388  * check if person to be transfered hung up, check for answer break loop,
03389  * set cdr return channel.
03390  *
03391  * \retval Channel Connected channel for transfer.
03392  * \retval NULL on failure to get third party connected.
03393  *
03394  * \note This is similar to __ast_request_and_dial() in channel.c
03395  */
03396 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
03397    const char *caller_name, struct ast_channel *requestor,
03398    struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, const char *addr,
03399    int timeout, int *outstate, const char *language)
03400 {
03401    int state = 0;
03402    int cause = 0;
03403    int to;
03404    int caller_hungup;
03405    int transferee_hungup;
03406    struct ast_channel *chan;
03407    struct ast_channel *monitor_chans[3];
03408    struct ast_channel *active_channel;
03409    int res;
03410    int ready = 0;
03411    struct timeval started;
03412    int x, len = 0;
03413    char *disconnect_code = NULL, *dialed_code = NULL;
03414    struct ast_format_cap *tmp_cap;
03415    struct ast_format best_audio_fmt;
03416    struct ast_frame *f;
03417    AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
03418 
03419    tmp_cap = ast_format_cap_alloc_nolock();
03420    if (!tmp_cap) {
03421       if (outstate) {
03422          *outstate = 0;
03423       }
03424       return NULL;
03425    }
03426    ast_best_codec(cap, &best_audio_fmt);
03427    ast_format_cap_add(tmp_cap, &best_audio_fmt);
03428 
03429    caller_hungup = ast_check_hangup(caller);
03430 
03431    if (!(chan = ast_request(type, tmp_cap, requestor, addr, &cause))) {
03432       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, addr);
03433       switch (cause) {
03434       case AST_CAUSE_BUSY:
03435          state = AST_CONTROL_BUSY;
03436          break;
03437       case AST_CAUSE_CONGESTION:
03438          state = AST_CONTROL_CONGESTION;
03439          break;
03440       default:
03441          state = 0;
03442          break;
03443       }
03444       goto done;
03445    }
03446 
03447    ast_channel_language_set(chan, language);
03448    ast_channel_inherit_variables(caller, chan);
03449    pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
03450 
03451    ast_channel_lock(chan);
03452    ast_connected_line_copy_from_caller(&chan->connected, &requestor->caller);
03453    ast_channel_unlock(chan);
03454 
03455    if (ast_call(chan, addr, timeout)) {
03456       ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, addr);
03457       switch (chan->hangupcause) {
03458       case AST_CAUSE_BUSY:
03459          state = AST_CONTROL_BUSY;
03460          break;
03461       case AST_CAUSE_CONGESTION:
03462          state = AST_CONTROL_CONGESTION;
03463          break;
03464       default:
03465          state = 0;
03466          break;
03467       }
03468       goto done;
03469    }
03470 
03471    /* support dialing of the featuremap disconnect code while performing an attended tranfer */
03472    ast_rwlock_rdlock(&features_lock);
03473    for (x = 0; x < FEATURES_COUNT; x++) {
03474       if (strcasecmp(builtin_features[x].sname, "disconnect"))
03475          continue;
03476 
03477       disconnect_code = builtin_features[x].exten;
03478       len = strlen(disconnect_code) + 1;
03479       dialed_code = alloca(len);
03480       memset(dialed_code, 0, len);
03481       break;
03482    }
03483    ast_rwlock_unlock(&features_lock);
03484    x = 0;
03485    started = ast_tvnow();
03486    to = timeout;
03487    AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
03488 
03489    ast_poll_channel_add(caller, chan);
03490 
03491    transferee_hungup = 0;
03492    while (!ast_check_hangup(transferee) && (chan->_state != AST_STATE_UP)) {
03493       int num_chans = 0;
03494 
03495       monitor_chans[num_chans++] = transferee;
03496       monitor_chans[num_chans++] = chan;
03497       if (!caller_hungup) {
03498          if (ast_check_hangup(caller)) {
03499             caller_hungup = 1;
03500 
03501 #if defined(ATXFER_NULL_TECH)
03502             /* Change caller's name to ensure that it will remain unique. */
03503             set_new_chan_name(caller);
03504 
03505             /*
03506              * Get rid of caller's physical technology so it is free for
03507              * other calls.
03508              */
03509             set_kill_chan_tech(caller);
03510 #endif   /* defined(ATXFER_NULL_TECH) */
03511          } else {
03512             /* caller is not hungup so monitor it. */
03513             monitor_chans[num_chans++] = caller;
03514          }
03515       }
03516 
03517       /* see if the timeout has been violated */
03518       if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
03519          state = AST_CONTROL_UNHOLD;
03520          ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", ast_channel_name(chan));
03521          break; /*doh! timeout*/
03522       }
03523 
03524       active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
03525       if (!active_channel)
03526          continue;
03527 
03528       f = NULL;
03529       if (transferee == active_channel) {
03530          struct ast_frame *dup_f;
03531 
03532          f = ast_read(transferee);
03533          if (f == NULL) { /*doh! where'd he go?*/
03534             transferee_hungup = 1;
03535             state = 0;
03536             break;
03537          }
03538          if (ast_is_deferrable_frame(f)) {
03539             dup_f = ast_frisolate(f);
03540             if (dup_f) {
03541                if (dup_f == f) {
03542                   f = NULL;
03543                }
03544                AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
03545             }
03546          }
03547       } else if (chan == active_channel) {
03548          if (!ast_strlen_zero(ast_channel_call_forward(chan))) {
03549             state = 0;
03550             ast_autoservice_start(transferee);
03551             chan = ast_call_forward(caller, chan, NULL, tmp_cap, NULL, &state);
03552             ast_autoservice_stop(transferee);
03553             if (!chan) {
03554                break;
03555             }
03556             continue;
03557          }
03558          f = ast_read(chan);
03559          if (f == NULL) { /*doh! where'd he go?*/
03560             switch (chan->hangupcause) {
03561             case AST_CAUSE_BUSY:
03562                state = AST_CONTROL_BUSY;
03563                break;
03564             case AST_CAUSE_CONGESTION:
03565                state = AST_CONTROL_CONGESTION;
03566                break;
03567             default:
03568                state = 0;
03569                break;
03570             }
03571             break;
03572          }
03573 
03574          if (f->frametype == AST_FRAME_CONTROL) {
03575             if (f->subclass.integer == AST_CONTROL_RINGING) {
03576                ast_verb(3, "%s is ringing\n", ast_channel_name(chan));
03577                ast_indicate(caller, AST_CONTROL_RINGING);
03578             } else if (f->subclass.integer == AST_CONTROL_BUSY) {
03579                state = f->subclass.integer;
03580                ast_verb(3, "%s is busy\n", ast_channel_name(chan));
03581                ast_indicate(caller, AST_CONTROL_BUSY);
03582                ast_frfree(f);
03583                break;
03584             } else if (f->subclass.integer == AST_CONTROL_INCOMPLETE) {
03585                ast_verb(3, "%s dialed incomplete extension %s; ignoring\n", ast_channel_name(chan), chan->exten);
03586             } else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
03587                state = f->subclass.integer;
03588                ast_verb(3, "%s is congested\n", ast_channel_name(chan));
03589                ast_indicate(caller, AST_CONTROL_CONGESTION);
03590                ast_frfree(f);
03591                break;
03592             } else if (f->subclass.integer == AST_CONTROL_ANSWER) {
03593                /* This is what we are hoping for */
03594                state = f->subclass.integer;
03595                ast_frfree(f);
03596                ready=1;
03597                break;
03598             } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
03599                if (caller_hungup) {
03600                   struct ast_party_connected_line connected;
03601 
03602                   /* Just save it for the transfer. */
03603                   ast_party_connected_line_set_init(&connected, &caller->connected);
03604                   res = ast_connected_line_parse_data(f->data.ptr, f->datalen,
03605                      &connected);
03606                   if (!res) {
03607                      ast_channel_set_connected_line(caller, &connected, NULL);
03608                   }
03609                   ast_party_connected_line_free(&connected);
03610                } else {
03611                   ast_autoservice_start(transferee);
03612                   if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
03613                      ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE,
03614                         f->data.ptr, f->datalen);
03615                   }
03616                   ast_autoservice_stop(transferee);
03617                }
03618             } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
03619                if (!caller_hungup) {
03620                   ast_autoservice_start(transferee);
03621                   if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
03622                      ast_indicate_data(caller, AST_CONTROL_REDIRECTING,
03623                         f->data.ptr, f->datalen);
03624                   }
03625                   ast_autoservice_stop(transferee);
03626                }
03627             } else if (f->subclass.integer != -1
03628                && f->subclass.integer != AST_CONTROL_PROGRESS
03629                && f->subclass.integer != AST_CONTROL_PROCEEDING) {
03630                ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
03631             }
03632             /* else who cares */
03633          } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
03634             ast_write(caller, f);
03635          }
03636       } else if (caller == active_channel) {
03637          f = ast_read(caller);
03638          if (f) {
03639             if (f->frametype == AST_FRAME_DTMF) {
03640                dialed_code[x++] = f->subclass.integer;
03641                dialed_code[x] = '\0';
03642                if (strlen(dialed_code) == len) {
03643                   x = 0;
03644                } else if (x && strncmp(dialed_code, disconnect_code, x)) {
03645                   x = 0;
03646                   dialed_code[x] = '\0';
03647                }
03648                if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
03649                   /* Caller Canceled the call */
03650                   state = AST_CONTROL_UNHOLD;
03651                   ast_frfree(f);
03652                   break;
03653                }
03654             } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
03655                ast_write(chan, f);
03656             }
03657          }
03658       }
03659       if (f)
03660          ast_frfree(f);
03661    } /* end while */
03662 
03663    ast_poll_channel_del(caller, chan);
03664 
03665    /*
03666     * We need to free all the deferred frames, but we only need to
03667     * queue the deferred frames if no hangup was received.
03668     */
03669    ast_channel_lock(transferee);
03670    transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
03671    while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
03672       if (!transferee_hungup) {
03673          ast_queue_frame_head(transferee, f);
03674       }
03675       ast_frfree(f);
03676    }
03677    ast_channel_unlock(transferee);
03678 
03679 done:
03680    ast_indicate(caller, -1);
03681    if (chan && (ready || chan->_state == AST_STATE_UP)) {
03682       state = AST_CONTROL_ANSWER;
03683    } else if (chan) {
03684       ast_hangup(chan);
03685       chan = NULL;
03686    }
03687 
03688    tmp_cap = ast_format_cap_destroy(tmp_cap);
03689 
03690    if (outstate)
03691       *outstate = state;
03692 
03693    return chan;
03694 }
03695 
03696 void ast_channel_log(char *title, struct ast_channel *chan);
03697 
03698 void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */
03699 {
03700    ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long) chan);
03701    ast_log(LOG_NOTICE, "CHAN: name: %s;  appl: %s; data: %s; contxt: %s;  exten: %s; pri: %d;\n",
03702       ast_channel_name(chan), chan->appl, chan->data, chan->context, chan->exten, chan->priority);
03703    ast_log(LOG_NOTICE, "CHAN: acctcode: %s;  dialcontext: %s; amaflags: %x; maccontxt: %s;  macexten: %s; macpri: %d;\n",
03704       ast_channel_accountcode(chan), ast_channel_dialcontext(chan), chan->amaflags, chan->macrocontext, chan->macroexten, chan->macropriority);
03705    ast_log(LOG_NOTICE, "CHAN: masq: %p;  masqr: %p; _bridge: %p; uniqueID: %s; linkedID:%s\n",
03706       chan->masq, chan->masqr,
03707       chan->_bridge, ast_channel_uniqueid(chan), ast_channel_linkedid(chan));
03708    if (chan->masqr) {
03709       ast_log(LOG_NOTICE, "CHAN: masquerading as: %s;  cdr: %p;\n",
03710          ast_channel_name(chan->masqr), chan->masqr->cdr);
03711    }
03712    if (chan->_bridge) {
03713       ast_log(LOG_NOTICE, "CHAN: Bridged to %s\n", ast_channel_name(chan->_bridge));
03714    }
03715 
03716    ast_log(LOG_NOTICE, "===== done ====\n");
03717 }
03718 
03719 /*!
03720  * \brief return the first unlocked cdr in a possible chain
03721  */
03722 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
03723 {
03724    struct ast_cdr *cdr_orig = cdr;
03725    while (cdr) {
03726       if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
03727          return cdr;
03728       cdr = cdr->next;
03729    }
03730    return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
03731 }
03732 
03733 static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
03734 {
03735    const char *feature;
03736 
03737    if (ast_strlen_zero(features)) {
03738       return;
03739    }
03740 
03741    for (feature = features; *feature; feature++) {
03742       switch (*feature) {
03743       case 'T' :
03744       case 't' :
03745          ast_set_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
03746          break;
03747       case 'K' :
03748       case 'k' :
03749          ast_set_flag(&(config->features_caller), AST_FEATURE_PARKCALL);
03750          break;
03751       case 'H' :
03752       case 'h' :
03753          ast_set_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
03754          break;
03755       case 'W' :
03756       case 'w' :
03757          ast_set_flag(&(config->features_caller), AST_FEATURE_AUTOMON);
03758          break;
03759       default :
03760          ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
03761       }
03762    }
03763 }
03764 
03765 static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
03766 {
03767    struct ast_datastore *ds_callee_features = NULL, *ds_caller_features = NULL;
03768    struct ast_dial_features *callee_features = NULL, *caller_features = NULL;
03769 
03770    ast_channel_lock(caller);
03771    ds_caller_features = ast_channel_datastore_find(caller, &dial_features_info, NULL);
03772    ast_channel_unlock(caller);
03773    if (!ds_caller_features) {
03774       if (!(ds_caller_features = ast_datastore_alloc(&dial_features_info, NULL))) {
03775          ast_log(LOG_WARNING, "Unable to create channel datastore for caller features. Aborting!\n");
03776          return;
03777       }
03778       if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
03779          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
03780          ast_datastore_free(ds_caller_features);
03781          return;
03782       }
03783       ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
03784       caller_features->is_caller = 1;
03785       ast_copy_flags(&(caller_features->features_callee), &(config->features_callee), AST_FLAGS_ALL);
03786       ast_copy_flags(&(caller_features->features_caller), &(config->features_caller), AST_FLAGS_ALL);
03787       ds_caller_features->data = caller_features;
03788       ast_channel_lock(caller);
03789       ast_channel_datastore_add(caller, ds_caller_features);
03790       ast_channel_unlock(caller);
03791    } else {
03792       /* If we don't return here, then when we do a builtin_atxfer we will copy the disconnect
03793        * flags over from the atxfer to the caller */
03794       return;
03795    }
03796 
03797    ast_channel_lock(callee);
03798    ds_callee_features = ast_channel_datastore_find(callee, &dial_features_info, NULL);
03799    ast_channel_unlock(callee);
03800    if (!ds_callee_features) {
03801       if (!(ds_callee_features = ast_datastore_alloc(&dial_features_info, NULL))) {
03802          ast_log(LOG_WARNING, "Unable to create channel datastore for callee features. Aborting!\n");
03803          return;
03804       }
03805       if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
03806          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
03807          ast_datastore_free(ds_callee_features);
03808          return;
03809       }
03810       ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
03811       callee_features->is_caller = 0;
03812       ast_copy_flags(&(callee_features->features_callee), &(config->features_caller), AST_FLAGS_ALL);
03813       ast_copy_flags(&(callee_features->features_caller), &(config->features_callee), AST_FLAGS_ALL);
03814       ds_callee_features->data = callee_features;
03815       ast_channel_lock(callee);
03816       ast_channel_datastore_add(callee, ds_callee_features);
03817       ast_channel_unlock(callee);
03818    }
03819 
03820    return;
03821 }
03822 
03823 static void clear_dialed_interfaces(struct ast_channel *chan)
03824 {
03825    struct ast_datastore *di_datastore;
03826 
03827    ast_channel_lock(chan);
03828    if ((di_datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL))) {
03829       if (option_debug) {
03830          ast_log(LOG_DEBUG, "Removing dialed interfaces datastore on %s since we're bridging\n", ast_channel_name(chan));
03831       }
03832       if (!ast_channel_datastore_remove(chan, di_datastore)) {
03833          ast_datastore_free(di_datastore);
03834       }
03835    }
03836    ast_channel_unlock(chan);
03837 }
03838 
03839 /*!
03840  * \brief bridge the call and set CDR
03841  *
03842  * \param chan The bridge considers this channel the caller.
03843  * \param peer The bridge considers this channel the callee.
03844  * \param config Configuration for this bridge.
03845  *
03846  * Set start time, check for two channels,check if monitor on
03847  * check for feature activation, create new CDR
03848  * \retval res on success.
03849  * \retval -1 on failure to bridge.
03850  */
03851 int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
03852 {
03853    /* Copy voice back and forth between the two channels.  Give the peer
03854       the ability to transfer calls with '#<extension' syntax. */
03855    struct ast_frame *f;
03856    struct ast_channel *who;
03857    char chan_featurecode[FEATURE_MAX_LEN + 1]="";
03858    char peer_featurecode[FEATURE_MAX_LEN + 1]="";
03859    char orig_channame[AST_CHANNEL_NAME];
03860    char orig_peername[AST_CHANNEL_NAME];
03861    int res;
03862    int diff;
03863    int hasfeatures=0;
03864    int hadfeatures=0;
03865    int autoloopflag;
03866    int sendingdtmfdigit = 0;
03867    int we_disabled_peer_cdr = 0;
03868    struct ast_option_header *aoh;
03869    struct ast_cdr *bridge_cdr = NULL;
03870    struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */
03871    struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
03872    struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
03873    struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
03874    struct ast_silence_generator *silgen = NULL;
03875    const char *h_context;
03876 
03877    pbx_builtin_setvar_helper(chan, "BRIDGEPEER", ast_channel_name(peer));
03878    pbx_builtin_setvar_helper(peer, "BRIDGEPEER", ast_channel_name(chan));
03879 
03880    set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
03881    add_features_datastores(chan, peer, config);
03882 
03883    /* This is an interesting case.  One example is if a ringing channel gets redirected to
03884     * an extension that picks up a parked call.  This will make sure that the call taken
03885     * out of parking gets told that the channel it just got bridged to is still ringing. */
03886    if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
03887       ast_indicate(peer, AST_CONTROL_RINGING);
03888    }
03889 
03890    if (monitor_ok) {
03891       const char *monitor_exec;
03892       struct ast_channel *src = NULL;
03893       if (!monitor_app) {
03894          if (!(monitor_app = pbx_findapp("Monitor")))
03895             monitor_ok=0;
03896       }
03897       if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
03898          src = chan;
03899       else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
03900          src = peer;
03901       if (monitor_app && src) {
03902          char *tmp = ast_strdupa(monitor_exec);
03903          pbx_exec(src, monitor_app, tmp);
03904       }
03905    }
03906 
03907    set_config_flags(chan, config);
03908 
03909    /* Answer if need be */
03910    if (chan->_state != AST_STATE_UP) {
03911       if (ast_raw_answer(chan, 1)) {
03912          return -1;
03913       }
03914    }
03915 
03916 #ifdef FOR_DEBUG
03917    /* show the two channels and cdrs involved in the bridge for debug & devel purposes */
03918    ast_channel_log("Pre-bridge CHAN Channel info", chan);
03919    ast_channel_log("Pre-bridge PEER Channel info", peer);
03920 #endif
03921    /* two channels are being marked as linked here */
03922    ast_channel_set_linkgroup(chan,peer);
03923 
03924    /* copy the userfield from the B-leg to A-leg if applicable */
03925    if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
03926       char tmp[256];
03927 
03928       ast_channel_lock(chan);
03929       if (!ast_strlen_zero(chan->cdr->userfield)) {
03930          snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
03931          ast_cdr_appenduserfield(chan, tmp);
03932       } else {
03933          ast_cdr_setuserfield(chan, peer->cdr->userfield);
03934       }
03935       ast_channel_unlock(chan);
03936       /* Don't delete the CDR; just disable it. */
03937       ast_set_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED);
03938       we_disabled_peer_cdr = 1;
03939    }
03940    ast_copy_string(orig_channame,ast_channel_name(chan),sizeof(orig_channame));
03941    ast_copy_string(orig_peername,ast_channel_name(peer),sizeof(orig_peername));
03942 
03943    if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
03944       ast_channel_lock_both(chan, peer);
03945       if (chan_cdr) {
03946          ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
03947          ast_cdr_update(chan);
03948          bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr);
03949          /* rip any forked CDR's off of the chan_cdr and attach
03950           * them to the bridge_cdr instead */
03951          bridge_cdr->next = chan_cdr->next;
03952          chan_cdr->next = NULL;
03953          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
03954          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
03955          if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) {
03956             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
03957          }
03958          ast_cdr_setaccount(peer, ast_channel_accountcode(chan));
03959       } else {
03960          /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
03961          bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
03962          ast_copy_string(bridge_cdr->channel, ast_channel_name(chan), sizeof(bridge_cdr->channel));
03963          ast_copy_string(bridge_cdr->dstchannel, ast_channel_name(peer), sizeof(bridge_cdr->dstchannel));
03964          ast_copy_string(bridge_cdr->uniqueid, ast_channel_uniqueid(chan), sizeof(bridge_cdr->uniqueid));
03965          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
03966          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
03967          ast_cdr_setcid(bridge_cdr, chan);
03968          bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
03969          bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
03970          ast_copy_string(bridge_cdr->accountcode, ast_channel_accountcode(chan), sizeof(bridge_cdr->accountcode));
03971          /* Destination information */
03972          ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
03973          ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
03974          if (peer_cdr) {
03975             bridge_cdr->start = peer_cdr->start;
03976             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
03977          } else {
03978             ast_cdr_start(bridge_cdr);
03979          }
03980       }
03981       ast_channel_unlock(chan);
03982       ast_channel_unlock(peer);
03983 
03984       ast_debug(4, "bridge answer set, chan answer set\n");
03985       /* peer_cdr->answer will be set when a macro runs on the peer;
03986          in that case, the bridge answer will be delayed while the
03987          macro plays on the peer channel. The peer answered the call
03988          before the macro started playing. To the phone system,
03989          this is billable time for the call, even tho the caller
03990          hears nothing but ringing while the macro does its thing. */
03991 
03992       /* Another case where the peer cdr's time will be set, is when
03993          A self-parks by pickup up phone and dialing 700, then B
03994          picks up A by dialing its parking slot; there may be more 
03995          practical paths that get the same result, tho... in which
03996          case you get the previous answer time from the Park... which
03997          is before the bridge's start time, so I added in the 
03998          tvcmp check to the if below */
03999 
04000       if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) {
04001          ast_cdr_setanswer(bridge_cdr, peer_cdr->answer);
04002          ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition);
04003          if (chan_cdr) {
04004             ast_cdr_setanswer(chan_cdr, peer_cdr->answer);
04005             ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition);
04006          }
04007       } else {
04008          ast_cdr_answer(bridge_cdr);
04009          if (chan_cdr) {
04010             ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
04011          }
04012       }
04013       if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
04014          if (chan_cdr) {
04015             ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
04016          }
04017          if (peer_cdr) {
04018             ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
04019          }
04020       }
04021       /* the DIALED flag may be set if a dialed channel is transfered
04022        * and then bridged to another channel.  In order for the
04023        * bridge CDR to be written, the DIALED flag must not be
04024        * present. */
04025       ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED);
04026    }
04027    ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, peer);
04028 
04029    /* If we are bridging a call, stop worrying about forwarding loops. We presume that if
04030     * a call is being bridged, that the humans in charge know what they're doing. If they
04031     * don't, well, what can we do about that? */
04032    clear_dialed_interfaces(chan);
04033    clear_dialed_interfaces(peer);
04034 
04035    for (;;) {
04036       struct ast_channel *other; /* used later */
04037    
04038       res = ast_channel_bridge(chan, peer, config, &f, &who);
04039 
04040       if (ast_test_flag(chan, AST_FLAG_ZOMBIE)
04041          || ast_test_flag(peer, AST_FLAG_ZOMBIE)) {
04042          /* Zombies are present time to leave! */
04043          res = -1;
04044          if (f) {
04045             ast_frfree(f);
04046          }
04047          goto before_you_go;
04048       }
04049 
04050       /* When frame is not set, we are probably involved in a situation
04051          where we've timed out.
04052          When frame is set, we'll come this code twice; once for DTMF_BEGIN
04053          and also for DTMF_END. If we flow into the following 'if' for both, then 
04054          our wait times are cut in half, as both will subtract from the
04055          feature_timer. Not good!
04056       */
04057       if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
04058          /* Update feature timer for next pass */
04059          diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time);
04060          if (res == AST_BRIDGE_RETRY) {
04061             /* The feature fully timed out but has not been updated. Skip
04062              * the potential round error from the diff calculation and
04063              * explicitly set to expired. */
04064             config->feature_timer = -1;
04065          } else {
04066             config->feature_timer -= diff;
04067          }
04068 
04069          if (hasfeatures) {
04070             if (config->feature_timer <= 0) {
04071                /* Not *really* out of time, just out of time for
04072                   digits to come in for features. */
04073                ast_debug(1, "Timed out for feature!\n");
04074                if (!ast_strlen_zero(peer_featurecode)) {
04075                   ast_dtmf_stream(chan, peer, peer_featurecode, 0, f ? f->len : 0);
04076                   memset(peer_featurecode, 0, sizeof(peer_featurecode));
04077                }
04078                if (!ast_strlen_zero(chan_featurecode)) {
04079                   ast_dtmf_stream(peer, chan, chan_featurecode, 0, f ? f->len : 0);
04080                   memset(chan_featurecode, 0, sizeof(chan_featurecode));
04081                }
04082                if (f)
04083                   ast_frfree(f);
04084                hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
04085                if (!hasfeatures) {
04086                   /* No more digits expected - reset the timer */
04087                   config->feature_timer = 0;
04088                }
04089                hadfeatures = hasfeatures;
04090                /* Continue as we were */
04091                continue;
04092             } else if (!f) {
04093                /* The bridge returned without a frame and there is a feature in progress.
04094                 * However, we don't think the feature has quite yet timed out, so just
04095                 * go back into the bridge. */
04096                continue;
04097             }
04098          } else {
04099             if (config->feature_timer <=0) {
04100                /* We ran out of time */
04101                config->feature_timer = 0;
04102                who = chan;
04103                if (f)
04104                   ast_frfree(f);
04105                f = NULL;
04106                res = 0;
04107             }
04108          }
04109       }
04110       if (res < 0) {
04111          if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) {
04112             ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", ast_channel_name(chan), ast_channel_name(peer));
04113          }
04114          goto before_you_go;
04115       }
04116       
04117       if (!f || (f->frametype == AST_FRAME_CONTROL &&
04118             (f->subclass.integer == AST_CONTROL_HANGUP || f->subclass.integer == AST_CONTROL_BUSY ||
04119                f->subclass.integer == AST_CONTROL_CONGESTION))) {
04120          /*
04121           * If the bridge was broken for a hangup that isn't real,
04122           * then don't run the h extension, because the channel isn't
04123           * really hung up. This should really only happen with AST_SOFTHANGUP_ASYNCGOTO,
04124           * but it doesn't hurt to check AST_SOFTHANGUP_UNBRIDGE either.
04125           */
04126          ast_channel_lock(chan);
04127          if (chan->_softhangup & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE)) {
04128             ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
04129          }
04130          ast_channel_unlock(chan);
04131          res = -1;
04132          break;
04133       }
04134       /* many things should be sent to the 'other' channel */
04135       other = (who == chan) ? peer : chan;
04136       if (f->frametype == AST_FRAME_CONTROL) {
04137          switch (f->subclass.integer) {
04138          case AST_CONTROL_RINGING:
04139          case AST_CONTROL_FLASH:
04140          case AST_CONTROL_MCID:
04141          case -1:
04142             ast_indicate(other, f->subclass.integer);
04143             break;
04144          case AST_CONTROL_CONNECTED_LINE:
04145             if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
04146                break;
04147             }
04148             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
04149             break;
04150          case AST_CONTROL_REDIRECTING:
04151             if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
04152                break;
04153             }
04154             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
04155             break;
04156          case AST_CONTROL_AOC:
04157          case AST_CONTROL_HOLD:
04158          case AST_CONTROL_UNHOLD:
04159             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
04160             break;
04161          case AST_CONTROL_OPTION:
04162             aoh = f->data.ptr;
04163             /* Forward option Requests, but only ones we know are safe
04164              * These are ONLY sent by chan_iax2 and I'm not convinced that
04165              * they are useful. I haven't deleted them entirely because I
04166              * just am not sure of the ramifications of removing them. */
04167             if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
04168                   switch (ntohs(aoh->option)) {
04169                case AST_OPTION_TONE_VERIFY:
04170                case AST_OPTION_TDD:
04171                case AST_OPTION_RELAXDTMF:
04172                case AST_OPTION_AUDIO_MODE:
04173                case AST_OPTION_DIGIT_DETECT:
04174                case AST_OPTION_FAX_DETECT:
04175                   ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 
04176                      f->datalen - sizeof(struct ast_option_header), 0);
04177                }
04178             }
04179             break;
04180          }
04181       } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
04182          struct ast_flags *cfg;
04183          char dtmfcode[2] = { f->subclass.integer, };
04184          size_t featurelen;
04185 
04186          if (who == chan) {
04187             featurelen = strlen(chan_featurecode);
04188             cfg = &(config->features_caller);
04189          } else {
04190             featurelen = strlen(peer_featurecode);
04191             cfg = &(config->features_callee);
04192          }
04193          /* Take a peek if this (possibly) matches a feature. If not, just pass this
04194           * DTMF along untouched. If this is not the first digit of a multi-digit code
04195           * then we need to fall through and stream the characters if it matches */
04196          if (featurelen == 0
04197             && feature_check(chan, cfg, &dtmfcode[0]) == AST_FEATURE_RETURN_PASSDIGITS) {
04198             if (option_debug > 3) {
04199                ast_log(LOG_DEBUG, "Passing DTMF through, since it is not a feature code\n");
04200             }
04201             ast_write(other, f);
04202             sendingdtmfdigit = 1;
04203          } else {
04204             /* If ast_opt_transmit_silence is set, then we need to make sure we are
04205              * transmitting something while we hold on to the DTMF waiting for a
04206              * feature. */
04207             if (!silgen && ast_opt_transmit_silence) {
04208                silgen = ast_channel_start_silence_generator(other);
04209             }
04210             if (option_debug > 3) {
04211                ast_log(LOG_DEBUG, "Not passing DTMF through, since it may be a feature code\n");
04212             }
04213          }
04214       } else if (f->frametype == AST_FRAME_DTMF_END) {
04215          char *featurecode;
04216          int sense;
04217          unsigned int dtmfduration = f->len;
04218 
04219          hadfeatures = hasfeatures;
04220          /* This cannot overrun because the longest feature is one shorter than our buffer */
04221          if (who == chan) {
04222             sense = FEATURE_SENSE_CHAN;
04223             featurecode = chan_featurecode;
04224          } else  {
04225             sense = FEATURE_SENSE_PEER;
04226             featurecode = peer_featurecode;
04227          }
04228 
04229          if (sendingdtmfdigit == 1) {
04230             /* We let the BEGIN go through happily, so let's not bother with the END,
04231              * since we already know it's not something we bother with */
04232             ast_write(other, f);
04233             sendingdtmfdigit = 0;
04234          } else {
04235             /*! append the event to featurecode. we rely on the string being zero-filled, and
04236              * not overflowing it. 
04237              * \todo XXX how do we guarantee the latter ?
04238              */
04239             featurecode[strlen(featurecode)] = f->subclass.integer;
04240             /* Get rid of the frame before we start doing "stuff" with the channels */
04241             ast_frfree(f);
04242             f = NULL;
04243             if (silgen) {
04244                ast_channel_stop_silence_generator(other, silgen);
04245                silgen = NULL;
04246             }
04247             config->feature_timer = 0;
04248             res = feature_interpret(chan, peer, config, featurecode, sense);
04249             switch(res) {
04250             case AST_FEATURE_RETURN_PASSDIGITS:
04251                ast_dtmf_stream(other, who, featurecode, 0, dtmfduration);
04252                /* Fall through */
04253             case AST_FEATURE_RETURN_SUCCESS:
04254                memset(featurecode, 0, sizeof(chan_featurecode));
04255                break;
04256             }
04257             if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
04258                res = 0;
04259             } else {
04260                break;
04261             }
04262             hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
04263             if (hadfeatures && !hasfeatures) {
04264                /* Feature completed or timed out */
04265                config->feature_timer = 0;
04266             } else if (hasfeatures) {
04267                if (config->timelimit) {
04268                   /* No warning next time - we are waiting for feature code */
04269                   ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
04270                }
04271                config->feature_start_time = ast_tvnow();
04272                config->feature_timer = featuredigittimeout;
04273                ast_debug(1, "Set feature timer to %ld ms\n", config->feature_timer);
04274             }
04275          }
04276       }
04277       if (f)
04278          ast_frfree(f);
04279    }
04280    ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, peer);
04281 
04282 before_you_go:
04283    /* Just in case something weird happened and we didn't clean up the silence generator... */
04284    if (silgen) {
04285       ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen);
04286       silgen = NULL;
04287    }
04288 
04289    if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) {
04290       ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
04291       if (bridge_cdr) {
04292          ast_cdr_discard(bridge_cdr);
04293          /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */
04294       }
04295       return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */
04296    }
04297 
04298    if (config->end_bridge_callback) {
04299       config->end_bridge_callback(config->end_bridge_callback_data);
04300    }
04301 
04302    /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation 
04303     * if it were, then chan belongs to a different thread now, and might have been hung up long
04304      * ago.
04305     */
04306    if (ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) {
04307       h_context = NULL;
04308    } else if (ast_exists_extension(chan, chan->context, "h", 1,
04309       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
04310       h_context = chan->context;
04311    } else if (!ast_strlen_zero(chan->macrocontext)
04312       && ast_exists_extension(chan, chan->macrocontext, "h", 1,
04313          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
04314       h_context = chan->macrocontext;
04315    } else {
04316       h_context = NULL;
04317    }
04318    if (h_context) {
04319       struct ast_cdr *swapper = NULL;
04320       char savelastapp[AST_MAX_EXTENSION];
04321       char savelastdata[AST_MAX_EXTENSION];
04322       char save_context[AST_MAX_CONTEXT];
04323       char save_exten[AST_MAX_EXTENSION];
04324       int  save_prio;
04325       int  found = 0;   /* set if we find at least one match */
04326       int  spawn_error = 0;
04327 
04328       /*
04329        * Make sure that the channel is marked as hungup since we are
04330        * going to run the "h" exten on it.
04331        */
04332       ast_softhangup(chan, AST_SOFTHANGUP_APPUNLOAD);
04333 
04334       autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
04335       ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
04336       if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
04337          ast_cdr_end(bridge_cdr);
04338       }
04339 
04340       /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
04341          dialplan code operate on it */
04342       ast_channel_lock(chan);
04343       if (bridge_cdr) {
04344          swapper = chan->cdr;
04345          ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
04346          ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
04347          chan->cdr = bridge_cdr;
04348       }
04349       ast_copy_string(save_context, chan->context, sizeof(save_context));
04350       ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
04351       save_prio = chan->priority;
04352       if (h_context != chan->context) {
04353          ast_copy_string(chan->context, h_context, sizeof(chan->context));
04354       }
04355       ast_copy_string(chan->exten, "h", sizeof(chan->exten));
04356       chan->priority = 1;
04357       ast_channel_unlock(chan);
04358 
04359       while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten,
04360          chan->priority,
04361          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
04362          &found, 1)) == 0) {
04363          chan->priority++;
04364       }
04365       if (found && spawn_error) {
04366          /* Something bad happened, or a hangup has been requested. */
04367          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, ast_channel_name(chan));
04368          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, ast_channel_name(chan));
04369       }
04370 
04371       /* swap it back */
04372       ast_channel_lock(chan);
04373       ast_copy_string(chan->context, save_context, sizeof(chan->context));
04374       ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
04375       chan->priority = save_prio;
04376       if (bridge_cdr) {
04377          if (chan->cdr == bridge_cdr) {
04378             chan->cdr = swapper;
04379          } else {
04380             bridge_cdr = NULL;
04381          }
04382       }
04383       /* An "h" exten has been run, so indicate that one has been run. */
04384       ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
04385       ast_channel_unlock(chan);
04386 
04387       /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
04388       if (bridge_cdr) {
04389          ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
04390          ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
04391       }
04392       ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
04393    }
04394    
04395    /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
04396    new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
04397    if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))
04398       ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
04399 
04400    /* we can post the bridge CDR at this point */
04401    if (bridge_cdr) {
04402       ast_cdr_end(bridge_cdr);
04403       ast_cdr_detach(bridge_cdr);
04404    }
04405    
04406    /* do a specialized reset on the beginning channel
04407       CDR's, if they still exist, so as not to mess up
04408       issues in future bridges;
04409       
04410       Here are the rules of the game:
04411       1. The chan and peer channel pointers will not change
04412          during the life of the bridge.
04413       2. But, in transfers, the channel names will change.
04414          between the time the bridge is started, and the
04415          time the channel ends. 
04416          Usually, when a channel changes names, it will
04417          also change CDR pointers.
04418       3. Usually, only one of the two channels (chan or peer)
04419          will change names.
04420       4. Usually, if a channel changes names during a bridge,
04421          it is because of a transfer. Usually, in these situations,
04422          it is normal to see 2 bridges running simultaneously, and
04423          it is not unusual to see the two channels that change
04424          swapped between bridges.
04425       5. After a bridge occurs, we have 2 or 3 channels' CDRs
04426          to attend to; if the chan or peer changed names,
04427          we have the before and after attached CDR's.
04428    */
04429 
04430    if (new_chan_cdr) {
04431       struct ast_channel *chan_ptr = NULL;
04432 
04433       if (strcasecmp(orig_channame, ast_channel_name(chan)) != 0) { 
04434          /* old channel */
04435          if ((chan_ptr = ast_channel_get_by_name(orig_channame))) {
04436             ast_channel_lock(chan_ptr);
04437             if (!ast_bridged_channel(chan_ptr)) {
04438                struct ast_cdr *cur;
04439                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
04440                   if (cur == chan_cdr) {
04441                      break;
04442                   }
04443                }
04444                if (cur) {
04445                   ast_cdr_specialized_reset(chan_cdr, 0);
04446                }
04447             }
04448             ast_channel_unlock(chan_ptr);
04449             chan_ptr = ast_channel_unref(chan_ptr);
04450          }
04451          /* new channel */
04452          ast_cdr_specialized_reset(new_chan_cdr, 0);
04453       } else {
04454          ast_cdr_specialized_reset(chan->cdr, 0); /* nothing changed, reset the chan cdr  */
04455       }
04456    }
04457 
04458    {
04459       struct ast_channel *chan_ptr = NULL;
04460       new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
04461       if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED))
04462          ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
04463       if (strcasecmp(orig_peername, ast_channel_name(peer)) != 0) { 
04464          /* old channel */
04465          if ((chan_ptr = ast_channel_get_by_name(orig_peername))) {
04466             ast_channel_lock(chan_ptr);
04467             if (!ast_bridged_channel(chan_ptr)) {
04468                struct ast_cdr *cur;
04469                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
04470                   if (cur == peer_cdr) {
04471                      break;
04472                   }
04473                }
04474                if (cur) {
04475                   ast_cdr_specialized_reset(peer_cdr, 0);
04476                }
04477             }
04478             ast_channel_unlock(chan_ptr);
04479             chan_ptr = ast_channel_unref(chan_ptr);
04480          }
04481          /* new channel */
04482          if (new_peer_cdr) {
04483             ast_cdr_specialized_reset(new_peer_cdr, 0);
04484          }
04485       } else {
04486          if (we_disabled_peer_cdr) {
04487             ast_clear_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED);
04488          }
04489          ast_cdr_specialized_reset(peer->cdr, 0); /* nothing changed, reset the peer cdr  */
04490       }
04491    }
04492    
04493    return res;
04494 }
04495 
04496 /*! \brief Output parking event to manager */
04497 static void post_manager_event(const char *s, struct parkeduser *pu)
04498 {
04499    manager_event(EVENT_FLAG_CALL, s,
04500       "Exten: %s\r\n"
04501       "Channel: %s\r\n"
04502       "Parkinglot: %s\r\n"
04503       "CallerIDNum: %s\r\n"
04504       "CallerIDName: %s\r\n"
04505       "ConnectedLineNum: %s\r\n"
04506       "ConnectedLineName: %s\r\n"
04507       "UniqueID: %s\r\n",
04508       pu->parkingexten, 
04509       ast_channel_name(pu->chan),
04510       pu->parkinglot->name,
04511       S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
04512       S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
04513       S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
04514       S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
04515       ast_channel_uniqueid(pu->chan)
04516       );
04517 }
04518 
04519 static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
04520 {
04521    int i = 0;
04522    enum {
04523       OPT_CALLEE_REDIRECT   = 't',
04524       OPT_CALLER_REDIRECT   = 'T',
04525       OPT_CALLEE_AUTOMON    = 'w',
04526       OPT_CALLER_AUTOMON    = 'W',
04527       OPT_CALLEE_DISCONNECT = 'h',
04528       OPT_CALLER_DISCONNECT = 'H',
04529       OPT_CALLEE_PARKCALL   = 'k',
04530       OPT_CALLER_PARKCALL   = 'K',
04531    };
04532 
04533    memset(options, 0, len);
04534    if (ast_test_flag(features_caller, AST_FEATURE_REDIRECT) && i < len) {
04535       options[i++] = OPT_CALLER_REDIRECT;
04536    }
04537    if (ast_test_flag(features_caller, AST_FEATURE_AUTOMON) && i < len) {
04538       options[i++] = OPT_CALLER_AUTOMON;
04539    }
04540    if (ast_test_flag(features_caller, AST_FEATURE_DISCONNECT) && i < len) {
04541       options[i++] = OPT_CALLER_DISCONNECT;
04542    }
04543    if (ast_test_flag(features_caller, AST_FEATURE_PARKCALL) && i < len) {
04544       options[i++] = OPT_CALLER_PARKCALL;
04545    }
04546 
04547    if (ast_test_flag(features_callee, AST_FEATURE_REDIRECT) && i < len) {
04548       options[i++] = OPT_CALLEE_REDIRECT;
04549    }
04550    if (ast_test_flag(features_callee, AST_FEATURE_AUTOMON) && i < len) {
04551       options[i++] = OPT_CALLEE_AUTOMON;
04552    }
04553    if (ast_test_flag(features_callee, AST_FEATURE_DISCONNECT) && i < len) {
04554       options[i++] = OPT_CALLEE_DISCONNECT;
04555    }
04556    if (ast_test_flag(features_callee, AST_FEATURE_PARKCALL) && i < len) {
04557       options[i++] = OPT_CALLEE_PARKCALL;
04558    }
04559 
04560    return options;
04561 }
04562 
04563 /*!
04564  * \internal
04565  * \brief Run management on a parked call.
04566  *
04567  * \note The parkinglot parkings list is locked on entry.
04568  *
04569  * \retval TRUE if the parking completed.
04570  */
04571 static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
04572 {
04573    struct ast_channel *chan = pu->chan;   /* shorthand */
04574    int tms;        /* timeout for this item */
04575    int x;          /* fd index in channel */
04576    int parking_complete = 0;
04577 
04578    tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
04579    if (tms > pu->parkingtime) {
04580       /*
04581        * Call has been parked too long.
04582        * Stop entertaining the caller.
04583        */
04584       switch (pu->hold_method) {
04585       case AST_CONTROL_HOLD:
04586          ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
04587          break;
04588       case AST_CONTROL_RINGING:
04589          ast_indicate(pu->chan, -1);
04590          break;
04591       default:
04592          break;
04593       }
04594       pu->hold_method = 0;
04595 
04596       /* Get chan, exten from derived kludge */
04597       if (pu->peername[0]) {
04598          char *peername;
04599          char *dash;
04600          char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
04601          int i;
04602 
04603          peername = ast_strdupa(pu->peername);
04604          dash = strrchr(peername, '-');
04605          if (dash) {
04606             *dash = '\0';
04607          }
04608 
04609          peername_flat = ast_strdupa(peername);
04610          for (i = 0; peername_flat[i]; i++) {
04611             if (peername_flat[i] == '/') {
04612                peername_flat[i] = '_';
04613             }
04614          }
04615 
04616          if (!ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar)) {
04617             ast_log(LOG_ERROR,
04618                "Parking dial context '%s' does not exist and unable to create\n",
04619                parking_con_dial);
04620          } else {
04621             char returnexten[AST_MAX_EXTENSION];
04622             char comebackdialtime[AST_MAX_EXTENSION];
04623             struct ast_datastore *features_datastore;
04624             struct ast_dial_features *dialfeatures;
04625 
04626             if (!strncmp(peername, "Parked/", 7)) {
04627                peername += 7;
04628             }
04629 
04630             ast_channel_lock(chan);
04631             features_datastore = ast_channel_datastore_find(chan, &dial_features_info,
04632                NULL);
04633             if (features_datastore && (dialfeatures = features_datastore->data)) {
04634                char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
04635 
04636                snprintf(returnexten, sizeof(returnexten), "%s,%u,%s", peername,
04637                   pu->parkinglot->cfg.comebackdialtime,
04638                   callback_dialoptions(&(dialfeatures->features_callee),
04639                      &(dialfeatures->features_caller), buf, sizeof(buf)));
04640             } else { /* Existing default */
04641                ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n",
04642                   ast_channel_name(chan));
04643                snprintf(returnexten, sizeof(returnexten), "%s,%u,t", peername,
04644                   pu->parkinglot->cfg.comebackdialtime);
04645             }
04646             ast_channel_unlock(chan);
04647 
04648             snprintf(comebackdialtime, sizeof(comebackdialtime), "%u",
04649                   pu->parkinglot->cfg.comebackdialtime);
04650             pbx_builtin_setvar_helper(chan, "COMEBACKDIALTIME", comebackdialtime);
04651 
04652             pbx_builtin_setvar_helper(chan, "PARKER", peername);
04653 
04654             if (ast_add_extension(parking_con_dial, 1, peername_flat, 1, NULL, NULL,
04655                "Dial", ast_strdup(returnexten), ast_free_ptr, registrar)) {
04656                ast_log(LOG_ERROR,
04657                   "Could not create parking return dial exten: %s@%s\n",
04658                   peername_flat, parking_con_dial);
04659             }
04660          }
04661          if (pu->options_specified) {
04662             /*
04663              * Park() was called with overriding return arguments, respect
04664              * those arguments.
04665              */
04666             set_c_e_p(chan, pu->context, pu->exten, pu->priority);
04667          } else if (pu->parkinglot->cfg.comebacktoorigin) {
04668             set_c_e_p(chan, parking_con_dial, peername_flat, 1);
04669          } else {
04670             char parkingslot[AST_MAX_EXTENSION];
04671 
04672             snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
04673             pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
04674             pbx_builtin_setvar_helper(chan, "PARKEDLOT", pu->parkinglot->name);
04675             set_c_e_p(chan, pu->parkinglot->cfg.comebackcontext, peername_flat, 1);
04676          }
04677       } else {
04678          /*
04679           * They've been waiting too long, send them back to where they
04680           * came.  Theoretically they should have their original
04681           * extensions and such, but we copy to be on the safe side.
04682           */
04683          set_c_e_p(chan, pu->context, pu->exten, pu->priority);
04684       }
04685       post_manager_event("ParkedCallTimeOut", pu);
04686       ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
04687 
04688       ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n",
04689          ast_channel_name(pu->chan), pu->parkingnum, pu->parkinglot->name, pu->chan->context,
04690          pu->chan->exten, pu->chan->priority);
04691 
04692       /* Start up the PBX, or hang them up */
04693       if (ast_pbx_start(chan))  {
04694          ast_log(LOG_WARNING,
04695             "Unable to restart the PBX for user on '%s', hanging them up...\n",
04696             ast_channel_name(pu->chan));
04697          ast_hangup(chan);
04698       }
04699 
04700       /* And take them out of the parking lot */
04701       parking_complete = 1;
04702    } else { /* still within parking time, process descriptors */
04703       for (x = 0; x < AST_MAX_FDS; x++) {
04704          struct ast_frame *f;
04705          int y;
04706 
04707          if (chan->fds[x] == -1) {
04708             continue;   /* nothing on this descriptor */
04709          }
04710 
04711          for (y = 0; y < nfds; y++) {
04712             if (pfds[y].fd == chan->fds[x]) {
04713                /* Found poll record! */
04714                break;
04715             }
04716          }
04717          if (y == nfds) {
04718             /* Not found */
04719             continue;
04720          }
04721 
04722          if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
04723             /* Next x */
04724             continue;
04725          }
04726 
04727          if (pfds[y].revents & POLLPRI) {
04728             ast_set_flag(chan, AST_FLAG_EXCEPTION);
04729          } else {
04730             ast_clear_flag(chan, AST_FLAG_EXCEPTION);
04731          }
04732          chan->fdno = x;
04733 
04734          /* See if they need servicing */
04735          f = ast_read(pu->chan);
04736          /* Hangup? */
04737          if (!f || (f->frametype == AST_FRAME_CONTROL
04738             && f->subclass.integer == AST_CONTROL_HANGUP)) {
04739             if (f) {
04740                ast_frfree(f);
04741             }
04742             post_manager_event("ParkedCallGiveUp", pu);
04743             ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp",
04744                NULL);
04745 
04746             /* There's a problem, hang them up */
04747             ast_verb(2, "%s got tired of being parked\n", ast_channel_name(chan));
04748             ast_hangup(chan);
04749 
04750             /* And take them out of the parking lot */
04751             parking_complete = 1;
04752             break;
04753          } else {
04754             /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
04755             ast_frfree(f);
04756             if (pu->hold_method == AST_CONTROL_HOLD
04757                && pu->moh_trys < 3
04758                && !chan->generatordata) {
04759                ast_debug(1,
04760                   "MOH on parked call stopped by outside source.  Restarting on channel %s.\n",
04761                   ast_channel_name(chan));
04762                ast_indicate_data(chan, AST_CONTROL_HOLD,
04763                   S_OR(pu->parkinglot->cfg.mohclass, NULL),
04764                   (!ast_strlen_zero(pu->parkinglot->cfg.mohclass)
04765                      ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0));
04766                pu->moh_trys++;
04767             }
04768             goto std;   /* XXX Ick: jumping into an else statement??? XXX */
04769          }
04770       } /* End for */
04771       if (x >= AST_MAX_FDS) {
04772 std:     for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
04773             if (chan->fds[x] > -1) {
04774                void *tmp = ast_realloc(*new_pfds,
04775                   (*new_nfds + 1) * sizeof(struct pollfd));
04776 
04777                if (!tmp) {
04778                   continue;
04779                }
04780                *new_pfds = tmp;
04781                (*new_pfds)[*new_nfds].fd = chan->fds[x];
04782                (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
04783                (*new_pfds)[*new_nfds].revents = 0;
04784                (*new_nfds)++;
04785             }
04786          }
04787          /* Keep track of our shortest wait */
04788          if (tms < *ms || *ms < 0) {
04789             *ms = tms;
04790          }
04791       }
04792    }
04793 
04794    return parking_complete;
04795 }
04796 
04797 /*! \brief Run management on parkinglots, called once per parkinglot */
04798 static void manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
04799 {
04800    struct parkeduser *pu;
04801    struct ast_context *con;
04802 
04803    /* Lock parkings list */
04804    AST_LIST_LOCK(&curlot->parkings);
04805    AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
04806       if (pu->notquiteyet) { /* Pretend this one isn't here yet */
04807          continue;
04808       }
04809       if (manage_parked_call(pu, pfds, nfds, new_pfds, new_nfds, ms)) {
04810          /* Parking is complete for this call so remove it from the parking lot. */
04811          con = ast_context_find(pu->parkinglot->cfg.parking_con);
04812          if (con) {
04813             if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
04814                ast_log(LOG_WARNING,
04815                   "Whoa, failed to remove the parking extension %s@%s!\n",
04816                   pu->parkingexten, pu->parkinglot->cfg.parking_con);
04817             }
04818             notify_metermaids(pu->parkingexten, pu->parkinglot->cfg.parking_con,
04819                AST_DEVICE_NOT_INUSE);
04820          } else {
04821             ast_log(LOG_WARNING,
04822                "Whoa, parking lot '%s' context '%s' does not exist.\n",
04823                pu->parkinglot->name, pu->parkinglot->cfg.parking_con);
04824          }
04825          AST_LIST_REMOVE_CURRENT(list);
04826          parkinglot_unref(pu->parkinglot);
04827          ast_free(pu);
04828       }
04829    }
04830    AST_LIST_TRAVERSE_SAFE_END;
04831    AST_LIST_UNLOCK(&curlot->parkings);
04832 }
04833 
04834 /*! 
04835  * \brief Take care of parked calls and unpark them if needed 
04836  * \param ignore unused var.
04837  * 
04838  * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
04839  * if so, remove channel from parking lot and return it to the extension that parked it.
04840  * Check if parked channel decided to hangup, wait until next FD via select().
04841  */
04842 static void *do_parking_thread(void *ignore)
04843 {
04844    struct pollfd *pfds = NULL, *new_pfds = NULL;
04845    int nfds = 0, new_nfds = 0;
04846 
04847    for (;;) {
04848       struct ao2_iterator iter;
04849       struct ast_parkinglot *curlot;
04850       int ms = -1;   /* poll2 timeout, uninitialized */
04851 
04852       iter = ao2_iterator_init(parkinglots, 0);
04853       while ((curlot = ao2_iterator_next(&iter))) {
04854          manage_parkinglot(curlot, pfds, nfds, &new_pfds, &new_nfds, &ms);
04855          ao2_ref(curlot, -1);
04856       }
04857       ao2_iterator_destroy(&iter);
04858 
04859       /* Recycle */
04860       ast_free(pfds);
04861       pfds = new_pfds;
04862       nfds = new_nfds;
04863       new_pfds = NULL;
04864       new_nfds = 0;
04865 
04866       /* Wait for something to happen */
04867       ast_poll(pfds, nfds, ms);
04868       pthread_testcancel();
04869    }
04870    /* If this WERE reached, we'd need to free(pfds) */
04871    return NULL;   /* Never reached */
04872 }
04873 
04874 /*! \brief Find parkinglot by name */
04875 static struct ast_parkinglot *find_parkinglot(const char *name)
04876 {
04877    struct ast_parkinglot *parkinglot;
04878 
04879    if (ast_strlen_zero(name)) {
04880       return NULL;
04881    }
04882 
04883    parkinglot = ao2_find(parkinglots, (void *) name, 0);
04884    if (parkinglot) {
04885       ast_debug(1, "Found Parking lot: %s\n", parkinglot->name);
04886    }
04887 
04888    return parkinglot;
04889 }
04890 
04891 /*! \brief Copy parkinglot and store it with new name */
04892 static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot)
04893 {
04894    struct ast_parkinglot *copylot;
04895 
04896    if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
04897       ao2_ref(copylot, -1);
04898       return NULL;
04899    }
04900 
04901    copylot = create_parkinglot(name);
04902    if (!copylot) {
04903       return NULL;
04904    }
04905 
04906    ast_debug(1, "Building parking lot %s\n", name);
04907 
04908    /* Copy the source parking lot configuration. */
04909    copylot->cfg = parkinglot->cfg;
04910 
04911    return copylot;
04912 }
04913 
04914 AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
04915    AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
04916    AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
04917    AST_APP_OPTION('s', AST_PARK_OPT_SILENCE),
04918 END_OPTIONS );
04919 
04920 /*! \brief Park a call */
04921 static int park_call_exec(struct ast_channel *chan, const char *data)
04922 {
04923    /* Cache the original channel name in case we get masqueraded in the middle
04924     * of a park--it is still theoretically possible for a transfer to happen before
04925     * we get here, but it is _really_ unlikely */
04926    char *orig_chan_name = ast_strdupa(ast_channel_name(chan));
04927    struct ast_park_call_args args = {
04928       .orig_chan_name = orig_chan_name,
04929    };
04930    struct ast_flags flags = { 0 };
04931    char orig_exten[AST_MAX_EXTENSION];
04932    int orig_priority;
04933    int res;
04934    const char *pl_name;
04935    char *parse;
04936    struct park_app_args app_args;
04937 
04938    /* Answer if call is not up */
04939    if (chan->_state != AST_STATE_UP) {
04940       if (ast_answer(chan)) {
04941          return -1;
04942       }
04943 
04944       /* Sleep to allow VoIP streams to settle down */
04945       if (ast_safe_sleep(chan, 1000)) {
04946          return -1;
04947       }
04948    }
04949 
04950    /* Process the dialplan application options. */
04951    parse = ast_strdupa(data);
04952    AST_STANDARD_APP_ARGS(app_args, parse);
04953 
04954    if (!ast_strlen_zero(app_args.timeout)) {
04955       if (sscanf(app_args.timeout, "%30d", &args.timeout) != 1) {
04956          ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
04957          args.timeout = 0;
04958       }
04959    }
04960    if (!ast_strlen_zero(app_args.return_con)) {
04961       args.return_con = app_args.return_con;
04962    }
04963    if (!ast_strlen_zero(app_args.return_ext)) {
04964       args.return_ext = app_args.return_ext;
04965    }
04966    if (!ast_strlen_zero(app_args.return_pri)) {
04967       if (sscanf(app_args.return_pri, "%30d", &args.return_pri) != 1) {
04968          ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
04969          args.return_pri = 0;
04970       }
04971    }
04972 
04973    ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
04974    args.flags = flags.flags;
04975 
04976    /*
04977     * Setup the exten/priority to be s/1 since we don't know where
04978     * this call should return.
04979     */
04980    ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
04981    orig_priority = chan->priority;
04982    strcpy(chan->exten, "s");
04983    chan->priority = 1;
04984 
04985    /* Park the call */
04986    if (!ast_strlen_zero(app_args.pl_name)) {
04987       pl_name = app_args.pl_name;
04988    } else {
04989       pl_name = findparkinglotname(chan);
04990    }
04991    if (ast_strlen_zero(pl_name)) {
04992       /* Parking lot is not specified, so use the default parking lot. */
04993       args.parkinglot = parkinglot_addref(default_parkinglot);
04994    } else {
04995       args.parkinglot = find_parkinglot(pl_name);
04996       if (!args.parkinglot && parkeddynamic) {
04997          args.parkinglot = create_dynamic_parkinglot(pl_name, chan);
04998       }
04999    }
05000    if (args.parkinglot) {
05001       res = masq_park_call(chan, chan, &args);
05002       parkinglot_unref(args.parkinglot);
05003    } else {
05004       /* Parking failed because the parking lot does not exist. */
05005       if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
05006          ast_stream_and_wait(chan, "pbx-parkingfailed", "");
05007       }
05008       res = -1;
05009    }
05010    if (res) {
05011       /* Park failed, try to continue in the dialplan. */
05012       ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
05013       chan->priority = orig_priority;
05014       res = 0;
05015    } else {
05016       /* Park succeeded. */
05017       res = -1;
05018    }
05019 
05020    return res;
05021 }
05022 
05023 /*! \brief Pickup parked call */
05024 static int parked_call_exec(struct ast_channel *chan, const char *data)
05025 {
05026    int res = 0;
05027    struct ast_channel *peer = NULL;
05028    struct parkeduser *pu;
05029    struct ast_context *con;
05030    char *parse;
05031    const char *pl_name;
05032    int park = 0;
05033    struct ast_bridge_config config;
05034    struct ast_parkinglot *parkinglot;
05035    AST_DECLARE_APP_ARGS(app_args,
05036       AST_APP_ARG(pl_space);  /*!< Parking lot space to retrieve if present. */
05037       AST_APP_ARG(pl_name);   /*!< Parking lot name to use if present. */
05038       AST_APP_ARG(dummy);     /*!< Place to put any remaining args string. */
05039    );
05040 
05041    parse = ast_strdupa(data);
05042    AST_STANDARD_APP_ARGS(app_args, parse);
05043 
05044    if (!ast_strlen_zero(app_args.pl_space)) {
05045       if (sscanf(app_args.pl_space, "%30u", &park) != 1) {
05046          ast_log(LOG_WARNING, "Specified parking extension not a number: %s\n",
05047             app_args.pl_space);
05048          park = -1;
05049       }
05050    }
05051 
05052    if (!ast_strlen_zero(app_args.pl_name)) {
05053       pl_name = app_args.pl_name;
05054    } else {
05055       pl_name = findparkinglotname(chan);
05056    }
05057    if (ast_strlen_zero(pl_name)) {
05058       /* Parking lot is not specified, so use the default parking lot. */
05059       parkinglot = parkinglot_addref(default_parkinglot);
05060    } else {
05061       parkinglot = find_parkinglot(pl_name);
05062       if (!parkinglot) {
05063          /* It helps to answer the channel if not already up. :) */
05064          if (chan->_state != AST_STATE_UP) {
05065             ast_answer(chan);
05066          }
05067          if (ast_stream_and_wait(chan, "pbx-invalidpark", "")) {
05068             ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n",
05069                "pbx-invalidpark", ast_channel_name(chan));
05070          }
05071          ast_log(LOG_WARNING,
05072             "Channel %s tried to retrieve parked call from unknown parking lot '%s'\n",
05073             ast_channel_name(chan), pl_name);
05074          return -1;
05075       }
05076    }
05077 
05078    AST_LIST_LOCK(&parkinglot->parkings);
05079    AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
05080       if ((ast_strlen_zero(app_args.pl_space) || pu->parkingnum == park)
05081          && !pu->notquiteyet && !pu->chan->pbx) {
05082          /* The parking space has a call and can be picked up now. */
05083          AST_LIST_REMOVE_CURRENT(list);
05084          break;
05085       }
05086    }
05087    AST_LIST_TRAVERSE_SAFE_END;
05088    if (pu) {
05089       /* Found a parked call to pickup. */
05090       peer = pu->chan;
05091       con = ast_context_find(parkinglot->cfg.parking_con);
05092       if (con) {
05093          if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
05094             ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
05095          } else {
05096             notify_metermaids(pu->parkingexten, parkinglot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
05097          }
05098       } else {
05099          ast_log(LOG_WARNING, "Whoa, no parking context?\n");
05100       }
05101 
05102       ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "UnParkedCall", chan);
05103       ast_manager_event(pu->chan, EVENT_FLAG_CALL, "UnParkedCall",
05104          "Exten: %s\r\n"
05105          "Channel: %s\r\n"
05106          "Parkinglot: %s\r\n"
05107          "From: %s\r\n"
05108          "CallerIDNum: %s\r\n"
05109          "CallerIDName: %s\r\n"
05110          "ConnectedLineNum: %s\r\n"
05111          "ConnectedLineName: %s\r\n"
05112          "Uniqueid: %s\r\n",
05113          pu->parkingexten, ast_channel_name(pu->chan), pu->parkinglot->name,
05114          ast_channel_name(chan),
05115          S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
05116          S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
05117          S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
05118          S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
05119          ast_channel_uniqueid(pu->chan)
05120          );
05121 
05122       /* Stop entertaining the caller. */
05123       switch (pu->hold_method) {
05124       case AST_CONTROL_HOLD:
05125          ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
05126          break;
05127       case AST_CONTROL_RINGING:
05128          ast_indicate(pu->chan, -1);
05129          break;
05130       default:
05131          break;
05132       }
05133       pu->hold_method = 0;
05134 
05135       parkinglot_unref(pu->parkinglot);
05136       ast_free(pu);
05137    }
05138    AST_LIST_UNLOCK(&parkinglot->parkings);
05139 
05140    if (peer) {
05141       /* Update connected line between retrieving call and parked call. */
05142       struct ast_party_connected_line connected;
05143 
05144       ast_party_connected_line_init(&connected);
05145 
05146       /* Send our caller-id to peer. */
05147       ast_channel_lock(chan);
05148       ast_connected_line_copy_from_caller(&connected, &chan->caller);
05149       ast_channel_unlock(chan);
05150       connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
05151       if (ast_channel_connected_line_macro(chan, peer, &connected, 0, 0)) {
05152          ast_channel_update_connected_line(peer, &connected, NULL);
05153       }
05154 
05155       /*
05156        * Get caller-id from peer.
05157        *
05158        * Update the retrieving call before it is answered if possible
05159        * for best results.  Some phones do not support updating the
05160        * connected line information after connection.
05161        */
05162       ast_channel_lock(peer);
05163       ast_connected_line_copy_from_caller(&connected, &peer->caller);
05164       ast_channel_unlock(peer);
05165       connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
05166       if (ast_channel_connected_line_macro(peer, chan, &connected, 1, 0)) {
05167          ast_channel_update_connected_line(chan, &connected, NULL);
05168       }
05169 
05170       ast_party_connected_line_free(&connected);
05171    }
05172 
05173    /* JK02: it helps to answer the channel if not already up */
05174    if (chan->_state != AST_STATE_UP) {
05175       ast_answer(chan);
05176    }
05177 
05178    if (peer) {
05179       struct ast_datastore *features_datastore;
05180       struct ast_dial_features *dialfeatures = NULL;
05181 
05182       /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
05183       if (!ast_strlen_zero(courtesytone)) {
05184          static const char msg[] = "courtesy tone";
05185 
05186          switch (parkedplay) {
05187          case 0:/* Courtesy tone to pickup chan */
05188             res = play_message_to_chans(chan, peer, -1, msg, courtesytone);
05189             break;
05190          case 1:/* Courtesy tone to parked chan */
05191             res = play_message_to_chans(chan, peer, 1, msg, courtesytone);
05192             break;
05193          case 2:/* Courtesy tone to both chans */
05194             res = play_message_to_chans(chan, peer, 0, msg, courtesytone);
05195             break;
05196          default:
05197             res = 0;
05198             break;
05199          }
05200          if (res) {
05201             ast_hangup(peer);
05202             parkinglot_unref(parkinglot);
05203             return -1;
05204          }
05205       }
05206 
05207       res = ast_channel_make_compatible(chan, peer);
05208       if (res < 0) {
05209          ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", ast_channel_name(chan), ast_channel_name(peer));
05210          ast_hangup(peer);
05211          parkinglot_unref(parkinglot);
05212          return -1;
05213       }
05214       /* This runs sorta backwards, since we give the incoming channel control, as if it
05215          were the person called. */
05216       ast_verb(3, "Channel %s connected to parked call %d\n", ast_channel_name(chan), park);
05217 
05218       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", ast_channel_name(peer));
05219       ast_cdr_setdestchan(chan->cdr, ast_channel_name(peer));
05220       memset(&config, 0, sizeof(struct ast_bridge_config));
05221 
05222       /* Get datastore for peer and apply it's features to the callee side of the bridge config */
05223       ast_channel_lock(peer);
05224       if ((features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL))) {
05225          dialfeatures = features_datastore->data;
05226       }
05227 
05228       /*
05229        * When the datastores for both caller and callee are created,
05230        * both the callee and caller channels use the features_caller
05231        * flag variable to represent themselves.  With that said, the
05232        * config.features_callee flags should be copied from the
05233        * datastore's caller feature flags regardless if peer was a
05234        * callee or caller.
05235        */
05236       if (dialfeatures) {
05237          ast_copy_flags(&(config.features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
05238       }
05239       ast_channel_unlock(peer);
05240 
05241       if ((parkinglot->cfg.parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->cfg.parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
05242          ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
05243       }
05244       if ((parkinglot->cfg.parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->cfg.parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
05245          ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
05246       }
05247       if ((parkinglot->cfg.parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->cfg.parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
05248          ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
05249       }
05250       if ((parkinglot->cfg.parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->cfg.parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
05251          ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
05252       }
05253       if ((parkinglot->cfg.parkedcallhangup == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->cfg.parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
05254          ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
05255       }
05256       if ((parkinglot->cfg.parkedcallhangup == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->cfg.parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
05257          ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
05258       }
05259       if ((parkinglot->cfg.parkedcallrecording == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->cfg.parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
05260          ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
05261       }
05262       if ((parkinglot->cfg.parkedcallrecording == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->cfg.parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
05263          ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
05264       }
05265 
05266       res = ast_bridge_call(chan, peer, &config);
05267 
05268       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", ast_channel_name(peer));
05269       ast_cdr_setdestchan(chan->cdr, ast_channel_name(peer));
05270 
05271       /* Simulate the PBX hanging up */
05272       ast_hangup(peer);
05273    } else {
05274       if (ast_stream_and_wait(chan, "pbx-invalidpark", "")) {
05275          ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark",
05276             ast_channel_name(chan));
05277       }
05278       ast_verb(3, "Channel %s tried to retrieve nonexistent parked call %d\n",
05279          ast_channel_name(chan), park);
05280    }
05281 
05282    parkinglot_unref(parkinglot);
05283    return -1;
05284 }
05285 
05286 /*!
05287  * \brief Unreference parkinglot object.
05288  */
05289 static void parkinglot_unref(struct ast_parkinglot *parkinglot) 
05290 {
05291    ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name,
05292       ao2_ref(parkinglot, 0) - 1);
05293    ao2_ref(parkinglot, -1);
05294 }
05295 
05296 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
05297 {
05298    int refcount;
05299 
05300    refcount = ao2_ref(parkinglot, +1);
05301    ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
05302    return parkinglot;
05303 }
05304 
05305 /*! \brief Destroy a parking lot */
05306 static void parkinglot_destroy(void *obj)
05307 {
05308    struct ast_parkinglot *doomed = obj;
05309 
05310    /*
05311     * No need to destroy parked calls here because any parked call
05312     * holds a parking lot reference.  Therefore the parkings list
05313     * must be empty.
05314     */
05315    ast_assert(AST_LIST_EMPTY(&doomed->parkings));
05316    AST_LIST_HEAD_DESTROY(&doomed->parkings);
05317 }
05318 
05319 /*! \brief Allocate parking lot structure */
05320 static struct ast_parkinglot *create_parkinglot(const char *name)
05321 {
05322    struct ast_parkinglot *newlot;
05323 
05324    if (ast_strlen_zero(name)) { /* No name specified */
05325       return NULL;
05326    }
05327 
05328    newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);
05329    if (!newlot)
05330       return NULL;
05331    
05332    ast_copy_string(newlot->name, name, sizeof(newlot->name));
05333    newlot->cfg.is_invalid = 1;/* No config is set yet. */
05334    AST_LIST_HEAD_INIT(&newlot->parkings);
05335 
05336    return newlot;
05337 }
05338 
05339 /*! 
05340  * \brief Add parking hints for all defined parking spaces.
05341  * \param context Dialplan context to add the hints.
05342  * \param start Starting space in parkinglot.
05343  * \param stop Ending space in parkinglot.
05344  */
05345 static void park_add_hints(const char *context, int start, int stop)
05346 {
05347    int numext;
05348    char device[AST_MAX_EXTENSION];
05349    char exten[10];
05350 
05351    for (numext = start; numext <= stop; numext++) {
05352       snprintf(exten, sizeof(exten), "%d", numext);
05353       snprintf(device, sizeof(device), "park:%s@%s", exten, context);
05354       ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
05355    }
05356 }
05357 
05358 /*! Default configuration for default parking lot. */
05359 static const struct parkinglot_cfg parkinglot_cfg_default_default = {
05360    .mohclass = "default",
05361    .parkext = DEFAULT_PARK_EXTENSION,
05362    .parking_con = "parkedcalls",
05363    .parking_start = 701,
05364    .parking_stop = 750,
05365    .parkingtime = DEFAULT_PARK_TIME,
05366    .comebackdialtime = DEFAULT_COMEBACK_DIAL_TIME,
05367    .comebackcontext = DEFAULT_COMEBACK_CONTEXT,
05368    .comebacktoorigin = DEFAULT_COMEBACK_TO_ORIGIN,
05369 };
05370 
05371 /*! Default configuration for normal parking lots. */
05372 static const struct parkinglot_cfg parkinglot_cfg_default = {
05373    .parkext = DEFAULT_PARK_EXTENSION,
05374    .parkingtime = DEFAULT_PARK_TIME,
05375    .comebackdialtime = DEFAULT_COMEBACK_DIAL_TIME,
05376    .comebackcontext = DEFAULT_COMEBACK_CONTEXT,
05377    .comebacktoorigin = DEFAULT_COMEBACK_TO_ORIGIN,
05378 };
05379 
05380 /*!
05381  * \internal
05382  * \brief Set parking lot feature flag configuration value.
05383  *
05384  * \param pl_name Parking lot name for diagnostic messages.
05385  * \param param Parameter value to set.
05386  * \param var Current configuration variable item.
05387  *
05388  * \return Nothing
05389  */
05390 static void parkinglot_feature_flag_cfg(const char *pl_name, int *param, struct ast_variable *var)
05391 {
05392    ast_debug(1, "Setting parking lot %s %s to %s\n", pl_name, var->name, var->value);
05393    if (!strcasecmp(var->value, "both")) {
05394       *param = AST_FEATURE_FLAG_BYBOTH;
05395    } else if (!strcasecmp(var->value, "caller")) {
05396       *param = AST_FEATURE_FLAG_BYCALLER;
05397    } else if (!strcasecmp(var->value, "callee")) {
05398       *param = AST_FEATURE_FLAG_BYCALLEE;
05399    }
05400 }
05401 
05402 /*!
05403  * \internal
05404  * \brief Read parking lot configuration.
05405  *
05406  * \param pl_name Parking lot name for diagnostic messages.
05407  * \param cfg Parking lot config to update that is already initialized with defaults.
05408  * \param var Config variable list.
05409  *
05410  * \retval 0 on success.
05411  * \retval -1 on error.
05412  */
05413 static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cfg, struct ast_variable *var)
05414 {
05415    int error = 0;
05416 
05417    while (var) {
05418       if (!strcasecmp(var->name, "context")) {
05419          ast_copy_string(cfg->parking_con, var->value, sizeof(cfg->parking_con));
05420       } else if (!strcasecmp(var->name, "parkext")) {
05421          ast_copy_string(cfg->parkext, var->value, sizeof(cfg->parkext));
05422       } else if (!strcasecmp(var->name, "parkext_exclusive")) {
05423          cfg->parkext_exclusive = ast_true(var->value);
05424       } else if (!strcasecmp(var->name, "parkinghints")) {
05425          cfg->parkaddhints = ast_true(var->value);
05426       } else if (!strcasecmp(var->name, "parkedmusicclass")) {
05427          ast_copy_string(cfg->mohclass, var->value, sizeof(cfg->mohclass));
05428       } else if (!strcasecmp(var->name, "parkingtime")) {
05429          int parkingtime = 0;
05430 
05431          if ((sscanf(var->value, "%30d", &parkingtime) != 1) || parkingtime < 1) {
05432             ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
05433             error = -1;
05434          } else {
05435             cfg->parkingtime = parkingtime * 1000;
05436          }
05437       } else if (!strcasecmp(var->name, "parkpos")) {
05438          int start = 0;
05439          int end = 0;
05440 
05441          if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
05442             ast_log(LOG_WARNING,
05443                "Format for parking positions is a-b, where a and b are numbers at line %d of %s\n",
05444                var->lineno, var->file);
05445             error = -1;
05446          } else if (end < start || start <= 0 || end <= 0) {
05447             ast_log(LOG_WARNING, "Parking range is invalid. Must be a <= b, at line %d of %s\n",
05448                var->lineno, var->file);
05449             error = -1;
05450          } else {
05451             cfg->parking_start = start;
05452             cfg->parking_stop = end;
05453          }
05454       } else if (!strcasecmp(var->name, "findslot")) {
05455          cfg->parkfindnext = (!strcasecmp(var->value, "next"));
05456       } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
05457          parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcalltransfers, var);
05458       } else if (!strcasecmp(var->name, "parkedcallreparking")) {
05459          parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallreparking, var);
05460       } else if (!strcasecmp(var->name, "parkedcallhangup")) {
05461          parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallhangup, var);
05462       } else if (!strcasecmp(var->name, "parkedcallrecording")) {
05463          parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallrecording, var);
05464       } else if (!strcasecmp(var->name, "comebackcontext")) {
05465          ast_copy_string(cfg->comebackcontext, var->value, sizeof(cfg->comebackcontext));
05466       } else if (!strcasecmp(var->name, "comebacktoorigin")) {
05467          cfg->comebacktoorigin = ast_true(var->value);
05468       } else if (!strcasecmp(var->name, "comebackdialtime")) {
05469          if ((sscanf(var->value, "%30u", &cfg->comebackdialtime) != 1)
05470                || (cfg->comebackdialtime < 1)) {
05471             ast_log(LOG_WARNING, "%s is not a valid comebackdialtime\n", var->value);
05472             cfg->parkingtime = DEFAULT_COMEBACK_DIAL_TIME;
05473          }
05474       }
05475       var = var->next;
05476    }
05477 
05478    /* Check for configuration errors */
05479    if (ast_strlen_zero(cfg->parking_con)) {
05480       ast_log(LOG_WARNING, "Parking lot %s needs context\n", pl_name);
05481       error = -1;
05482    }
05483    if (ast_strlen_zero(cfg->parkext)) {
05484       ast_log(LOG_WARNING, "Parking lot %s needs parkext\n", pl_name);
05485       error = -1;
05486    }
05487    if (!cfg->parking_start) {
05488       ast_log(LOG_WARNING, "Parking lot %s needs parkpos\n", pl_name);
05489       error = -1;
05490    }
05491    if (!cfg->comebacktoorigin && ast_strlen_zero(cfg->comebackcontext)) {
05492       ast_log(LOG_WARNING, "Parking lot %s has comebacktoorigin set false"
05493             "but has no comebackcontext.\n",
05494             pl_name);
05495       error = -1;
05496    }
05497    if (error) {
05498       cfg->is_invalid = 1;
05499    }
05500 
05501    return error;
05502 }
05503 
05504 /*!
05505  * \internal
05506  * \brief Activate the given parkinglot.
05507  *
05508  * \param parkinglot Parking lot to activate.
05509  *
05510  * \details
05511  * Insert into the dialplan the context, parking lot access
05512  * extension, and optional dialplan hints.
05513  *
05514  * \retval 0 on success.
05515  * \retval -1 on error.
05516  */
05517 static int parkinglot_activate(struct ast_parkinglot *parkinglot)
05518 {
05519    int disabled = 0;
05520    char app_data[5 + AST_MAX_CONTEXT];
05521 
05522    /* Create Park option list.  Must match with struct park_app_args options. */
05523    if (parkinglot->cfg.parkext_exclusive) {
05524       /* Specify the parking lot this parking extension parks calls. */
05525       snprintf(app_data, sizeof(app_data), ",,,,,%s", parkinglot->name);
05526    } else {
05527       /* The dialplan must specify which parking lot to use. */
05528       app_data[0] = '\0';
05529    }
05530 
05531    /* Create context */
05532    if (!ast_context_find_or_create(NULL, NULL, parkinglot->cfg.parking_con, registrar)) {
05533       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n",
05534          parkinglot->cfg.parking_con);
05535       disabled = 1;
05536 
05537    /* Add a parking extension into the context */
05538    } else if (ast_add_extension(parkinglot->cfg.parking_con, 1, parkinglot->cfg.parkext,
05539       1, NULL, NULL, parkcall, ast_strdup(app_data), ast_free_ptr, registrar)) {
05540       ast_log(LOG_ERROR, "Could not create parking lot %s access exten %s@%s\n",
05541          parkinglot->name, parkinglot->cfg.parkext, parkinglot->cfg.parking_con);
05542       disabled = 1;
05543    } else {
05544       /* Add parking hints */
05545       if (parkinglot->cfg.parkaddhints) {
05546          park_add_hints(parkinglot->cfg.parking_con, parkinglot->cfg.parking_start,
05547             parkinglot->cfg.parking_stop);
05548       }
05549 
05550       /*
05551        * XXX Not sure why we should need to notify the metermaids for
05552        * this exten.  It was originally done for the default parking
05553        * lot entry exten only but should be done for all entry extens
05554        * if we do it for one.
05555        */
05556       /* Notify metermaids about parking lot entry exten state. */
05557       notify_metermaids(parkinglot->cfg.parkext, parkinglot->cfg.parking_con,
05558          AST_DEVICE_INUSE);
05559    }
05560 
05561    parkinglot->disabled = disabled;
05562    return disabled ? -1 : 0;
05563 }
05564 
05565 /*! \brief Build parkinglot from configuration and chain it in if it doesn't already exist */
05566 static struct ast_parkinglot *build_parkinglot(const char *pl_name, struct ast_variable *var)
05567 {
05568    struct ast_parkinglot *parkinglot;
05569    const struct parkinglot_cfg *cfg_defaults;
05570    struct parkinglot_cfg new_cfg;
05571    int cfg_error;
05572    int oldparkinglot = 0;
05573 
05574    parkinglot = find_parkinglot(pl_name);
05575    if (parkinglot) {
05576       oldparkinglot = 1;
05577    } else {
05578       parkinglot = create_parkinglot(pl_name);
05579       if (!parkinglot) {
05580          return NULL;
05581       }
05582    }
05583    if (!strcmp(parkinglot->name, DEFAULT_PARKINGLOT)) {
05584       cfg_defaults = &parkinglot_cfg_default_default;
05585    } else {
05586       cfg_defaults = &parkinglot_cfg_default;
05587    }
05588    new_cfg = *cfg_defaults;
05589 
05590    ast_debug(1, "Building parking lot %s\n", parkinglot->name);
05591 
05592    ao2_lock(parkinglot);
05593 
05594    /* Do some config stuff */
05595    cfg_error = parkinglot_config_read(parkinglot->name, &new_cfg, var);
05596    if (oldparkinglot) {
05597       if (cfg_error) {
05598          /* Bad configuration read.  Keep using the original config. */
05599          ast_log(LOG_WARNING, "Changes to parking lot %s are discarded.\n",
05600             parkinglot->name);
05601          cfg_error = 0;
05602       } else if (!AST_LIST_EMPTY(&parkinglot->parkings)
05603          && memcmp(&new_cfg, &parkinglot->cfg, sizeof(parkinglot->cfg))) {
05604          /* Try reloading later when parking lot is empty. */
05605          ast_log(LOG_WARNING,
05606             "Parking lot %s has parked calls.  Parking lot changes discarded.\n",
05607             parkinglot->name);
05608          force_reload_load = 1;
05609       } else {
05610          /* Accept the new config */
05611          parkinglot->cfg = new_cfg;
05612       }
05613    } else {
05614       /* Load the initial parking lot config. */
05615       parkinglot->cfg = new_cfg;
05616    }
05617    parkinglot->the_mark = 0;
05618 
05619    ao2_unlock(parkinglot);
05620 
05621    if (cfg_error) {
05622       /* Only new parking lots could have config errors here. */
05623       ast_log(LOG_WARNING, "New parking lot %s is discarded.\n", parkinglot->name);
05624       parkinglot_unref(parkinglot);
05625       return NULL;
05626    }
05627 
05628    /* Move it into the list, if it wasn't already there */
05629    if (!oldparkinglot) {
05630       ao2_link(parkinglots, parkinglot);
05631    }
05632    parkinglot_unref(parkinglot);
05633 
05634    return parkinglot;
05635 }
05636 
05637 /*!
05638  * \internal
05639  * \brief Process an applicationmap section config line.
05640  *
05641  * \param var Config variable line.
05642  *
05643  * \return Nothing
05644  */
05645 static void process_applicationmap_line(struct ast_variable *var)
05646 {
05647    char *tmp_val = ast_strdupa(var->value);
05648    char *activateon;
05649    struct ast_call_feature *feature;
05650    AST_DECLARE_APP_ARGS(args,
05651       AST_APP_ARG(exten);
05652       AST_APP_ARG(activatedby);
05653       AST_APP_ARG(app);
05654       AST_APP_ARG(app_args);
05655       AST_APP_ARG(moh_class);
05656    );
05657 
05658    AST_STANDARD_APP_ARGS(args, tmp_val);
05659    if (strchr(args.app, '(')) {
05660       /* New syntax */
05661       args.moh_class = args.app_args;
05662       args.app_args = strchr(args.app, '(');
05663       *args.app_args++ = '\0';
05664       if (args.app_args[strlen(args.app_args) - 1] == ')') {
05665          args.app_args[strlen(args.app_args) - 1] = '\0';
05666       }
05667    }
05668 
05669    activateon = strsep(&args.activatedby, "/");
05670 
05671    /*! \todo XXX var_name or app_args ? */
05672    if (ast_strlen_zero(args.app)
05673       || ast_strlen_zero(args.exten)
05674       || ast_strlen_zero(activateon)
05675       || ast_strlen_zero(var->name)) {
05676       ast_log(LOG_NOTICE,
05677          "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
05678          args.app, args.exten, activateon, var->name);
05679       return;
05680    }
05681 
05682    AST_RWLIST_RDLOCK(&feature_list);
05683    if (find_dynamic_feature(var->name)) {
05684       AST_RWLIST_UNLOCK(&feature_list);
05685       ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n",
05686          var->name);
05687       return;
05688    }
05689    AST_RWLIST_UNLOCK(&feature_list);
05690 
05691    if (!(feature = ast_calloc(1, sizeof(*feature)))) {
05692       return;
05693    }
05694 
05695    ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
05696    ast_copy_string(feature->app, args.app, FEATURE_APP_LEN);
05697    ast_copy_string(feature->exten, args.exten, FEATURE_EXTEN_LEN);
05698 
05699    if (args.app_args) {
05700       ast_copy_string(feature->app_args, args.app_args, FEATURE_APP_ARGS_LEN);
05701    }
05702 
05703    if (args.moh_class) {
05704       ast_copy_string(feature->moh_class, args.moh_class, FEATURE_MOH_LEN);
05705    }
05706 
05707    ast_copy_string(feature->exten, args.exten, sizeof(feature->exten));
05708    feature->operation = feature_exec_app;
05709    ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
05710 
05711    /* Allow caller and callee to be specified for backwards compatability */
05712    if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller")) {
05713       ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
05714    } else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee")) {
05715       ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
05716    } else {
05717       ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
05718          " must be 'self', or 'peer'\n", var->name);
05719       return;
05720    }
05721 
05722    if (ast_strlen_zero(args.activatedby)) {
05723       ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
05724    } else if (!strcasecmp(args.activatedby, "caller")) {
05725       ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
05726    } else if (!strcasecmp(args.activatedby, "callee")) {
05727       ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
05728    } else if (!strcasecmp(args.activatedby, "both")) {
05729       ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
05730    } else {
05731       ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
05732          " must be 'caller', or 'callee', or 'both'\n", var->name);
05733       return;
05734    }
05735 
05736    ast_register_feature(feature);
05737 
05738    ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n",
05739       var->name, args.app, args.app_args, args.exten);
05740 }
05741 
05742 static int process_config(struct ast_config *cfg)
05743 {
05744    int i;
05745    struct ast_variable *var = NULL;
05746    struct feature_group *fg = NULL;
05747    char *ctg; 
05748    static const char * const categories[] = { 
05749       /* Categories in features.conf that are not
05750        * to be parsed as group categories
05751        */
05752       "general",
05753       "featuremap",
05754       "applicationmap"
05755    };
05756 
05757    /* Set general features global defaults. */
05758    featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
05759 
05760    /* Set global call pickup defaults. */
05761    strcpy(pickup_ext, "*8");
05762    pickupsound[0] = '\0';
05763    pickupfailsound[0] = '\0';
05764 
05765    /* Set global call transfer defaults. */
05766    strcpy(xfersound, "beep");
05767    strcpy(xferfailsound, "beeperr");
05768    transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
05769    atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
05770    atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
05771    atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
05772    atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
05773 
05774    /* Set global call parking defaults. */
05775    courtesytone[0] = '\0';
05776    parkedplay = 0;
05777    adsipark = 0;
05778    parkeddynamic = 0;
05779 
05780    var = ast_variable_browse(cfg, "general");
05781    build_parkinglot(DEFAULT_PARKINGLOT, var);
05782    for (; var; var = var->next) {
05783       if (!strcasecmp(var->name, "parkeddynamic")) {
05784          parkeddynamic = ast_true(var->value);
05785       } else if (!strcasecmp(var->name, "adsipark")) {
05786          adsipark = ast_true(var->value);
05787       } else if (!strcasecmp(var->name, "transferdigittimeout")) {
05788          if ((sscanf(var->value, "%30d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
05789             ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
05790             transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
05791          } else {
05792             transferdigittimeout = transferdigittimeout * 1000;
05793          }
05794       } else if (!strcasecmp(var->name, "featuredigittimeout")) {
05795          if ((sscanf(var->value, "%30d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
05796             ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
05797             featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
05798          }
05799       } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
05800          if ((sscanf(var->value, "%30d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
05801             ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
05802             atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
05803          } else {
05804             atxfernoanswertimeout = atxfernoanswertimeout * 1000;
05805          }
05806       } else if (!strcasecmp(var->name, "atxferloopdelay")) {
05807          if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
05808             ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
05809             atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
05810          } else {
05811             atxferloopdelay *= 1000;
05812          }
05813       } else if (!strcasecmp(var->name, "atxferdropcall")) {
05814          atxferdropcall = ast_true(var->value);
05815       } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
05816          if ((sscanf(var->value, "%30u", &atxfercallbackretries) != 1)) {
05817             ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
05818             atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
05819          }
05820       } else if (!strcasecmp(var->name, "courtesytone")) {
05821          ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
05822       }  else if (!strcasecmp(var->name, "parkedplay")) {
05823          if (!strcasecmp(var->value, "both")) {
05824             parkedplay = 2;
05825          } else if (!strcasecmp(var->value, "parked")) {
05826             parkedplay = 1;
05827          } else {
05828             parkedplay = 0;
05829          }
05830       } else if (!strcasecmp(var->name, "xfersound")) {
05831          ast_copy_string(xfersound, var->value, sizeof(xfersound));
05832       } else if (!strcasecmp(var->name, "xferfailsound")) {
05833          ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
05834       } else if (!strcasecmp(var->name, "pickupexten")) {
05835          ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
05836       } else if (!strcasecmp(var->name, "pickupsound")) {
05837          ast_copy_string(pickupsound, var->value, sizeof(pickupsound));
05838       } else if (!strcasecmp(var->name, "pickupfailsound")) {
05839          ast_copy_string(pickupfailsound, var->value, sizeof(pickupfailsound));
05840       }
05841    }
05842 
05843    unmap_features();
05844    for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
05845       if (remap_feature(var->name, var->value)) {
05846          ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
05847       }
05848    }
05849 
05850    /* Map a key combination to an application */
05851    ast_unregister_features();
05852    for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
05853       process_applicationmap_line(var);
05854    }
05855 
05856    ast_unregister_groups();
05857    AST_RWLIST_WRLOCK(&feature_groups);
05858 
05859    ctg = NULL;
05860    while ((ctg = ast_category_browse(cfg, ctg))) {
05861       /* Is this a parkinglot definition ? */
05862       if (!strncasecmp(ctg, "parkinglot_", strlen("parkinglot_"))) {
05863          ast_debug(2, "Found configuration section %s, assume parking context\n", ctg);
05864          if (!build_parkinglot(ctg, ast_variable_browse(cfg, ctg))) {
05865             ast_log(LOG_ERROR, "Could not build parking lot %s. Configuration error.\n", ctg);
05866          } else {
05867             ast_debug(1, "Configured parking context %s\n", ctg);
05868          }
05869          continue;
05870       }
05871 
05872       /* No, check if it's a group */
05873       for (i = 0; i < ARRAY_LEN(categories); i++) {
05874          if (!strcasecmp(categories[i], ctg)) {
05875             break;
05876          }
05877       }
05878       if (i < ARRAY_LEN(categories)) {
05879          continue;
05880       }
05881 
05882       if (!(fg = register_group(ctg))) {
05883          continue;
05884       }
05885 
05886       for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
05887          struct ast_call_feature *feature;
05888 
05889          AST_RWLIST_RDLOCK(&feature_list);
05890          if (!(feature = find_dynamic_feature(var->name)) && 
05891              !(feature = ast_find_call_feature(var->name))) {
05892             AST_RWLIST_UNLOCK(&feature_list);
05893             ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
05894             continue;
05895          }
05896          AST_RWLIST_UNLOCK(&feature_list);
05897 
05898          register_group_feature(fg, var->value, feature);
05899       }
05900    }
05901 
05902    AST_RWLIST_UNLOCK(&feature_groups);
05903 
05904    return 0;
05905 }
05906 
05907 /*!
05908  * \internal
05909  * \brief Destroy the given dialplan usage context.
05910  *
05911  * \param doomed Parking lot usage context to destroy.
05912  *
05913  * \return Nothing
05914  */
05915 static void destroy_dialplan_usage_context(struct parking_dp_context *doomed)
05916 {
05917    struct parking_dp_ramp *ramp;
05918    struct parking_dp_spaces *spaces;
05919 
05920    while ((ramp = AST_LIST_REMOVE_HEAD(&doomed->access_extens, node))) {
05921       ast_free(ramp);
05922    }
05923    while ((spaces = AST_LIST_REMOVE_HEAD(&doomed->spaces, node))) {
05924       ast_free(spaces);
05925    }
05926    while ((spaces = AST_LIST_REMOVE_HEAD(&doomed->hints, node))) {
05927       ast_free(spaces);
05928    }
05929    ast_free(doomed);
05930 }
05931 
05932 /*!
05933  * \internal
05934  * \brief Destroy the given dialplan usage map.
05935  *
05936  * \param doomed Parking lot usage map to destroy.
05937  *
05938  * \return Nothing
05939  */
05940 static void destroy_dialplan_usage_map(struct parking_dp_map *doomed)
05941 {
05942    struct parking_dp_context *item;
05943 
05944    while ((item = AST_LIST_REMOVE_HEAD(doomed, node))) {
05945       destroy_dialplan_usage_context(item);
05946    }
05947 }
05948 
05949 /*!
05950  * \internal
05951  * \brief Create a new parking lot ramp dialplan usage node.
05952  *
05953  * \param exten Parking lot access ramp extension.
05954  * \param exclusive TRUE if the parking lot access ramp extension is exclusive.
05955  *
05956  * \retval New usage ramp node on success.
05957  * \retval NULL on error.
05958  */
05959 static struct parking_dp_ramp *build_dialplan_useage_ramp(const char *exten, int exclusive)
05960 {
05961    struct parking_dp_ramp *ramp_node;
05962 
05963    ramp_node = ast_calloc(1, sizeof(*ramp_node) + strlen(exten));
05964    if (!ramp_node) {
05965       return NULL;
05966    }
05967    ramp_node->exclusive = exclusive;
05968    strcpy(ramp_node->exten, exten);
05969    return ramp_node;
05970 }
05971 
05972 /*!
05973  * \internal
05974  * \brief Add parking lot access ramp to the context ramp usage map.
05975  *
05976  * \param ramp_map Current parking lot context ramp usage map.
05977  * \param exten Parking lot access ramp extension to add.
05978  * \param exclusive TRUE if the parking lot access ramp extension is exclusive.
05979  * \param lot Parking lot supplying reference data.
05980  * \param complain TRUE if to complain of parking lot ramp conflicts.
05981  *
05982  * \retval 0 on success.  The ramp_map is updated.
05983  * \retval -1 on failure.
05984  */
05985 static int usage_context_add_ramp(struct parking_dp_ramp_map *ramp_map, const char *exten, int exclusive, struct ast_parkinglot *lot, int complain)
05986 {
05987    struct parking_dp_ramp *cur_ramp;
05988    struct parking_dp_ramp *new_ramp;
05989    int cmp;
05990 
05991    /* Make sure that exclusive is only 0 or 1 */
05992    if (exclusive) {
05993       exclusive = 1;
05994    }
05995 
05996    AST_LIST_TRAVERSE_SAFE_BEGIN(ramp_map, cur_ramp, node) {
05997       cmp = strcmp(exten, cur_ramp->exten);
05998       if (cmp > 0) {
05999          /* The parking lot ramp goes after this node. */
06000          continue;
06001       }
06002       if (cmp == 0) {
06003          /* The ramp is already in the map. */
06004          if (complain && (cur_ramp->exclusive || exclusive)) {
06005             ast_log(LOG_WARNING,
06006                "Parking lot '%s' parkext %s@%s used by another parking lot.\n",
06007                lot->name, exten, lot->cfg.parking_con);
06008          }
06009          return 0;
06010       }
06011       /* The new parking lot ramp goes before this node. */
06012       new_ramp = build_dialplan_useage_ramp(exten, exclusive);
06013       if (!new_ramp) {
06014          return -1;
06015       }
06016       AST_LIST_INSERT_BEFORE_CURRENT(new_ramp, node);
06017       return 0;
06018    }
06019    AST_LIST_TRAVERSE_SAFE_END;
06020 
06021    /* New parking lot access ramp goes on the end. */
06022    new_ramp = build_dialplan_useage_ramp(exten, exclusive);
06023    if (!new_ramp) {
06024       return -1;
06025    }
06026    AST_LIST_INSERT_TAIL(ramp_map, new_ramp, node);
06027    return 0;
06028 }
06029 
06030 /*!
06031  * \internal
06032  * \brief Create a new parking lot spaces dialplan usage node.
06033  *
06034  * \param start First parking lot space to add.
06035  * \param stop Last parking lot space to add.
06036  *
06037  * \retval New usage ramp node on success.
06038  * \retval NULL on error.
06039  */
06040 static struct parking_dp_spaces *build_dialplan_useage_spaces(int start, int stop)
06041 {
06042    struct parking_dp_spaces *spaces_node;
06043 
06044    spaces_node = ast_calloc(1, sizeof(*spaces_node));
06045    if (!spaces_node) {
06046       return NULL;
06047    }
06048    spaces_node->start = start;
06049    spaces_node->stop = stop;
06050    return spaces_node;
06051 }
06052 
06053 /*!
06054  * \internal
06055  * \brief Add parking lot spaces to the context space usage map.
06056  *
06057  * \param space_map Current parking lot context space usage map.
06058  * \param start First parking lot space to add.
06059  * \param stop Last parking lot space to add.
06060  * \param lot Parking lot supplying reference data.
06061  * \param complain TRUE if to complain of parking lot spaces conflicts.
06062  *
06063  * \retval 0 on success.  The space_map is updated.
06064  * \retval -1 on failure.
06065  */
06066 static int usage_context_add_spaces(struct parking_dp_space_map *space_map, int start, int stop, struct ast_parkinglot *lot, int complain)
06067 {
06068    struct parking_dp_spaces *cur_node;
06069    struct parking_dp_spaces *expand_node;
06070    struct parking_dp_spaces *new_node;
06071 
06072    expand_node = NULL;
06073    AST_LIST_TRAVERSE_SAFE_BEGIN(space_map, cur_node, node) {
06074       /* NOTE: stop + 1 to combine immediately adjacent nodes into one. */
06075       if (expand_node) {
06076          /* The previous node is expanding to possibly eat following nodes. */
06077          if (expand_node->stop + 1 < cur_node->start) {
06078             /* Current node is completely after expanding node. */
06079             return 0;
06080          }
06081 
06082          if (complain
06083             && ((cur_node->start <= start && start <= cur_node->stop)
06084                || (cur_node->start <= stop && stop <= cur_node->stop)
06085                || (start < cur_node->start && cur_node->stop < stop))) {
06086             /* Only complain once per range add. */
06087             complain = 0;
06088             ast_log(LOG_WARNING,
06089                "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
06090                lot->name, start, stop, lot->cfg.parking_con);
06091          }
06092 
06093          /* Current node is eaten by the expanding node. */
06094          if (expand_node->stop < cur_node->stop) {
06095             expand_node->stop = cur_node->stop;
06096          }
06097          AST_LIST_REMOVE_CURRENT(node);
06098          ast_free(cur_node);
06099          continue;
06100       }
06101 
06102       if (cur_node->stop + 1 < start) {
06103          /* New range is completely after current node. */
06104          continue;
06105       }
06106       if (stop + 1 < cur_node->start) {
06107          /* New range is completely before current node. */
06108          new_node = build_dialplan_useage_spaces(start, stop);
06109          if (!new_node) {
06110             return -1;
06111          }
06112          AST_LIST_INSERT_BEFORE_CURRENT(new_node, node);
06113          return 0;
06114       }
06115 
06116       if (complain
06117          && ((cur_node->start <= start && start <= cur_node->stop)
06118             || (cur_node->start <= stop && stop <= cur_node->stop)
06119             || (start < cur_node->start && cur_node->stop < stop))) {
06120          /* Only complain once per range add. */
06121          complain = 0;
06122          ast_log(LOG_WARNING,
06123             "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
06124             lot->name, start, stop, lot->cfg.parking_con);
06125       }
06126 
06127       /* Current node range overlaps or is immediately adjacent to new range. */
06128       if (start < cur_node->start) {
06129          /* Expand the current node in the front. */
06130          cur_node->start = start;
06131       }
06132       if (stop <= cur_node->stop) {
06133          /* Current node is not expanding in the rear. */
06134          return 0;
06135       }
06136       cur_node->stop = stop;
06137       expand_node = cur_node;
06138    }
06139    AST_LIST_TRAVERSE_SAFE_END;
06140 
06141    if (expand_node) {
06142       /*
06143        * The previous node expanded and either ate all following nodes
06144        * or it was the last node.
06145        */
06146       return 0;
06147    }
06148 
06149    /* New range goes on the end. */
06150    new_node = build_dialplan_useage_spaces(start, stop);
06151    if (!new_node) {
06152       return -1;
06153    }
06154    AST_LIST_INSERT_TAIL(space_map, new_node, node);
06155    return 0;
06156 }
06157 
06158 /*!
06159  * \internal
06160  * \brief Add parking lot spaces to the context dialplan usage node.
06161  *
06162  * \param ctx_node Usage node to add parking lot spaces.
06163  * \param lot Parking lot to add data to ctx_node.
06164  * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
06165  *
06166  * \retval 0 on success.
06167  * \retval -1 on error.
06168  */
06169 static int dialplan_usage_add_parkinglot_data(struct parking_dp_context *ctx_node, struct ast_parkinglot *lot, int complain)
06170 {
06171    if (usage_context_add_ramp(&ctx_node->access_extens, lot->cfg.parkext,
06172       lot->cfg.parkext_exclusive, lot, complain)) {
06173       return -1;
06174    }
06175    if (usage_context_add_spaces(&ctx_node->spaces, lot->cfg.parking_start,
06176       lot->cfg.parking_stop, lot, complain)) {
06177       return -1;
06178    }
06179    if (lot->cfg.parkaddhints
06180       && usage_context_add_spaces(&ctx_node->hints, lot->cfg.parking_start,
06181          lot->cfg.parking_stop, lot, 0)) {
06182       return -1;
06183    }
06184    return 0;
06185 }
06186 
06187 /*!
06188  * \internal
06189  * \brief Create a new parking lot context dialplan usage node.
06190  *
06191  * \param lot Parking lot to create a new dialplan usage from.
06192  *
06193  * \retval New usage context node on success.
06194  * \retval NULL on error.
06195  */
06196 static struct parking_dp_context *build_dialplan_useage_context(struct ast_parkinglot *lot)
06197 {
06198    struct parking_dp_context *ctx_node;
06199 
06200    ctx_node = ast_calloc(1, sizeof(*ctx_node) + strlen(lot->cfg.parking_con));
06201    if (!ctx_node) {
06202       return NULL;
06203    }
06204    if (dialplan_usage_add_parkinglot_data(ctx_node, lot, 0)) {
06205       destroy_dialplan_usage_context(ctx_node);
06206       return NULL;
06207    }
06208    strcpy(ctx_node->context, lot->cfg.parking_con);
06209    return ctx_node;
06210 }
06211 
06212 /*!
06213  * \internal
06214  * \brief Add the given parking lot dialplan usage to the dialplan usage map.
06215  *
06216  * \param usage_map Parking lot usage map to add the given parking lot.
06217  * \param lot Parking lot to add dialplan usage.
06218  * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
06219  *
06220  * \retval 0 on success.
06221  * \retval -1 on error.
06222  */
06223 static int dialplan_usage_add_parkinglot(struct parking_dp_map *usage_map, struct ast_parkinglot *lot, int complain)
06224 {
06225    struct parking_dp_context *cur_ctx;
06226    struct parking_dp_context *new_ctx;
06227    int cmp;
06228 
06229    AST_LIST_TRAVERSE_SAFE_BEGIN(usage_map, cur_ctx, node) {
06230       cmp = strcmp(lot->cfg.parking_con, cur_ctx->context);
06231       if (cmp > 0) {
06232          /* The parking lot context goes after this node. */
06233          continue;
06234       }
06235       if (cmp == 0) {
06236          /* This is the node we will add parking lot spaces to the map. */
06237          return dialplan_usage_add_parkinglot_data(cur_ctx, lot, complain);
06238       }
06239       /* The new parking lot context goes before this node. */
06240       new_ctx = build_dialplan_useage_context(lot);
06241       if (!new_ctx) {
06242          return -1;
06243       }
06244       AST_LIST_INSERT_BEFORE_CURRENT(new_ctx, node);
06245       return 0;
06246    }
06247    AST_LIST_TRAVERSE_SAFE_END;
06248 
06249    /* New parking lot context goes on the end. */
06250    new_ctx = build_dialplan_useage_context(lot);
06251    if (!new_ctx) {
06252       return -1;
06253    }
06254    AST_LIST_INSERT_TAIL(usage_map, new_ctx, node);
06255    return 0;
06256 }
06257 
06258 /*!
06259  * \internal
06260  * \brief Build the dialplan usage map of the current parking lot container.
06261  *
06262  * \param usage_map Parking lot usage map.  Must already be initialized.
06263  * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
06264  *
06265  * \retval 0 on success.  The usage_map is filled in.
06266  * \retval -1 on failure.  Built usage_map is incomplete.
06267  */
06268 static int build_dialplan_useage_map(struct parking_dp_map *usage_map, int complain)
06269 {
06270    int status = 0;
06271    struct ao2_iterator iter;
06272    struct ast_parkinglot *curlot;
06273 
06274    /* For all parking lots */
06275    iter = ao2_iterator_init(parkinglots, 0);
06276    for (; (curlot = ao2_iterator_next(&iter)); ao2_ref(curlot, -1)) {
06277       /* Add the parking lot to the map. */
06278       if (dialplan_usage_add_parkinglot(usage_map, curlot, complain)) {
06279          ao2_ref(curlot, -1);
06280          status = -1;
06281          break;
06282       }
06283    }
06284    ao2_iterator_destroy(&iter);
06285 
06286    return status;
06287 }
06288 
06289 /*!
06290  * \internal
06291  * \brief Remove the given extension if it exists.
06292  *
06293  * \param context Dialplan database context name.
06294  * \param exten Extension to remove.
06295  * \param priority Extension priority to remove.
06296  *
06297  * \return Nothing
06298  */
06299 static void remove_exten_if_exist(const char *context, const char *exten, int priority)
06300 {
06301    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
06302 
06303    if (pbx_find_extension(NULL, NULL, &q, context, exten, priority, NULL, NULL,
06304       E_MATCH)) {
06305       ast_debug(1, "Removing unneeded parking lot exten: %s@%s priority:%d\n",
06306          context, exten, priority);
06307       ast_context_remove_extension(context, exten, priority, registrar);
06308    }
06309 }
06310 
06311 /*!
06312  * \internal
06313  * \brief Remove unused parking lot access ramp items.
06314  *
06315  * \param context Dialplan database context name.
06316  * \param old_ramps Before configuration reload access ramp usage map.
06317  * \param new_ramps After configuration reload access ramp usage map.
06318  *
06319  * \details
06320  * Remove access ramp items that were in the old context but not in the
06321  * new context.
06322  *
06323  * \return Nothing
06324  */
06325 static void remove_dead_ramp_usage(const char *context, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
06326 {
06327    struct parking_dp_ramp *old_ramp;
06328    struct parking_dp_ramp *new_ramp;
06329    int cmp;
06330 
06331    old_ramp = AST_LIST_FIRST(old_ramps);
06332    new_ramp = AST_LIST_FIRST(new_ramps);
06333 
06334    while (new_ramp) {
06335       if (!old_ramp) {
06336          /* No old ramps left, so no dead ramps can remain. */
06337          return;
06338       }
06339       cmp = strcmp(old_ramp->exten, new_ramp->exten);
06340       if (cmp < 0) {
06341          /* New map does not have old ramp. */
06342          remove_exten_if_exist(context, old_ramp->exten, 1);
06343          old_ramp = AST_LIST_NEXT(old_ramp, node);
06344          continue;
06345       }
06346       if (cmp == 0) {
06347          /* Old and new map have this ramp. */
06348          old_ramp = AST_LIST_NEXT(old_ramp, node);
06349       } else {
06350          /* Old map does not have new ramp. */
06351       }
06352       new_ramp = AST_LIST_NEXT(new_ramp, node);
06353    }
06354 
06355    /* Any old ramps left must be dead. */
06356    for (; old_ramp; old_ramp = AST_LIST_NEXT(old_ramp, node)) {
06357       remove_exten_if_exist(context, old_ramp->exten, 1);
06358    }
06359 }
06360 
06361 /*!
06362  * \internal
06363  * \brief Destroy the given parking space.
06364  *
06365  * \param context Dialplan database context name.
06366  * \param space Parking space.
06367  *
06368  * \return Nothing
06369  */
06370 static void destroy_space(const char *context, int space)
06371 {
06372    char exten[AST_MAX_EXTENSION];
06373 
06374    /* Destroy priorities of the parking space that we registered. */
06375    snprintf(exten, sizeof(exten), "%d", space);
06376    remove_exten_if_exist(context, exten, PRIORITY_HINT);
06377    remove_exten_if_exist(context, exten, 1);
06378 }
06379 
06380 /*!
06381  * \internal
06382  * \brief Remove unused parking lot space items.
06383  *
06384  * \param context Dialplan database context name.
06385  * \param old_spaces Before configuration reload parking space usage map.
06386  * \param new_spaces After configuration reload parking space usage map.
06387  * \param destroy_space Function to destroy parking space item.
06388  *
06389  * \details
06390  * Remove parking space items that were in the old context but
06391  * not in the new context.
06392  *
06393  * \return Nothing
06394  */
06395 static void remove_dead_spaces_usage(const char *context,
06396    struct parking_dp_space_map *old_spaces, struct parking_dp_space_map *new_spaces,
06397    void (*destroy_space)(const char *context, int space))
06398 {
06399    struct parking_dp_spaces *old_range;
06400    struct parking_dp_spaces *new_range;
06401    int space;/*!< Current position in the current old range. */
06402    int stop;
06403 
06404    old_range = AST_LIST_FIRST(old_spaces);
06405    new_range = AST_LIST_FIRST(new_spaces);
06406    space = -1;
06407 
06408    while (old_range) {
06409       if (space < old_range->start) {
06410          space = old_range->start;
06411       }
06412       if (new_range) {
06413          if (space < new_range->start) {
06414             /* Current position in old range starts before new range. */
06415             if (old_range->stop < new_range->start) {
06416                /* Old range ends before new range. */
06417                stop = old_range->stop;
06418                old_range = AST_LIST_NEXT(old_range, node);
06419             } else {
06420                /* Tail of old range overlaps new range. */
06421                stop = new_range->start - 1;
06422             }
06423          } else if (/* new_range->start <= space && */ space <= new_range->stop) {
06424             /* Current position in old range overlaps new range. */
06425             if (old_range->stop <= new_range->stop) {
06426                /* Old range ends at or before new range. */
06427                old_range = AST_LIST_NEXT(old_range, node);
06428             } else {
06429                /* Old range extends beyond end of new range. */
06430                space = new_range->stop + 1;
06431                new_range = AST_LIST_NEXT(new_range, node);
06432             }
06433             continue;
06434          } else /* if (new_range->stop < space) */ {
06435             /* Current position in old range starts after new range. */
06436             new_range = AST_LIST_NEXT(new_range, node);
06437             continue;
06438          }
06439       } else {
06440          /* No more new ranges.  All remaining old spaces are dead. */
06441          stop = old_range->stop;
06442          old_range = AST_LIST_NEXT(old_range, node);
06443       }
06444 
06445       /* Destroy dead parking spaces. */
06446       for (; space <= stop; ++space) {
06447          destroy_space(context, space);
06448       }
06449    }
06450 }
06451 
06452 /*!
06453  * \internal
06454  * \brief Remove unused parking lot context items.
06455  *
06456  * \param context Dialplan database context name.
06457  * \param old_ctx Before configuration reload context usage map.
06458  * \param new_ctx After configuration reload context usage map.
06459  *
06460  * \details
06461  * Remove context usage items that were in the old context but not in the
06462  * new context.
06463  *
06464  * \return Nothing
06465  */
06466 static void remove_dead_context_usage(const char *context, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
06467 {
06468    remove_dead_ramp_usage(context, &old_ctx->access_extens, &new_ctx->access_extens);
06469    remove_dead_spaces_usage(context, &old_ctx->spaces, &new_ctx->spaces, destroy_space);
06470 #if 0
06471    /* I don't think we should destroy hints if the parking space still exists. */
06472    remove_dead_spaces_usage(context, &old_ctx->hints, &new_ctx->hints, destroy_space_hint);
06473 #endif
06474 }
06475 
06476 /*!
06477  * \internal
06478  * \brief Remove unused parking lot dialplan items.
06479  *
06480  * \param old_map Before configuration reload dialplan usage map.
06481  * \param new_map After configuration reload dialplan usage map.
06482  *
06483  * \details
06484  * Remove dialplan items that were in the old map but not in the
06485  * new map.
06486  *
06487  * \return Nothing
06488  */
06489 static void remove_dead_dialplan_useage(struct parking_dp_map *old_map, struct parking_dp_map *new_map)
06490 {
06491    struct parking_dp_context *old_ctx;
06492    struct parking_dp_context *new_ctx;
06493    struct ast_context *con;
06494    int cmp;
06495 
06496    old_ctx = AST_LIST_FIRST(old_map);
06497    new_ctx = AST_LIST_FIRST(new_map);
06498 
06499    while (new_ctx) {
06500       if (!old_ctx) {
06501          /* No old contexts left, so no dead stuff can remain. */
06502          return;
06503       }
06504       cmp = strcmp(old_ctx->context, new_ctx->context);
06505       if (cmp < 0) {
06506          /* New map does not have old map context. */
06507          con = ast_context_find(old_ctx->context);
06508          if (con) {
06509             ast_context_destroy(con, registrar);
06510          }
06511          old_ctx = AST_LIST_NEXT(old_ctx, node);
06512          continue;
06513       }
06514       if (cmp == 0) {
06515          /* Old and new map have this context. */
06516          remove_dead_context_usage(old_ctx->context, old_ctx, new_ctx);
06517          old_ctx = AST_LIST_NEXT(old_ctx, node);
06518       } else {
06519          /* Old map does not have new map context. */
06520       }
06521       new_ctx = AST_LIST_NEXT(new_ctx, node);
06522    }
06523 
06524    /* Any old contexts left must be dead. */
06525    for (; old_ctx; old_ctx = AST_LIST_NEXT(old_ctx, node)) {
06526       con = ast_context_find(old_ctx->context);
06527       if (con) {
06528          ast_context_destroy(con, registrar);
06529       }
06530    }
06531 }
06532 
06533 static int parkinglot_markall_cb(void *obj, void *arg, int flags)
06534 {
06535    struct ast_parkinglot *parkinglot = obj;
06536 
06537    parkinglot->the_mark = 1;
06538    return 0;
06539 }
06540 
06541 static int parkinglot_is_marked_cb(void *obj, void *arg, int flags)
06542 {
06543    struct ast_parkinglot *parkinglot = obj;
06544 
06545    if (parkinglot->the_mark) {
06546       if (AST_LIST_EMPTY(&parkinglot->parkings)) {
06547          /* This parking lot can actually be deleted. */
06548          return CMP_MATCH;
06549       }
06550       /* Try reloading later when parking lot is empty. */
06551       ast_log(LOG_WARNING,
06552          "Parking lot %s has parked calls.  Could not remove.\n",
06553          parkinglot->name);
06554       parkinglot->disabled = 1;
06555       force_reload_load = 1;
06556    }
06557 
06558    return 0;
06559 }
06560 
06561 static int parkinglot_activate_cb(void *obj, void *arg, int flags)
06562 {
06563    struct ast_parkinglot *parkinglot = obj;
06564 
06565    if (parkinglot->the_mark) {
06566       /*
06567        * Don't activate a parking lot that still bears the_mark since
06568        * it is effectively deleted.
06569        */
06570       return 0;
06571    }
06572 
06573    if (parkinglot_activate(parkinglot)) {
06574       /*
06575        * The parking lot failed to activate.  Allow reloading later to
06576        * see if that fixes it.
06577        */
06578       force_reload_load = 1;
06579       ast_log(LOG_WARNING, "Parking lot %s not open for business.\n", parkinglot->name);
06580    } else {
06581       ast_debug(1, "Parking lot %s now open for business. (parkpos %d-%d)\n",
06582          parkinglot->name, parkinglot->cfg.parking_start,
06583          parkinglot->cfg.parking_stop);
06584    }
06585 
06586    return 0;
06587 }
06588 
06589 static int load_config(int reload)
06590 {
06591    struct ast_flags config_flags = {
06592       reload && !force_reload_load ? CONFIG_FLAG_FILEUNCHANGED : 0 };
06593    struct ast_config *cfg;
06594    struct parking_dp_map old_usage_map = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
06595    struct parking_dp_map new_usage_map = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
06596 
06597    /* We are reloading now and have already determined if we will force the reload. */
06598    force_reload_load = 0;
06599 
06600    if (!default_parkinglot) {
06601       /* Must create the default default parking lot */
06602       default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
06603       if (!default_parkinglot) {
06604          ast_log(LOG_ERROR, "Configuration of default default parking lot failed.\n");
06605          return -1;
06606       }
06607       ast_debug(1, "Configuration of default default parking lot done.\n");
06608       parkinglot_addref(default_parkinglot);
06609    }
06610 
06611    cfg = ast_config_load2("features.conf", "features", config_flags);
06612    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
06613       /* No sense in asking for reload trouble if nothing changed. */
06614       ast_debug(1, "features.conf did not change.\n");
06615       return 0;
06616    }
06617    if (cfg == CONFIG_STATUS_FILEMISSING
06618       || cfg == CONFIG_STATUS_FILEINVALID) {
06619       ast_log(LOG_WARNING, "Could not load features.conf\n");
06620       return 0;
06621    }
06622 
06623    /* Save current parking lot dialplan needs. */
06624    if (build_dialplan_useage_map(&old_usage_map, 0)) {
06625       destroy_dialplan_usage_map(&old_usage_map);
06626 
06627       /* Allow reloading later to see if conditions have improved. */
06628       force_reload_load = 1;
06629       return -1;
06630    }
06631 
06632    ao2_t_callback(parkinglots, OBJ_NODATA, parkinglot_markall_cb, NULL,
06633       "callback to mark all parking lots");
06634    process_config(cfg);
06635    ast_config_destroy(cfg);
06636    ao2_t_callback(parkinglots, OBJ_NODATA | OBJ_UNLINK, parkinglot_is_marked_cb, NULL,
06637       "callback to remove marked parking lots");
06638 
06639    /* Save updated parking lot dialplan needs. */
06640    if (build_dialplan_useage_map(&new_usage_map, 1)) {
06641       /*
06642        * Yuck, if this failure caused any parking lot dialplan items
06643        * to be lost, they will likely remain lost until Asterisk is
06644        * restarted.
06645        */
06646       destroy_dialplan_usage_map(&old_usage_map);
06647       destroy_dialplan_usage_map(&new_usage_map);
06648       return -1;
06649    }
06650 
06651    /* Remove no longer needed parking lot dialplan usage. */
06652    remove_dead_dialplan_useage(&old_usage_map, &new_usage_map);
06653 
06654    destroy_dialplan_usage_map(&old_usage_map);
06655    destroy_dialplan_usage_map(&new_usage_map);
06656 
06657    ao2_t_callback(parkinglots, OBJ_NODATA, parkinglot_activate_cb, NULL,
06658       "callback to activate all parking lots");
06659 
06660    return 0;
06661 }
06662 
06663 /*!
06664  * \brief CLI command to list configured features
06665  * \param e
06666  * \param cmd
06667  * \param a
06668  *
06669  * \retval CLI_SUCCESS on success.
06670  * \retval NULL when tab completion is used.
06671  */
06672 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06673 {
06674    int i;
06675    struct ast_call_feature *feature;
06676    struct ao2_iterator iter;
06677    struct ast_parkinglot *curlot;
06678 #define HFS_FORMAT "%-25s %-7s %-7s\n"
06679 
06680    switch (cmd) {
06681    
06682    case CLI_INIT:
06683       e->command = "features show";
06684       e->usage =
06685          "Usage: features show\n"
06686          "       Lists configured features\n";
06687       return NULL;
06688    case CLI_GENERATE:
06689       return NULL;
06690    }
06691 
06692    ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
06693    ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
06694 
06695    ast_cli(a->fd, HFS_FORMAT, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
06696 
06697    ast_rwlock_rdlock(&features_lock);
06698    for (i = 0; i < FEATURES_COUNT; i++)
06699       ast_cli(a->fd, HFS_FORMAT, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
06700    ast_rwlock_unlock(&features_lock);
06701 
06702    ast_cli(a->fd, "\n");
06703    ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
06704    ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
06705    if (AST_RWLIST_EMPTY(&feature_list)) {
06706       ast_cli(a->fd, "(none)\n");
06707    } else {
06708       AST_RWLIST_RDLOCK(&feature_list);
06709       AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
06710          ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
06711       }
06712       AST_RWLIST_UNLOCK(&feature_list);
06713    }
06714 
06715    ast_cli(a->fd, "\nFeature Groups:\n");
06716    ast_cli(a->fd, "---------------\n");
06717    if (AST_RWLIST_EMPTY(&feature_groups)) {
06718       ast_cli(a->fd, "(none)\n");
06719    } else {
06720       struct feature_group *fg;
06721       struct feature_group_exten *fge;
06722 
06723       AST_RWLIST_RDLOCK(&feature_groups);
06724       AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
06725          ast_cli(a->fd, "===> Group: %s\n", fg->gname);
06726          AST_LIST_TRAVERSE(&fg->features, fge, entry) {
06727             ast_cli(a->fd, "===> --> %s (%s)\n", fge->feature->sname, fge->exten);
06728          }
06729       }
06730       AST_RWLIST_UNLOCK(&feature_groups);
06731    }
06732 
06733    iter = ao2_iterator_init(parkinglots, 0);
06734    while ((curlot = ao2_iterator_next(&iter))) {
06735       ast_cli(a->fd, "\nCall parking (Parking lot: %s)\n", curlot->name);
06736       ast_cli(a->fd, "------------\n");
06737       ast_cli(a->fd,"%-22s:      %s\n", "Parking extension", curlot->cfg.parkext);
06738       ast_cli(a->fd,"%-22s:      %s\n", "Parking context", curlot->cfg.parking_con);
06739       ast_cli(a->fd,"%-22s:      %d-%d\n", "Parked call extensions",
06740          curlot->cfg.parking_start, curlot->cfg.parking_stop);
06741       ast_cli(a->fd,"%-22s:      %d ms\n", "Parkingtime", curlot->cfg.parkingtime);
06742       ast_cli(a->fd,"%-22s:      %s\n", "Comeback to origin",
06743             (curlot->cfg.comebacktoorigin ? "yes" : "no"));
06744       ast_cli(a->fd,"%-22s:      %s%s\n", "Comeback context",
06745             curlot->cfg.comebackcontext, (curlot->cfg.comebacktoorigin ?
06746                " (comebacktoorigin=yes, not used)" : ""));
06747       ast_cli(a->fd,"%-22s:      %d\n", "Comeback dial time",
06748             curlot->cfg.comebackdialtime);
06749       ast_cli(a->fd,"%-22s:      %s\n", "MusicOnHold class", curlot->cfg.mohclass);
06750       ast_cli(a->fd,"%-22s:      %s\n", "Enabled", AST_CLI_YESNO(!curlot->disabled));
06751       ast_cli(a->fd,"\n");
06752       ao2_ref(curlot, -1);
06753    }
06754    ao2_iterator_destroy(&iter);
06755 
06756    return CLI_SUCCESS;
06757 }
06758 
06759 int ast_features_reload(void)
06760 {
06761    struct ast_context *con;
06762    int res;
06763 
06764    ast_mutex_lock(&features_reload_lock);/* Searialize reloading features.conf */
06765 
06766    /*
06767     * Always destroy the parking_con_dial context to remove buildup
06768     * of recalled extensions in the context.  At worst, the parked
06769     * call gets hungup attempting to run an invalid extension when
06770     * we are trying to callback the parker or the preset return
06771     * extension.  This is a small window of opportunity on an
06772     * execution chain that is not expected to happen very often.
06773     */
06774    con = ast_context_find(parking_con_dial);
06775    if (con) {
06776       ast_context_destroy(con, registrar);
06777    }
06778 
06779    res = load_config(1);
06780    ast_mutex_unlock(&features_reload_lock);
06781 
06782    return res;
06783 }
06784 
06785 static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06786 {
06787    switch (cmd) { 
06788    case CLI_INIT:
06789       e->command = "features reload";
06790       e->usage =
06791          "Usage: features reload\n"
06792          "       Reloads configured call features from features.conf\n";
06793       return NULL;
06794    case CLI_GENERATE:
06795       return NULL;
06796    }
06797    ast_features_reload();
06798 
06799    return CLI_SUCCESS;
06800 }
06801 
06802 /*!
06803  * \brief Actual bridge
06804  * \param chan
06805  * \param tmpchan
06806  * 
06807  * Stop hold music, lock both channels, masq channels,
06808  * after bridge return channel to next priority.
06809  */
06810 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
06811 {
06812    ast_moh_stop(chan);
06813    ast_channel_lock_both(chan, tmpchan);
06814    ast_setstate(tmpchan, chan->_state);
06815    tmpchan->readformat = chan->readformat;
06816    tmpchan->writeformat = chan->writeformat;
06817    ast_channel_unlock(chan);
06818    ast_channel_unlock(tmpchan);
06819 
06820    ast_channel_masquerade(tmpchan, chan);
06821 
06822    /* must be done without any channel locks held */
06823    ast_do_masquerade(tmpchan);
06824 
06825    /* when returning from bridge, the channel will continue at the next priority */
06826    ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
06827 }
06828 
06829 /*!
06830  * \brief Bridge channels together
06831  * \param s
06832  * \param m
06833  * 
06834  * Make sure valid channels were specified, 
06835  * send errors if any of the channels could not be found/locked, answer channels if needed,
06836  * create the placeholder channels and grab the other channels 
06837  * make the channels compatible, send error if we fail doing so 
06838  * setup the bridge thread object and start the bridge.
06839  * 
06840  * \retval 0 on success or on incorrect use.
06841  * \retval 1 on failure to bridge channels.
06842  */
06843 static int action_bridge(struct mansession *s, const struct message *m)
06844 {
06845    const char *channela = astman_get_header(m, "Channel1");
06846    const char *channelb = astman_get_header(m, "Channel2");
06847    const char *playtone = astman_get_header(m, "Tone");
06848    struct ast_channel *chana = NULL, *chanb = NULL, *chans[2];
06849    struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
06850    struct ast_bridge_thread_obj *tobj = NULL;
06851 
06852    /* make sure valid channels were specified */
06853    if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
06854       astman_send_error(s, m, "Missing channel parameter in request");
06855       return 0;
06856    }
06857 
06858    /* Start with chana */
06859    chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
06860 
06861    /* send errors if any of the channels could not be found/locked */
06862    if (!chana) {
06863       char buf[256];
06864       snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
06865       astman_send_error(s, m, buf);
06866       return 0;
06867    }
06868 
06869    /* Answer the channels if needed */
06870    if (chana->_state != AST_STATE_UP)
06871       ast_answer(chana);
06872 
06873    /* create the placeholder channels and grab the other channels */
06874    if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
06875       NULL, NULL, ast_channel_linkedid(chana), 0, "Bridge/%s", ast_channel_name(chana)))) {
06876       astman_send_error(s, m, "Unable to create temporary channel!");
06877       chana = ast_channel_unref(chana);
06878       return 1;
06879    }
06880 
06881    do_bridge_masquerade(chana, tmpchana);
06882 
06883    chana = ast_channel_unref(chana);
06884 
06885    /* now do chanb */
06886    chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
06887    /* send errors if any of the channels could not be found/locked */
06888    if (!chanb) {
06889       char buf[256];
06890       snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
06891       ast_hangup(tmpchana);
06892       astman_send_error(s, m, buf);
06893       return 0;
06894    }
06895 
06896    /* Answer the channels if needed */
06897    if (chanb->_state != AST_STATE_UP)
06898       ast_answer(chanb);
06899 
06900    /* create the placeholder channels and grab the other channels */
06901    if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
06902       NULL, NULL, ast_channel_linkedid(chanb), 0, "Bridge/%s", ast_channel_name(chanb)))) {
06903       astman_send_error(s, m, "Unable to create temporary channels!");
06904       ast_hangup(tmpchana);
06905       chanb = ast_channel_unref(chanb);
06906       return 1;
06907    }
06908 
06909    do_bridge_masquerade(chanb, tmpchanb);
06910 
06911    chanb = ast_channel_unref(chanb);
06912 
06913    /* make the channels compatible, send error if we fail doing so */
06914    if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
06915       ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", ast_channel_name(tmpchana), ast_channel_name(tmpchanb));
06916       astman_send_error(s, m, "Could not make channels compatible for manager bridge");
06917       ast_hangup(tmpchana);
06918       ast_hangup(tmpchanb);
06919       return 1;
06920    }
06921 
06922    /* setup the bridge thread object and start the bridge */
06923    if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
06924       ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", ast_channel_name(tmpchana), ast_channel_name(tmpchanb), strerror(errno));
06925       astman_send_error(s, m, "Unable to spawn a new bridge thread");
06926       ast_hangup(tmpchana);
06927       ast_hangup(tmpchanb);
06928       return 1;
06929    }
06930 
06931    tobj->chan = tmpchana;
06932    tobj->peer = tmpchanb;
06933    tobj->return_to_pbx = 1;
06934 
06935    if (ast_true(playtone)) {
06936       if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, ast_channel_language(tmpchanb))) {
06937          if (ast_waitstream(tmpchanb, "") < 0)
06938             ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", ast_channel_name(tmpchanb));
06939       }
06940    }
06941 
06942    chans[0] = tmpchana;
06943    chans[1] = tmpchanb;
06944 
06945    ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeAction", 2, chans,
06946             "Response: Success\r\n"
06947             "Channel1: %s\r\n"
06948             "Channel2: %s\r\n", ast_channel_name(tmpchana), ast_channel_name(tmpchanb));
06949 
06950    bridge_call_thread_launch(tobj);
06951 
06952    astman_send_ack(s, m, "Launched bridge thread with success");
06953 
06954    return 0;
06955 }
06956 
06957 /*!
06958  * \brief CLI command to list parked calls
06959  * \param e 
06960  * \param cmd
06961  * \param a
06962  *  
06963  * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
06964  * \retval CLI_SUCCESS on success.
06965  * \retval CLI_SHOWUSAGE on incorrect number of arguments.
06966  * \retval NULL when tab completion is used.
06967  */
06968 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06969 {
06970    struct parkeduser *cur;
06971    int numparked = 0;
06972    struct ao2_iterator iter;
06973    struct ast_parkinglot *curlot;
06974 
06975    switch (cmd) {
06976    case CLI_INIT:
06977       e->command = "parkedcalls show";
06978       e->usage =
06979          "Usage: parkedcalls show\n"
06980          "       List currently parked calls\n";
06981       return NULL;
06982    case CLI_GENERATE:
06983       return NULL;
06984    }
06985 
06986    if (a->argc > e->args)
06987       return CLI_SHOWUSAGE;
06988 
06989    ast_cli(a->fd, "%-10s %-25s (%-15s %-12s %4s) %s\n", "Num", "Channel",
06990       "Context", "Extension", "Pri", "Timeout");
06991 
06992    iter = ao2_iterator_init(parkinglots, 0);
06993    while ((curlot = ao2_iterator_next(&iter))) {
06994       int lotparked = 0;
06995 
06996       /* subtract ref for iterator and for configured parking lot */
06997       ast_cli(a->fd, "*** Parking lot: %s (%d)\n", curlot->name,
06998          ao2_ref(curlot, 0) - 2 - (curlot == default_parkinglot));
06999 
07000       AST_LIST_LOCK(&curlot->parkings);
07001       AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
07002          ast_cli(a->fd, "%-10.10s %-25s (%-15s %-12s %4d) %6lds\n",
07003             cur->parkingexten, ast_channel_name(cur->chan), cur->context, cur->exten,
07004             cur->priority,
07005             (long) (cur->start.tv_sec + (cur->parkingtime / 1000) - time(NULL)));
07006          ++lotparked;
07007       }
07008       AST_LIST_UNLOCK(&curlot->parkings);
07009       if (lotparked) {
07010          numparked += lotparked;
07011          ast_cli(a->fd, "   %d parked call%s in parking lot %s\n", lotparked,
07012             ESS(lotparked), curlot->name);
07013       }
07014 
07015       ao2_ref(curlot, -1);
07016    }
07017    ao2_iterator_destroy(&iter);
07018 
07019    ast_cli(a->fd, "---\n%d parked call%s in total.\n", numparked, ESS(numparked));
07020 
07021    return CLI_SUCCESS;
07022 }
07023 
07024 static struct ast_cli_entry cli_features[] = {
07025    AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
07026    AST_CLI_DEFINE(handle_features_reload, "Reloads configured features"),
07027    AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls"),
07028 };
07029 
07030 /*! 
07031  * \brief Dump parking lot status
07032  * \param s
07033  * \param m
07034  * 
07035  * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
07036  * \return Always RESULT_SUCCESS 
07037  */
07038 static int manager_parking_status(struct mansession *s, const struct message *m)
07039 {
07040    struct parkeduser *cur;
07041    const char *id = astman_get_header(m, "ActionID");
07042    char idText[256] = "";
07043    struct ao2_iterator iter;
07044    struct ast_parkinglot *curlot;
07045    int numparked = 0;
07046 
07047    if (!ast_strlen_zero(id))
07048       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
07049 
07050    astman_send_ack(s, m, "Parked calls will follow");
07051 
07052    iter = ao2_iterator_init(parkinglots, 0);
07053    while ((curlot = ao2_iterator_next(&iter))) {
07054       AST_LIST_LOCK(&curlot->parkings);
07055       AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
07056          astman_append(s, "Event: ParkedCall\r\n"
07057             "Parkinglot: %s\r\n"
07058             "Exten: %d\r\n"
07059             "Channel: %s\r\n"
07060             "From: %s\r\n"
07061             "Timeout: %ld\r\n"
07062             "CallerIDNum: %s\r\n"
07063             "CallerIDName: %s\r\n"
07064             "ConnectedLineNum: %s\r\n"
07065             "ConnectedLineName: %s\r\n"
07066             "%s"
07067             "\r\n",
07068             curlot->name,
07069             cur->parkingnum, ast_channel_name(cur->chan), cur->peername,
07070             (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
07071             S_COR(cur->chan->caller.id.number.valid, cur->chan->caller.id.number.str, ""),   /* XXX in other places it is <unknown> */
07072             S_COR(cur->chan->caller.id.name.valid, cur->chan->caller.id.name.str, ""),
07073             S_COR(cur->chan->connected.id.number.valid, cur->chan->connected.id.number.str, ""),   /* XXX in other places it is <unknown> */
07074             S_COR(cur->chan->connected.id.name.valid, cur->chan->connected.id.name.str, ""),
07075             idText);
07076          ++numparked;
07077       }
07078       AST_LIST_UNLOCK(&curlot->parkings);
07079       ao2_ref(curlot, -1);
07080    }
07081    ao2_iterator_destroy(&iter);
07082 
07083    astman_append(s,
07084       "Event: ParkedCallsComplete\r\n"
07085       "Total: %d\r\n"
07086       "%s"
07087       "\r\n",
07088       numparked, idText);
07089 
07090    return RESULT_SUCCESS;
07091 }
07092 
07093 /*!
07094  * \brief Create manager event for parked calls
07095  * \param s
07096  * \param m
07097  *
07098  * Get channels involved in park, create event.
07099  * \return Always 0
07100  *
07101  * \note ADSI is not compatible with this AMI action for the
07102  * same reason ch2 can no longer announce the parking space.
07103  */
07104 static int manager_park(struct mansession *s, const struct message *m)
07105 {
07106    const char *channel = astman_get_header(m, "Channel");
07107    const char *channel2 = astman_get_header(m, "Channel2");
07108    const char *timeout = astman_get_header(m, "Timeout");
07109    const char *parkinglotname = astman_get_header(m, "Parkinglot");
07110    char buf[BUFSIZ];
07111    int res = 0;
07112    struct ast_channel *ch1, *ch2;
07113    struct ast_park_call_args args = {
07114          /*
07115           * Don't say anything to ch2 since AMI is a third party parking
07116           * a call and we will likely crash if we do.
07117           *
07118           * XXX When the AMI action was originally implemented, the
07119           * parking space was announced to ch2.  Unfortunately, grabbing
07120           * the ch2 lock and holding it while the announcement is played
07121           * was not really a good thing to do to begin with since it
07122           * could hold up the system.  Also holding the lock is no longer
07123           * possible with a masquerade.
07124           *
07125           * Restoring the announcement to ch2 is not easily doable for
07126           * the following reasons:
07127           *
07128           * 1) The AMI manager is not the thread processing ch2.
07129           *
07130           * 2) ch2 could be the same as ch1, bridged to ch1, or some
07131           * random uninvolved channel.
07132           */
07133          .flags = AST_PARK_OPT_SILENCE,
07134       };
07135 
07136    if (ast_strlen_zero(channel)) {
07137       astman_send_error(s, m, "Channel not specified");
07138       return 0;
07139    }
07140 
07141    if (ast_strlen_zero(channel2)) {
07142       astman_send_error(s, m, "Channel2 not specified");
07143       return 0;
07144    }
07145 
07146    if (!ast_strlen_zero(timeout)) {
07147       if (sscanf(timeout, "%30d", &args.timeout) != 1) {
07148          astman_send_error(s, m, "Invalid timeout value.");
07149          return 0;
07150       }
07151    }
07152 
07153    if (!(ch1 = ast_channel_get_by_name(channel))) {
07154       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
07155       astman_send_error(s, m, buf);
07156       return 0;
07157    }
07158 
07159    if (!(ch2 = ast_channel_get_by_name(channel2))) {
07160       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
07161       astman_send_error(s, m, buf);
07162       ast_channel_unref(ch1);
07163       return 0;
07164    }
07165 
07166    if (!ast_strlen_zero(parkinglotname)) {
07167       args.parkinglot = find_parkinglot(parkinglotname);
07168    }
07169 
07170    res = masq_park_call(ch1, ch2, &args);
07171    if (!res) {
07172       ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
07173       astman_send_ack(s, m, "Park successful");
07174    } else {
07175       astman_send_error(s, m, "Park failure");
07176    }
07177 
07178    if (args.parkinglot) {
07179       parkinglot_unref(args.parkinglot);
07180    }
07181    ch1 = ast_channel_unref(ch1);
07182    ch2 = ast_channel_unref(ch2);
07183 
07184    return 0;
07185 }
07186 
07187 /*!
07188  * The presence of this datastore on the channel indicates that
07189  * someone is attemting to pickup or has picked up the channel.
07190  * The purpose is to prevent a race between two channels
07191  * attempting to pickup the same channel.
07192  */
07193 static const struct ast_datastore_info pickup_active = {
07194    .type = "pickup-active",
07195 };
07196 
07197 int ast_can_pickup(struct ast_channel *chan)
07198 {
07199    if (!chan->pbx && !chan->masq && !ast_test_flag(chan, AST_FLAG_ZOMBIE)
07200       && (chan->_state == AST_STATE_RINGING
07201          || chan->_state == AST_STATE_RING
07202          /*
07203           * Check the down state as well because some SIP devices do not
07204           * give 180 ringing when they can just give 183 session progress
07205           * instead.  Issue 14005.  (Some ISDN switches as well for that
07206           * matter.)
07207           */
07208          || chan->_state == AST_STATE_DOWN)
07209       && !ast_channel_datastore_find(chan, &pickup_active, NULL)) {
07210       return 1;
07211    }
07212    return 0;
07213 }
07214 
07215 static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
07216 {
07217    struct ast_channel *target = obj;/*!< Potential pickup target */
07218    struct ast_channel *chan = data;/*!< Channel wanting to pickup call */
07219 
07220    ast_channel_lock(target);
07221    if (chan != target && (chan->pickupgroup & target->callgroup)
07222       && ast_can_pickup(target)) {
07223       /* Return with the channel still locked on purpose */
07224       return CMP_MATCH | CMP_STOP;
07225    }
07226    ast_channel_unlock(target);
07227 
07228    return 0;
07229 }
07230 
07231 /*!
07232  * \brief Pickup a call
07233  * \param chan channel that initiated pickup.
07234  *
07235  * Walk list of channels, checking it is not itself, channel is pbx one,
07236  * check that the callgroup for both channels are the same and the channel is ringing.
07237  * Answer calling channel, flag channel as answered on queue, masq channels together.
07238  */
07239 int ast_pickup_call(struct ast_channel *chan)
07240 {
07241    struct ast_channel *target;/*!< Potential pickup target */
07242    int res = -1;
07243    ast_debug(1, "pickup attempt by %s\n", ast_channel_name(chan));
07244 
07245    /* The found channel is already locked. */
07246    target = ast_channel_callback(find_channel_by_group, NULL, chan, 0);
07247    if (target) {
07248       ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
07249 
07250       res = ast_do_pickup(chan, target);
07251       ast_channel_unlock(target);
07252       if (!res) {
07253          if (!ast_strlen_zero(pickupsound)) {
07254             pbx_builtin_setvar_helper(target, "BRIDGE_PLAY_SOUND", pickupsound);
07255          }
07256       } else {
07257          ast_log(LOG_WARNING, "pickup %s failed by %s\n", ast_channel_name(target), ast_channel_name(chan));
07258       }
07259       target = ast_channel_unref(target);
07260    }
07261 
07262    if (res < 0) {
07263       ast_debug(1, "No call pickup possible... for %s\n", ast_channel_name(chan));
07264       if (!ast_strlen_zero(pickupfailsound)) {
07265          ast_answer(chan);
07266          ast_stream_and_wait(chan, pickupfailsound, "");
07267       }
07268    }
07269 
07270    return res;
07271 }
07272 
07273 int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
07274 {
07275    struct ast_party_connected_line connected_caller;
07276    struct ast_channel *chans[2] = { chan, target };
07277    struct ast_datastore *ds_pickup;
07278    const char *chan_name;/*!< A masquerade changes channel names. */
07279    const char *target_name;/*!< A masquerade changes channel names. */
07280    int res = -1;
07281 
07282    target_name = ast_strdupa(ast_channel_name(target));
07283    ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, ast_channel_name(chan));
07284 
07285    /* Mark the target to block any call pickup race. */
07286    ds_pickup = ast_datastore_alloc(&pickup_active, NULL);
07287    if (!ds_pickup) {
07288       ast_log(LOG_WARNING,
07289          "Unable to create channel datastore on '%s' for call pickup\n", target_name);
07290       return -1;
07291    }
07292    ast_channel_datastore_add(target, ds_pickup);
07293 
07294    ast_party_connected_line_init(&connected_caller);
07295    ast_party_connected_line_copy(&connected_caller, &target->connected);
07296    ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */
07297    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
07298    if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
07299       ast_channel_update_connected_line(chan, &connected_caller, NULL);
07300    }
07301    ast_party_connected_line_free(&connected_caller);
07302 
07303    ast_channel_lock(chan);
07304    chan_name = ast_strdupa(ast_channel_name(chan));
07305    ast_connected_line_copy_from_caller(&connected_caller, &chan->caller);
07306    ast_channel_unlock(chan);
07307    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
07308    ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
07309    ast_party_connected_line_free(&connected_caller);
07310 
07311    ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan);
07312 
07313    if (ast_answer(chan)) {
07314       ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
07315       goto pickup_failed;
07316    }
07317 
07318    if (ast_queue_control(chan, AST_CONTROL_ANSWER)) {
07319       ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
07320       goto pickup_failed;
07321    }
07322    
07323    /* setting this flag to generate a reason header in the cancel message to the ringing channel */
07324    ast_set_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE);
07325 
07326    if (ast_channel_masquerade(target, chan)) {
07327       ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan_name,
07328          target_name);
07329       goto pickup_failed;
07330    }
07331 
07332    /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
07333    ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
07334       "Channel: %s\r\n"
07335       "TargetChannel: %s\r\n",
07336       chan_name, target_name);
07337 
07338    /* Do the masquerade manually to make sure that it is completed. */
07339    ast_do_masquerade(target);
07340    res = 0;
07341 
07342 pickup_failed:
07343    ast_channel_lock(target);
07344    if (!ast_channel_datastore_remove(target, ds_pickup)) {
07345       ast_datastore_free(ds_pickup);
07346    }
07347 
07348    return res;
07349 }
07350 
07351 static char *app_bridge = "Bridge";
07352 
07353 enum {
07354    BRIDGE_OPT_PLAYTONE = (1 << 0),
07355    OPT_CALLEE_HANGUP =  (1 << 1),
07356    OPT_CALLER_HANGUP =  (1 << 2),
07357    OPT_DURATION_LIMIT = (1 << 3),
07358    OPT_DURATION_STOP =  (1 << 4),
07359    OPT_CALLEE_TRANSFER = (1 << 5),
07360    OPT_CALLER_TRANSFER = (1 << 6),
07361    OPT_CALLEE_MONITOR = (1 << 7),
07362    OPT_CALLER_MONITOR = (1 << 8),
07363    OPT_CALLEE_PARK = (1 << 9),
07364    OPT_CALLER_PARK = (1 << 10),
07365    OPT_CALLEE_KILL = (1 << 11),
07366 };
07367  
07368 enum {
07369    OPT_ARG_DURATION_LIMIT = 0,
07370    OPT_ARG_DURATION_STOP,
07371    /* note: this entry _MUST_ be the last one in the enum */
07372    OPT_ARG_ARRAY_SIZE,
07373 };
07374 
07375 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
07376    AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE),
07377    AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
07378    AST_APP_OPTION('H', OPT_CALLER_HANGUP),
07379    AST_APP_OPTION('k', OPT_CALLEE_PARK),
07380    AST_APP_OPTION('K', OPT_CALLER_PARK),
07381    AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
07382    AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
07383    AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
07384    AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
07385    AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
07386    AST_APP_OPTION('W', OPT_CALLER_MONITOR),
07387    AST_APP_OPTION('x', OPT_CALLEE_KILL),
07388 END_OPTIONS );
07389 
07390 int ast_bridge_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
07391    char *parse, struct timeval *calldurationlimit)
07392 {
07393    char *stringp = ast_strdupa(parse);
07394    char *limit_str, *warning_str, *warnfreq_str;
07395    const char *var;
07396    int play_to_caller = 0, play_to_callee = 0;
07397    int delta;
07398 
07399    limit_str = strsep(&stringp, ":");
07400    warning_str = strsep(&stringp, ":");
07401    warnfreq_str = strsep(&stringp, ":");
07402 
07403    config->timelimit = atol(limit_str);
07404    if (warning_str)
07405       config->play_warning = atol(warning_str);
07406    if (warnfreq_str)
07407       config->warning_freq = atol(warnfreq_str);
07408 
07409    if (!config->timelimit) {
07410       ast_log(LOG_WARNING, "Bridge does not accept L(%s), hanging up.\n", limit_str);
07411       config->timelimit = config->play_warning = config->warning_freq = 0;
07412       config->warning_sound = NULL;
07413       return -1; /* error */
07414    } else if ( (delta = config->play_warning - config->timelimit) > 0) {
07415       int w = config->warning_freq;
07416 
07417       /*
07418        * If the first warning is requested _after_ the entire call
07419        * would end, and no warning frequency is requested, then turn
07420        * off the warning. If a warning frequency is requested, reduce
07421        * the 'first warning' time by that frequency until it falls
07422        * within the call's total time limit.
07423        *
07424        * Graphically:
07425        *                timelim->|    delta        |<-playwarning
07426        *      0__________________|_________________|
07427        *                       | w  |    |    |    |
07428        *
07429        * so the number of intervals to cut is 1+(delta-1)/w
07430        */
07431       if (w == 0) {
07432          config->play_warning = 0;
07433       } else {
07434          config->play_warning -= w * ( 1 + (delta-1)/w );
07435          if (config->play_warning < 1)
07436             config->play_warning = config->warning_freq = 0;
07437       }
07438    }
07439    
07440    ast_channel_lock(chan);
07441 
07442    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
07443    play_to_caller = var ? ast_true(var) : 1;
07444 
07445    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
07446    play_to_callee = var ? ast_true(var) : 0;
07447 
07448    if (!play_to_caller && !play_to_callee)
07449       play_to_caller = 1;
07450 
07451    var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
07452    config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
07453 
07454    /* The code looking at config wants a NULL, not just "", to decide
07455     * that the message should not be played, so we replace "" with NULL.
07456     * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
07457     * not found.
07458     */
07459 
07460    var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
07461    config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
07462 
07463    var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
07464    config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
07465 
07466    ast_channel_unlock(chan);
07467 
07468    /* undo effect of S(x) in case they are both used */
07469    calldurationlimit->tv_sec = 0;
07470    calldurationlimit->tv_usec = 0;
07471 
07472    /* more efficient to do it like S(x) does since no advanced opts */
07473    if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
07474       calldurationlimit->tv_sec = config->timelimit / 1000;
07475       calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
07476       ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
07477          calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
07478       config->timelimit = play_to_caller = play_to_callee =
07479       config->play_warning = config->warning_freq = 0;
07480    } else {
07481       ast_verb(4, "Limit Data for this call:\n");
07482       ast_verb(4, "timelimit      = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0);
07483       ast_verb(4, "play_warning   = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0);
07484       ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
07485       ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
07486       ast_verb(4, "warning_freq   = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0);
07487       ast_verb(4, "start_sound    = %s\n", S_OR(config->start_sound, ""));
07488       ast_verb(4, "warning_sound  = %s\n", config->warning_sound);
07489       ast_verb(4, "end_sound      = %s\n", S_OR(config->end_sound, ""));
07490    }
07491    if (play_to_caller)
07492       ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
07493    if (play_to_callee)
07494       ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
07495    return 0;
07496 }
07497 
07498 
07499 /*!
07500  * \brief Bridge channels
07501  * \param chan
07502  * \param data channel to bridge with.
07503  * 
07504  * Split data, check we aren't bridging with ourself, check valid channel,
07505  * answer call if not already, check compatible channels, setup bridge config
07506  * now bridge call, if transfered party hangs up return to PBX extension.
07507  */
07508 static int bridge_exec(struct ast_channel *chan, const char *data)
07509 {
07510    struct ast_channel *current_dest_chan, *final_dest_chan, *chans[2];
07511    char *tmp_data  = NULL;
07512    struct ast_flags opts = { 0, };
07513    struct ast_bridge_config bconfig = { { 0, }, };
07514    char *opt_args[OPT_ARG_ARRAY_SIZE];
07515    struct timeval calldurationlimit = { 0, };
07516 
07517    AST_DECLARE_APP_ARGS(args,
07518       AST_APP_ARG(dest_chan);
07519       AST_APP_ARG(options);
07520    );
07521    
07522    if (ast_strlen_zero(data)) {
07523       ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
07524       return -1;
07525    }
07526 
07527    tmp_data = ast_strdupa(data);
07528    AST_STANDARD_APP_ARGS(args, tmp_data);
07529    if (!ast_strlen_zero(args.options))
07530       ast_app_parse_options(bridge_exec_options, &opts, opt_args, args.options);
07531 
07532    /* avoid bridge with ourselves */
07533    if (!strcmp(ast_channel_name(chan), args.dest_chan)) {
07534       ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", ast_channel_name(chan));
07535       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
07536                "Response: Failed\r\n"
07537                "Reason: Unable to bridge channel to itself\r\n"
07538                "Channel1: %s\r\n"
07539                "Channel2: %s\r\n",
07540                ast_channel_name(chan), args.dest_chan);
07541       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
07542       return 0;
07543    }
07544 
07545    /* make sure we have a valid end point */
07546    if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
07547          strlen(args.dest_chan)))) {
07548       ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
07549          "cannot get its lock\n", args.dest_chan);
07550       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
07551                "Response: Failed\r\n"
07552                "Reason: Cannot grab end point\r\n"
07553                "Channel1: %s\r\n"
07554                "Channel2: %s\r\n", ast_channel_name(chan), args.dest_chan);
07555       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
07556       return 0;
07557    }
07558 
07559    /* answer the channel if needed */
07560    if (current_dest_chan->_state != AST_STATE_UP) {
07561       ast_answer(current_dest_chan);
07562    }
07563 
07564    /* try to allocate a place holder where current_dest_chan will be placed */
07565    if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
07566       NULL, NULL, ast_channel_linkedid(current_dest_chan), 0, "Bridge/%s", ast_channel_name(current_dest_chan)))) {
07567       ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
07568       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
07569                "Response: Failed\r\n"
07570                "Reason: cannot create placeholder\r\n"
07571                "Channel1: %s\r\n"
07572                "Channel2: %s\r\n", ast_channel_name(chan), args.dest_chan);
07573    }
07574 
07575    do_bridge_masquerade(current_dest_chan, final_dest_chan);
07576 
07577    chans[0] = current_dest_chan;
07578    chans[1] = final_dest_chan;
07579 
07580    /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
07581    /* try to make compatible, send error if we fail */
07582    if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
07583       ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", ast_channel_name(chan), ast_channel_name(final_dest_chan));
07584       ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
07585                "Response: Failed\r\n"
07586                "Reason: Could not make channels compatible for bridge\r\n"
07587                "Channel1: %s\r\n"
07588                "Channel2: %s\r\n", ast_channel_name(chan), ast_channel_name(final_dest_chan));
07589       ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
07590       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
07591       current_dest_chan = ast_channel_unref(current_dest_chan);
07592       return 0;
07593    }
07594 
07595    /* Report that the bridge will be successfull */
07596    ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
07597             "Response: Success\r\n"
07598             "Channel1: %s\r\n"
07599             "Channel2: %s\r\n", ast_channel_name(chan), ast_channel_name(final_dest_chan));
07600 
07601    /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */  
07602    if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
07603       if (!ast_streamfile(final_dest_chan, xfersound, ast_channel_language(final_dest_chan))) {
07604          if (ast_waitstream(final_dest_chan, "") < 0)
07605             ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", ast_channel_name(final_dest_chan));
07606       }
07607    }
07608    
07609    current_dest_chan = ast_channel_unref(current_dest_chan);
07610    
07611    if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
07612       if (ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
07613          goto done;
07614    }
07615 
07616    if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER))
07617       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_REDIRECT);
07618    if (ast_test_flag(&opts, OPT_CALLER_TRANSFER))
07619       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_REDIRECT);
07620    if (ast_test_flag(&opts, OPT_CALLEE_HANGUP))
07621       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
07622    if (ast_test_flag(&opts, OPT_CALLER_HANGUP))
07623       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
07624    if (ast_test_flag(&opts, OPT_CALLEE_MONITOR))
07625       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_AUTOMON);
07626    if (ast_test_flag(&opts, OPT_CALLER_MONITOR))
07627       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_AUTOMON);
07628    if (ast_test_flag(&opts, OPT_CALLEE_PARK))
07629       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_PARKCALL);
07630    if (ast_test_flag(&opts, OPT_CALLER_PARK))
07631       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_PARKCALL);
07632 
07633    ast_bridge_call(chan, final_dest_chan, &bconfig);
07634 
07635    /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
07636    pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
07637    if (!ast_check_hangup(final_dest_chan) && !ast_test_flag(&opts, OPT_CALLEE_KILL)) {
07638       ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
07639          final_dest_chan->context, final_dest_chan->exten,
07640          final_dest_chan->priority, ast_channel_name(final_dest_chan));
07641 
07642       if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
07643          ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", ast_channel_name(final_dest_chan));
07644          ast_hangup(final_dest_chan);
07645       } else
07646          ast_debug(1, "SUCCESS continuing PBX on chan %s\n", ast_channel_name(final_dest_chan));
07647    } else {
07648       ast_debug(1, "hangup chan %s since the other endpoint has hung up or the x flag was passed\n", ast_channel_name(final_dest_chan));
07649       ast_hangup(final_dest_chan);
07650    }
07651 done:
07652    if (bconfig.warning_sound) {
07653       ast_free((char *)bconfig.warning_sound);
07654    }
07655    if (bconfig.end_sound) {
07656       ast_free((char *)bconfig.end_sound);
07657    }
07658    if (bconfig.start_sound) {
07659       ast_free((char *)bconfig.start_sound);
07660    }
07661 
07662    return 0;
07663 }
07664 
07665 #if defined(TEST_FRAMEWORK)
07666 /*!
07667  * \internal
07668  * \brief Convert parking spaces map list to a comma separated string.
07669  *
07670  * \param str String buffer to fill.
07671  * \param spaces Parking spaces map list to convert.
07672  *
07673  * \return Nothing
07674  */
07675 static void create_spaces_str(struct ast_str **str, struct parking_dp_space_map *spaces)
07676 {
07677    const char *comma;
07678    struct parking_dp_spaces *cur;
07679 
07680    ast_str_reset(*str);
07681    comma = "";
07682    AST_LIST_TRAVERSE(spaces, cur, node) {
07683       if (cur->start == cur->stop) {
07684          ast_str_append(str, 0, "%s%d", comma, cur->start);
07685       } else {
07686          ast_str_append(str, 0, "%s%d-%d", comma, cur->start, cur->stop);
07687       }
07688       comma = ",";
07689    }
07690 }
07691 #endif   /* defined(TEST_FRAMEWORK) */
07692 
07693 #if defined(TEST_FRAMEWORK)
07694 /*!
07695  * \internal
07696  * \brief Compare parking spaces map to what is expected.
07697  *
07698  * \param test Unit test context.
07699  * \param spaces Parking spaces map list to check.
07700  * \param expected String to compare with.
07701  * \param what What is being compared.
07702  *
07703  * \retval 0 successful compare.
07704  * \retval nonzero if failed to compare.
07705  */
07706 static int check_spaces(struct ast_test *test, struct parking_dp_space_map *spaces, const char *expected, const char *what)
07707 {
07708    int cmp;
07709    struct ast_str *str = ast_str_alloca(1024);
07710 
07711    create_spaces_str(&str, spaces);
07712    cmp = strcmp(expected, ast_str_buffer(str));
07713    if (cmp) {
07714       ast_test_status_update(test,
07715          "Unexpected parking space map for %s. Expect:'%s' Got:'%s'\n",
07716          what, expected, ast_str_buffer(str));
07717    }
07718    return cmp;
07719 }
07720 #endif   /* defined(TEST_FRAMEWORK) */
07721 
07722 #if defined(TEST_FRAMEWORK)
07723 /*!
07724  * \internal
07725  * \brief Add a dead space to the dead spaces list.
07726  *
07727  * \param context Dead spaces list ptr pretending to be a context name ptr.
07728  * \param space Dead space to add to the list.
07729  *
07730  * \return Nothing
07731  */
07732 static void test_add_dead_space(const char *context, int space)
07733 {
07734    struct parking_dp_space_map *dead_spaces = (struct parking_dp_space_map *) context;
07735 
07736    usage_context_add_spaces(dead_spaces, space, space, NULL, 0);
07737 }
07738 #endif   /* defined(TEST_FRAMEWORK) */
07739 
07740 #if defined(TEST_FRAMEWORK)
07741 struct test_map {
07742    const char *ramp;
07743    int start;
07744    int stop;
07745    const char *expect;
07746 };
07747 
07748 /*!
07749  * \internal
07750  * \brief Build a parking lot dialplan usage test map from a table.
07751  *
07752  * \param test Unit test context.
07753  * \param lot Parking lot to use to build test usage map.
07754  * \param table_name Name of passed in table.
07755  * \param table Usage information to put in the usage map.
07756  * \param num_entries Number of entries in the table.
07757  *
07758  * \retval Created context node on success.
07759  * \retval NULL on error.
07760  */
07761 static struct parking_dp_context *test_build_maps(struct ast_test *test,
07762    struct ast_parkinglot *lot, const char *table_name, const struct test_map *table,
07763    size_t num_entries)
07764 {
07765    struct parking_dp_context *ctx_node;
07766    int cur_index = 0;
07767    char what[40];
07768 
07769    snprintf(what, sizeof(what), "%s[%d]", table_name, cur_index);
07770    ast_copy_string(lot->cfg.parkext, table->ramp, sizeof(lot->cfg.parkext));
07771    lot->cfg.parking_start = table->start;
07772    lot->cfg.parking_stop = table->stop;
07773    ctx_node = build_dialplan_useage_context(lot);
07774    if (!ctx_node) {
07775       ast_test_status_update(test, "Failed to create parking lot context map for %s\n",
07776          what);
07777       return NULL;
07778    }
07779    if (check_spaces(test, &ctx_node->spaces, table->expect, what)) {
07780       destroy_dialplan_usage_context(ctx_node);
07781       return NULL;
07782    }
07783    while (--num_entries) {
07784       ++cur_index;
07785       ++table;
07786       snprintf(what, sizeof(what), "%s[%d]", table_name, cur_index);
07787       ast_copy_string(lot->cfg.parkext, table->ramp, sizeof(lot->cfg.parkext));
07788       lot->cfg.parking_start = table->start;
07789       lot->cfg.parking_stop = table->stop;
07790       if (dialplan_usage_add_parkinglot_data(ctx_node, lot, 1)) {
07791          ast_test_status_update(test, "Failed to add parking lot data for %s\n", what);
07792          destroy_dialplan_usage_context(ctx_node);
07793          return NULL;
07794       }
07795       if (check_spaces(test, &ctx_node->spaces, table->expect, what)) {
07796          destroy_dialplan_usage_context(ctx_node);
07797          return NULL;
07798       }
07799    }
07800    return ctx_node;
07801 }
07802 
07803 static const struct test_map test_old_ctx[] = {
07804    /* The following order of building ctx is important to test adding items to the lists. */
07805    { "702", 14, 15, "14-15" },
07806    { "700", 10, 11, "10-11,14-15" },
07807    { "701", 18, 19, "10-11,14-15,18-19" },
07808    { "703", 12, 13, "10-15,18-19" },
07809    { "704", 16, 17, "10-19" },
07810 
07811    /* Parking ramp and space conflicts are intended with these lines. */
07812    { "704", 9, 19, "9-19" },
07813    { "704", 9, 20, "9-20" },
07814    { "704", 8, 21, "8-21" },
07815 
07816    /* Add more spaces to ctx to test removing dead parking spaces. */
07817    { "705", 23, 25, "8-21,23-25" },
07818    { "706", 28, 31, "8-21,23-25,28-31" },
07819    { "707", 33, 34, "8-21,23-25,28-31,33-34" },
07820    { "708", 38, 40, "8-21,23-25,28-31,33-34,38-40" },
07821    { "709", 42, 43, "8-21,23-25,28-31,33-34,38-40,42-43" },
07822 };
07823 
07824 static const struct test_map test_new_ctx[] = {
07825    { "702", 4, 5, "4-5" },
07826    { "704", 24, 26, "4-5,24-26" },
07827    { "709", 29, 30, "4-5,24-26,29-30" },
07828    { "710", 32, 35, "4-5,24-26,29-30,32-35" },
07829    { "711", 37, 39, "4-5,24-26,29-30,32-35,37-39" },
07830 };
07831 #endif   /* defined(TEST_FRAMEWORK) */
07832 
07833 #if defined(TEST_FRAMEWORK)
07834 /*!
07835  * \internal
07836  * \brief Test parking dialplan usage map code.
07837  *
07838  * \param test Unit test context.
07839  *
07840  * \retval 0 on success.
07841  * \retval -1 on error.
07842  */
07843 static int test_dialplan_usage_map(struct ast_test *test)
07844 {
07845    struct parking_dp_context *old_ctx;
07846    struct parking_dp_context *new_ctx;
07847    struct ast_parkinglot *lot;
07848    struct parking_dp_spaces *spaces;
07849    struct parking_dp_space_map dead_spaces = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07850    int res;
07851 
07852    ast_test_status_update(test, "Test parking dialplan usage map code\n");
07853 
07854    lot = create_parkinglot("test_lot");
07855    if (!lot) {
07856       return -1;
07857    }
07858    ast_copy_string(lot->cfg.parking_con, "test-ctx", sizeof(lot->cfg.parking_con));
07859    lot->cfg.parkext_exclusive = 1;
07860 
07861    ast_test_status_update(test,
07862       "Build old_ctx map\n");
07863    ast_log(LOG_NOTICE, "6 Ramp and space conflict warnings are expected.\n");
07864    old_ctx = test_build_maps(test, lot, "test_old_ctx", test_old_ctx,
07865       ARRAY_LEN(test_old_ctx));
07866    if (!old_ctx) {
07867       ao2_ref(lot, -1);
07868       return -1;
07869    }
07870 
07871    ast_test_status_update(test, "Build new_ctx map\n");
07872    new_ctx = test_build_maps(test, lot, "test_new_ctx", test_new_ctx,
07873       ARRAY_LEN(test_new_ctx));
07874    if (!new_ctx) {
07875       res = -1;
07876       goto fail_old_ctx;
07877    }
07878 
07879    ast_test_status_update(test, "Test removing dead parking spaces\n");
07880    remove_dead_spaces_usage((void *) &dead_spaces, &old_ctx->spaces,
07881       &new_ctx->spaces, test_add_dead_space);
07882    if (check_spaces(test, &dead_spaces, "8-21,23,28,31,40,42-43", "dead_spaces")) {
07883       res = -1;
07884       goto fail_dead_spaces;
07885    }
07886 
07887    res = 0;
07888 
07889 fail_dead_spaces:
07890    while ((spaces = AST_LIST_REMOVE_HEAD(&dead_spaces, node))) {
07891       ast_free(spaces);
07892    }
07893    destroy_dialplan_usage_context(new_ctx);
07894 
07895 fail_old_ctx:
07896    destroy_dialplan_usage_context(old_ctx);
07897    ao2_ref(lot, -1);
07898    return res;
07899 }
07900 #endif   /* defined(TEST_FRAMEWORK) */
07901 
07902 #if defined(TEST_FRAMEWORK)
07903 static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
07904 {
07905    return 0;
07906 }
07907 #endif   /* defined(TEST_FRAMEWORK) */
07908 
07909 #if defined(TEST_FRAMEWORK)
07910 static struct ast_channel *create_test_channel(const struct ast_channel_tech *fake_tech)
07911 {
07912    struct ast_channel *test_channel1;
07913    struct ast_format tmp_fmt;
07914 
07915    if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
07916       NULL, NULL, 0, 0, "TestChannel1"))) {
07917       ast_log(LOG_WARNING, "Whoa, test channel creation failed.\n");
07918       return NULL;
07919    }
07920 
07921    /* normally this is done in the channel driver */
07922    ast_format_cap_add(test_channel1->nativeformats, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0));
07923 
07924    ast_format_set(&test_channel1->writeformat, AST_FORMAT_GSM, 0);
07925    ast_format_set(&test_channel1->rawwriteformat, AST_FORMAT_GSM, 0);
07926    ast_format_set(&test_channel1->readformat, AST_FORMAT_GSM, 0);
07927    ast_format_set(&test_channel1->rawreadformat, AST_FORMAT_GSM, 0);
07928 
07929    test_channel1->tech = fake_tech;
07930 
07931    return test_channel1;
07932 }
07933 #endif   /* defined(TEST_FRAMEWORK) */
07934 
07935 #if defined(TEST_FRAMEWORK)
07936 static int unpark_test_channel(struct ast_channel *toremove, struct ast_park_call_args *args)
07937 {
07938    struct ast_context *con;
07939    struct parkeduser *pu_toremove;
07940    int res = 0;
07941 
07942    args->pu->notquiteyet = 1; /* go ahead and stop processing the test parking */
07943 
07944    AST_LIST_LOCK(&args->pu->parkinglot->parkings);
07945    AST_LIST_TRAVERSE_SAFE_BEGIN(&args->pu->parkinglot->parkings, pu_toremove, list) {
07946       if (pu_toremove == args->pu) {
07947          AST_LIST_REMOVE_CURRENT(list);
07948          break;
07949       }
07950    }
07951    AST_LIST_TRAVERSE_SAFE_END;
07952    AST_LIST_UNLOCK(&args->pu->parkinglot->parkings);
07953 
07954    if (!pu_toremove) {
07955       ast_log(LOG_WARNING, "Whoa, could not find parking test call!\n");
07956       return -1;
07957    }
07958 
07959    con = ast_context_find(args->pu->parkinglot->cfg.parking_con);
07960    if (con) {
07961       if (ast_context_remove_extension2(con, args->pu->parkingexten, 1, NULL, 0)) {
07962          ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
07963          res = -1;
07964       } else {
07965          notify_metermaids(args->pu->parkingexten,
07966             pu_toremove->parkinglot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
07967       }
07968    } else {
07969       ast_log(LOG_WARNING, "Whoa, no parking context?\n");
07970       res = -1;
07971    }
07972 
07973    parkinglot_unref(pu_toremove->parkinglot);
07974    ast_free(pu_toremove);
07975    args->pu = NULL;
07976 
07977    if (!res && toremove) {
07978       ast_hangup(toremove);
07979    }
07980    return res;
07981 }
07982 #endif   /* defined(TEST_FRAMEWORK) */
07983 
07984 #if defined(TEST_FRAMEWORK)
07985 AST_TEST_DEFINE(features_test)
07986 {
07987    struct ast_channel *test_channel1 = NULL;
07988    struct ast_channel *parked_chan = NULL;
07989    struct ast_parkinglot *dynlot;
07990    struct ast_park_call_args args = {
07991       .timeout = DEFAULT_PARK_TIME,
07992    };
07993 
07994    int res = 0;
07995 
07996    static const struct ast_channel_tech fake_tech = {
07997       .fixup = fake_fixup, /* silence warning from masquerade */
07998    };
07999 
08000    static const char unique_lot_1[] = "myuniquetestparkinglot314";
08001    static const char unique_lot_2[] = "myuniquetestparkinglot3141592654";
08002    static const char unique_context_1[] = "myuniquetestcontext314";
08003    static const char unique_context_2[] = "myuniquetestcontext3141592654";
08004    static const char parkinglot_parkext[] = "750";
08005    static const char parkinglot_range[] = "751-760";
08006 
08007    switch (cmd) {
08008    case TEST_INIT:
08009       info->name = "features_test";
08010       info->category = "/main/features/";
08011       info->summary = "Features unit test";
08012       info->description =
08013          "Tests whether parking respects PARKINGLOT settings";
08014       return AST_TEST_NOT_RUN;
08015    case TEST_EXECUTE:
08016       break;
08017    }
08018 
08019    if (test_dialplan_usage_map(test)) {
08020       res = -1;
08021       goto exit_features_test;
08022    }
08023 
08024    /* changing a config option is a bad practice, but must be done in this case */
08025    parkeddynamic = 1;
08026 
08027    ast_test_status_update(test, "Test parking functionality with defaults\n");
08028    if (!(test_channel1 = create_test_channel(&fake_tech))) {
08029       res = -1;
08030       goto exit_features_test;
08031    }
08032    if (park_call_full(test_channel1, NULL, &args)) {
08033       res = -1;
08034       goto exit_features_test;
08035    }
08036    if (unpark_test_channel(test_channel1, &args)) {
08037       res = -1;
08038       goto exit_features_test;
08039    }
08040 
08041 
08042    ast_test_status_update(test, "Check that certain parking options are respected\n");
08043    if (!(test_channel1 = create_test_channel(&fake_tech))) {
08044       res = -1;
08045       goto exit_features_test;
08046    }
08047    pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_lot_1);
08048    pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNCONTEXT", unique_context_1);
08049    pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNEXTEN", parkinglot_parkext);
08050    pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
08051    if (park_call_full(test_channel1, NULL, &args)) {
08052       res = -1;
08053       goto exit_features_test;
08054    }
08055    /* grab newly created parking lot for destruction in the end */
08056    dynlot = args.pu->parkinglot;
08057    if (args.pu->parkingnum != 751
08058       || strcmp(dynlot->name, unique_lot_1)
08059       || strcmp(dynlot->cfg.parking_con, unique_context_1)
08060       || strcmp(dynlot->cfg.parkext, parkinglot_parkext)
08061       || dynlot->cfg.parking_start != 751
08062       || dynlot->cfg.parking_stop != 760) {
08063       ast_test_status_update(test, "Parking settings were not respected\n");
08064       ast_test_status_update(test, "Dyn-name:%s\n", dynlot->name);
08065       ast_test_status_update(test, "Dyn-context:%s\n", dynlot->cfg.parking_con);
08066       ast_test_status_update(test, "Dyn-parkext:%s\n", dynlot->cfg.parkext);
08067       ast_test_status_update(test, "Dyn-parkpos:%d-%d\n", dynlot->cfg.parking_start,
08068          dynlot->cfg.parking_stop);
08069       ast_test_status_update(test, "Parked in space:%d\n", args.pu->parkingnum);
08070       if (!unpark_test_channel(test_channel1, &args)) {
08071          test_channel1 = NULL;
08072       }
08073       res = -1;
08074       goto exit_features_test;
08075    } else {
08076       ast_test_status_update(test, "Parking settings for non-masquerading park verified\n");
08077    }
08078    if (unpark_test_channel(test_channel1, &args)) {
08079       res = -1;
08080       goto exit_features_test;
08081    }
08082 
08083 
08084    ast_test_status_update(test, "Check #2 that certain parking options are respected\n");
08085    if (!(test_channel1 = create_test_channel(&fake_tech))) {
08086       res = -1;
08087       goto exit_features_test;
08088    }
08089    pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_lot_2);
08090    pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNCONTEXT", unique_context_2);
08091    pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNEXTEN", parkinglot_parkext);
08092    pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
08093    if (masq_park_call(test_channel1, NULL, &args)) {
08094       res = -1;
08095       goto exit_features_test;
08096    }
08097    /* hangup zombie channel */
08098    ast_hangup(test_channel1);
08099    test_channel1 = NULL;
08100 
08101    dynlot = args.pu->parkinglot;
08102    if (args.pu->parkingnum != 751
08103       || strcmp(dynlot->name, unique_lot_2)
08104       || strcmp(dynlot->cfg.parking_con, unique_context_2)
08105       || strcmp(dynlot->cfg.parkext, parkinglot_parkext)
08106       || dynlot->cfg.parking_start != 751
08107       || dynlot->cfg.parking_stop != 760) {
08108       ast_test_status_update(test, "Parking settings were not respected\n");
08109       ast_test_status_update(test, "Dyn-name:%s\n", dynlot->name);
08110       ast_test_status_update(test, "Dyn-context:%s\n", dynlot->cfg.parking_con);
08111       ast_test_status_update(test, "Dyn-parkext:%s\n", dynlot->cfg.parkext);
08112       ast_test_status_update(test, "Dyn-parkpos:%d-%d\n", dynlot->cfg.parking_start,
08113          dynlot->cfg.parking_stop);
08114       ast_test_status_update(test, "Parked in space:%d\n", args.pu->parkingnum);
08115       res = -1;
08116    } else {
08117       ast_test_status_update(test, "Parking settings for masquerading park verified\n");
08118    }
08119 
08120    /* find the real channel */
08121    parked_chan = ast_channel_get_by_name("TestChannel1");
08122    if (unpark_test_channel(parked_chan, &args)) {
08123       if (parked_chan) {
08124          ast_hangup(parked_chan);
08125       }
08126       res = -1;
08127    }
08128 
08129 
08130 exit_features_test:
08131 
08132    if (test_channel1) {
08133       ast_hangup(test_channel1);
08134    }
08135 
08136    force_reload_load = 1;
08137    ast_features_reload();
08138    return res ? AST_TEST_FAIL : AST_TEST_PASS;
08139 }
08140 #endif   /* defined(TEST_FRAMEWORK) */
08141 
08142 int ast_features_init(void)
08143 {
08144    int res;
08145 
08146    parkinglots = ao2_container_alloc(7, parkinglot_hash_cb, parkinglot_cmp_cb);
08147    if (!parkinglots) {
08148       return -1;
08149    }
08150 
08151    res = load_config(0);
08152    if (res) {
08153       return res;
08154    }
08155    ast_cli_register_multiple(cli_features, ARRAY_LEN(cli_features));
08156    ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
08157    ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
08158    res = ast_register_application2(parkedcall, parked_call_exec, NULL, NULL, NULL);
08159    if (!res)
08160       res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
08161    if (!res) {
08162       ast_manager_register_xml("ParkedCalls", 0, manager_parking_status);
08163       ast_manager_register_xml("Park", EVENT_FLAG_CALL, manager_park);
08164       ast_manager_register_xml("Bridge", EVENT_FLAG_CALL, action_bridge);
08165    }
08166 
08167    res |= ast_devstate_prov_add("Park", metermaidstate);
08168 #if defined(TEST_FRAMEWORK)
08169    res |= AST_TEST_REGISTER(features_test);
08170 #endif   /* defined(TEST_FRAMEWORK) */
08171 
08172    return res;
08173 }

Generated on Sat Feb 11 06:33:15 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6