Fri Apr 15 20:38:08 2016

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

Generated on 15 Apr 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1