Mon Jun 18 2012 03:55:33

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