Mon Mar 19 11:30:27 2012

Asterisk developer's documentation


features.c

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

Generated on Mon Mar 19 11:30:27 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7