Wed Apr 6 11:29:44 2011

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 #include "asterisk.h"
00027 
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 303138 $")
00029 
00030 #include "asterisk/_private.h"
00031 
00032 #include <pthread.h>
00033 #include <signal.h>
00034 #include <sys/time.h>
00035 #include <sys/signal.h>
00036 #include <netinet/in.h>
00037 
00038 #include "asterisk/lock.h"
00039 #include "asterisk/file.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/causes.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/translate.h"
00045 #include "asterisk/app.h"
00046 #include "asterisk/say.h"
00047 #include "asterisk/features.h"
00048 #include "asterisk/musiconhold.h"
00049 #include "asterisk/config.h"
00050 #include "asterisk/cli.h"
00051 #include "asterisk/manager.h"
00052 #include "asterisk/utils.h"
00053 #include "asterisk/adsi.h"
00054 #include "asterisk/devicestate.h"
00055 #include "asterisk/monitor.h"
00056 #include "asterisk/audiohook.h"
00057 #include "asterisk/global_datastores.h"
00058 #include "asterisk/astobj2.h"
00059 #include "asterisk/cel.h"
00060 #include "asterisk/test.h"
00061 
00062 /*
00063  * Party A - transferee
00064  * Party B - transferer
00065  * Party C - target of transfer
00066  *
00067  * DTMF attended transfer works within the channel bridge.
00068  * Unfortunately, when either party A or B in the channel bridge
00069  * hangs up, that channel is not completely hung up until the
00070  * transfer completes.  This is a real problem depending upon
00071  * the channel technology involved.
00072  *
00073  * For chan_dahdi, the channel is crippled until the hangup is
00074  * complete.  Either the channel is not useable (analog) or the
00075  * protocol disconnect messages are held up (PRI/BRI/SS7) and
00076  * the media is not released.
00077  *
00078  * For chan_sip, a call limit of one is going to block that
00079  * endpoint from any further calls until the hangup is complete.
00080  *
00081  * For party A this is a minor problem.  The party A channel
00082  * will only be in this condition while party B is dialing and
00083  * when party B and C are conferring.  The conversation between
00084  * party B and C is expected to be a short one.  Party B is
00085  * either asking a question of party C or announcing party A.
00086  * Also party A does not have much incentive to hangup at this
00087  * point.
00088  *
00089  * For party B this can be a major problem during a blonde
00090  * transfer.  (A blonde transfer is our term for an attended
00091  * transfer that is converted into a blind transfer. :))  Party
00092  * B could be the operator.  When party B hangs up, he assumes
00093  * that he is out of the original call entirely.  The party B
00094  * channel will be in this condition while party C is ringing,
00095  * while attempting to recall party B, and while waiting between
00096  * call attempts.
00097  *
00098  * WARNING:
00099  * The ATXFER_NULL_TECH conditional is a hack to fix the
00100  * problem.  It will replace the party B channel technology with
00101  * a NULL channel driver.  The consequences of this code is that
00102  * the 'h' extension will not be able to access any channel
00103  * technology specific information like SIP statistics for the
00104  * call.
00105  *
00106  * Uncomment the ATXFER_NULL_TECH define below to replace the
00107  * party B channel technology in the channel bridge to complete
00108  * hanging up the channel technology.
00109  */
00110 //#define ATXFER_NULL_TECH 1
00111 
00112 /*** DOCUMENTATION
00113    <application name="Bridge" language="en_US">
00114       <synopsis>
00115          Bridge two channels.
00116       </synopsis>
00117       <syntax>
00118          <parameter name="channel" required="true">
00119             <para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
00120          </parameter>
00121          <parameter name="options">
00122             <optionlist>
00123                <option name="p">
00124                   <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
00125                </option>
00126                <option name="h">
00127                   <para>Allow the called party to hang up by sending the
00128                   <replaceable>*</replaceable> DTMF digit.</para>
00129                </option>
00130                <option name="H">
00131                   <para>Allow the calling party to hang up by pressing the
00132                   <replaceable>*</replaceable> DTMF digit.</para>
00133                </option>
00134                <option name="k">
00135                   <para>Allow the called party to enable parking of the call by sending
00136                   the DTMF sequence defined for call parking in features.conf.</para>
00137                </option>
00138                <option name="K">
00139                   <para>Allow the calling party to enable parking of the call by sending
00140                    the DTMF sequence defined for call parking in features.conf.</para>
00141                </option>
00142                <option name="L(x[:y][:z])">
00143                   <para>Limit the call to <replaceable>x</replaceable> ms. Play a warning
00144                   when <replaceable>y</replaceable> ms are left. Repeat the warning every
00145                   <replaceable>z</replaceable> ms. The following special variables can be
00146                   used with this option:</para>
00147                   <variablelist>
00148                      <variable name="LIMIT_PLAYAUDIO_CALLER">
00149                         <para>Play sounds to the caller. yes|no (default yes)</para>
00150                      </variable>
00151                      <variable name="LIMIT_PLAYAUDIO_CALLEE">   
00152                         <para>Play sounds to the callee. yes|no</para>
00153                      </variable>
00154                      <variable name="LIMIT_TIMEOUT_FILE">
00155                         <para>File to play when time is up.</para>
00156                      </variable>
00157                      <variable name="LIMIT_CONNECT_FILE">
00158                         <para>File to play when call begins.</para>
00159                      </variable>
00160                      <variable name="LIMIT_WARNING_FILE">
00161                         <para>File to play as warning if <replaceable>y</replaceable> is
00162                         defined. The default is to say the time remaining.</para>
00163                      </variable>
00164                   </variablelist>
00165                </option>
00166                <option name="S(x)">
00167                   <para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
00168                </option>
00169                <option name="t">
00170                   <para>Allow the called party to transfer the calling party by sending the
00171                   DTMF sequence defined in features.conf.</para>
00172                </option>
00173                <option name="T">
00174                   <para>Allow the calling party to transfer the called party by sending the
00175                   DTMF sequence defined in features.conf.</para>
00176                </option>
00177                <option name="w">
00178                   <para>Allow the called party to enable recording of the call by sending
00179                   the DTMF sequence defined for one-touch recording in features.conf.</para>
00180                </option>
00181                <option name="W">
00182                   <para>Allow the calling party to enable recording of the call by sending
00183                   the DTMF sequence defined for one-touch recording in features.conf.</para>
00184                </option>
00185                <option name="x">
00186                   <para>Cause the called party to be hung up after the bridge, instead of being
00187                   restarted in the dialplan.</para>
00188                </option>
00189             </optionlist>
00190          </parameter>
00191       </syntax>
00192       <description>
00193          <para>Allows the ability to bridge two channels via the dialplan.</para>
00194          <para>This application sets the following channel variable upon completion:</para>
00195          <variablelist>
00196             <variable name="BRIDGERESULT">
00197                <para>The result of the bridge attempt as a text string.</para>
00198                <value name="SUCCESS" />
00199                <value name="FAILURE" />
00200                <value name="LOOP" />
00201                <value name="NONEXISTENT" />
00202                <value name="INCOMPATIBLE" />
00203             </variable>
00204          </variablelist>
00205       </description>
00206    </application>
00207    <application name="ParkedCall" language="en_US">
00208       <synopsis>
00209          Answer a parked call.
00210       </synopsis>
00211       <syntax>
00212          <parameter name="exten" required="true" />
00213       </syntax>
00214       <description>
00215          <para>Used to connect to a parked call. This application is always
00216          registered internally and does not need to be explicitly added
00217          into the dialplan, although you should include the <literal>parkedcalls</literal>
00218          context. If no extension is provided, then the first available
00219          parked call will be acquired.</para>
00220       </description>
00221       <see-also>
00222          <ref type="application">Park</ref>
00223          <ref type="application">ParkAndAnnounce</ref>
00224       </see-also>
00225    </application>
00226    <application name="Park" language="en_US">
00227       <synopsis>
00228          Park yourself.
00229       </synopsis>
00230       <syntax>
00231          <parameter name="timeout">
00232             <para>A custom parking timeout for this parked call. Value in milliseconds.</para>
00233          </parameter>
00234          <parameter name="return_context">
00235             <para>The context to return the call to after it times out.</para>
00236          </parameter>
00237          <parameter name="return_exten">
00238             <para>The extension to return the call to after it times out.</para>
00239          </parameter>
00240          <parameter name="return_priority">
00241             <para>The priority to return the call to after it times out.</para>
00242          </parameter>
00243          <parameter name="options">
00244             <para>A list of options for this parked call.</para>
00245             <optionlist>
00246                <option name="r">
00247                   <para>Send ringing instead of MOH to the parked call.</para>
00248                </option>
00249                <option name="R">
00250                   <para>Randomize the selection of a parking space.</para>
00251                </option>
00252                <option name="s">
00253                   <para>Silence announcement of the parking space number.</para>
00254                </option>
00255             </optionlist>
00256          </parameter>
00257       </syntax>
00258       <description>
00259          <para>Used to park yourself (typically in combination with a supervised
00260          transfer to know the parking space). This application is always
00261          registered internally and does not need to be explicitly added
00262          into the dialplan, although you should include the <literal>parkedcalls</literal>
00263          context (or the context specified in <filename>features.conf</filename>).</para>
00264          <para>If you set the <variable>PARKINGLOT</variable> variable, the call will be parked
00265          in the specifed parking context. Note setting this variable overrides the <variable>
00266          PARKINGLOT</variable> set by the <literal>CHANNEL</literal> function.</para>
00267          <para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
00268          parking context, Park() will park the call on that extension, unless
00269          it already exists. In that case, execution will continue at next priority.</para>
00270          <para>If you set the <variable>PARKINGLOT</variable> variable, Park() will park the call
00271          in that parkinglot.</para>
00272          <para>If you set the <variable>PARKINGDYNAMIC</variable> variable, this parkinglot from features.conf
00273          will be used as template for the newly created dynamic lot.</para>
00274          <para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable the newly created dynamic
00275          parking lot will use this context.</para>
00276          <para>If you set the <variable>PARKINGDYNPOS</variable> variable the newly created dynamic parkinglot
00277          will use those parking postitions.</para>
00278       </description>
00279       <see-also>
00280          <ref type="application">ParkAndAnnounce</ref>
00281          <ref type="application">ParkedCall</ref>
00282       </see-also>
00283    </application>
00284    <manager name="ParkedCalls" language="en_US">
00285       <synopsis>
00286          List parked calls.
00287       </synopsis>
00288       <syntax>
00289          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00290       </syntax>
00291       <description>
00292          <para>List parked calls.</para>
00293       </description>
00294    </manager>
00295    <manager name="Park" language="en_US">
00296       <synopsis>
00297          Park a channel.
00298       </synopsis>
00299       <syntax>
00300          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00301          <parameter name="Channel" required="true">
00302             <para>Channel name to park.</para>
00303          </parameter>
00304          <parameter name="Channel2" required="true">
00305             <para>Channel to announce park info to (and return to if timeout).</para>
00306          </parameter>
00307          <parameter name="Timeout">
00308             <para>Number of milliseconds to wait before callback.</para>
00309          </parameter>
00310          <parameter name="Parkinglot">
00311             <para>Parking lot to park channel in.</para>
00312          </parameter>
00313       </syntax>
00314       <description>
00315          <para>Park a channel.</para>
00316       </description>
00317    </manager>
00318    <manager name="Bridge" language="en_US">
00319       <synopsis>
00320          Bridge two channels already in the PBX.
00321       </synopsis>
00322       <syntax>
00323          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00324          <parameter name="Channel1" required="true">
00325             <para>Channel to Bridge to Channel2.</para>
00326          </parameter>
00327          <parameter name="Channel2" required="true">
00328             <para>Channel to Bridge to Channel1.</para>
00329          </parameter>
00330          <parameter name="Tone">
00331             <para>Play courtesy tone to Channel 2.</para>
00332             <enumlist>
00333                <enum name="yes" />
00334                <enum name="no" />
00335             </enumlist>
00336          </parameter>
00337       </syntax>
00338       <description>
00339          <para>Bridge together two channels already in the PBX.</para>
00340       </description>
00341    </manager>
00342  ***/
00343 
00344 #define DEFAULT_PARK_TIME                    45000 /*!< ms */
00345 #define DEFAULT_PARK_EXTENSION                  "700"
00346 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT          3000  /*!< ms */
00347 #define DEFAULT_FEATURE_DIGIT_TIMEOUT           1000  /*!< ms */
00348 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000 /*!< ms */
00349 #define DEFAULT_ATXFER_DROP_CALL             0     /*!< Do not drop call. */
00350 #define DEFAULT_ATXFER_LOOP_DELAY               10000 /*!< ms */
00351 #define DEFAULT_ATXFER_CALLBACK_RETRIES            2
00352 
00353 #define AST_MAX_WATCHERS 256
00354 #define MAX_DIAL_FEATURE_OPTIONS 30
00355 
00356 struct feature_group_exten {
00357    AST_LIST_ENTRY(feature_group_exten) entry;
00358    AST_DECLARE_STRING_FIELDS(
00359       AST_STRING_FIELD(exten);
00360    );
00361    struct ast_call_feature *feature;
00362 };
00363 
00364 struct feature_group {
00365    AST_LIST_ENTRY(feature_group) entry;
00366    AST_DECLARE_STRING_FIELDS(
00367       AST_STRING_FIELD(gname);
00368    );
00369    AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
00370 };
00371 
00372 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
00373 
00374 static char *parkedcall = "ParkedCall";
00375 
00376 static char pickup_ext[AST_MAX_EXTENSION];                 /*!< Call pickup extension */
00377 
00378 /*! \brief Description of one parked call, added to a list while active, then removed.
00379    The list belongs to a parkinglot 
00380 */
00381 struct parkeduser {
00382    struct ast_channel *chan;                   /*!< Parking channel */
00383    struct timeval start;                       /*!< Time the parking started */
00384    int parkingnum;                             /*!< Parking lot */
00385    char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
00386    char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
00387    char exten[AST_MAX_EXTENSION];
00388    int priority;
00389    int parkingtime;                            /*!< Maximum length in parking lot before return */
00390    unsigned int notquiteyet:1;
00391    unsigned int options_specified:1;
00392    char peername[1024];
00393    unsigned char moh_trys;
00394    struct ast_parkinglot *parkinglot;
00395    AST_LIST_ENTRY(parkeduser) list;
00396 };
00397 
00398 /*! \brief Structure for parking lots which are put in a container. */
00399 struct ast_parkinglot {
00400    char name[AST_MAX_CONTEXT];
00401    char parkext[AST_MAX_EXTENSION];          /*!< Parkingextension */
00402    char parking_con[AST_MAX_EXTENSION];      /*!< Context for which parking is made accessible */
00403    char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
00404    int parking_start;            /*!< First available extension for parking */
00405    int parking_stop;          /*!< Last available extension for parking */
00406    int parking_offset;
00407    int parkfindnext;
00408    int parkingtime;           /*!< Default parking time */
00409    char mohclass[MAX_MUSICCLASS];                  /*!< Music class used for parking */
00410    int parkaddhints;                               /*!< Add parking hints automatically */
00411    int parkedcalltransfers;                        /*!< Enable DTMF based transfers on bridge when picking up parked calls */
00412    int parkedcallreparking;                        /*!< Enable DTMF based parking on bridge when picking up parked calls */
00413    int parkedcallhangup;                           /*!< Enable DTMF based hangup on a bridge when pickup up parked calls */
00414    int parkedcallrecording;                        /*!< Enable DTMF based recording on a bridge when picking up parked calls */
00415    unsigned short the_mark:1;                      /*!< Used during reloads, that which bears the_mark shall be deleted! */
00416    AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings; /*!< List of active parkings in this parkinglot */
00417 };
00418 
00419 /*! \brief The list of parking lots configured. Always at least one  - the default parking lot */
00420 static struct ao2_container *parkinglots;
00421  
00422 struct ast_parkinglot *default_parkinglot;
00423 char parking_ext[AST_MAX_EXTENSION];            /*!< Extension you type to park the call */
00424 
00425 static char courtesytone[256];                             /*!< Courtesy tone */
00426 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
00427 static int parkeddynamic = 0;                              /*!< Enable creation of parkinglots dynamically */
00428 static char xfersound[256];                                /*!< Call transfer sound */
00429 static char xferfailsound[256];                            /*!< Call transfer failure sound */
00430 static char pickupsound[256];                              /*!< Pickup sound */
00431 static char pickupfailsound[256];                          /*!< Pickup failure sound */
00432 
00433 static int adsipark;
00434 
00435 static int transferdigittimeout;
00436 static int featuredigittimeout;
00437 static int comebacktoorigin = 1;
00438 
00439 static int atxfernoanswertimeout;
00440 static unsigned int atxferdropcall;
00441 static unsigned int atxferloopdelay;
00442 static unsigned int atxfercallbackretries;
00443 
00444 static char *registrar = "features";         /*!< Registrar for operations */
00445 
00446 /* module and CLI command definitions */
00447 static char *parkcall = PARK_APP_NAME;
00448 
00449 static struct ast_app *monitor_app = NULL;
00450 static int monitor_ok = 1;
00451 
00452 static struct ast_app *mixmonitor_app = NULL;
00453 static int mixmonitor_ok = 1;
00454 
00455 static struct ast_app *stopmixmonitor_app = NULL;
00456 static int stopmixmonitor_ok = 1;
00457 
00458 static pthread_t parking_thread;
00459 struct ast_dial_features {
00460    struct ast_flags features_caller;
00461    struct ast_flags features_callee;
00462    int is_caller;
00463 };
00464 
00465 #if defined(ATXFER_NULL_TECH)
00466 static struct ast_frame *null_read(struct ast_channel *chan)
00467 {
00468    /* Hangup channel. */
00469    return NULL;
00470 }
00471 
00472 static struct ast_frame *null_exception(struct ast_channel *chan)
00473 {
00474    /* Hangup channel. */
00475    return NULL;
00476 }
00477 
00478 static int null_write(struct ast_channel *chan, struct ast_frame *frame)
00479 {
00480    /* Hangup channel. */
00481    return -1;
00482 }
00483 
00484 static int null_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00485 {
00486    /* No problem fixing up the channel. */
00487    return 0;
00488 }
00489 
00490 static int null_hangup(struct ast_channel *chan)
00491 {
00492    chan->tech_pvt = NULL;
00493    return 0;
00494 }
00495 
00496 static const struct ast_channel_tech null_tech = {
00497    .type = "NULL",
00498    .description = "NULL channel driver for atxfer",
00499    .capabilities = -1,
00500    .read = null_read,
00501    .exception = null_exception,
00502    .write = null_write,
00503    .fixup = null_fixup,
00504    .hangup = null_hangup,
00505 };
00506 #endif   /* defined(ATXFER_NULL_TECH) */
00507 
00508 #if defined(ATXFER_NULL_TECH)
00509 /*!
00510  * \internal
00511  * \brief Set the channel technology to the NULL technology.
00512  *
00513  * \param chan Channel to change technology.
00514  *
00515  * \return Nothing
00516  */
00517 static void set_null_chan_tech(struct ast_channel *chan)
00518 {
00519    int idx;
00520 
00521    ast_channel_lock(chan);
00522 
00523    /* Hangup the channel's physical side */
00524    if (chan->tech->hangup) {
00525       chan->tech->hangup(chan);
00526    }
00527    if (chan->tech_pvt) {
00528       ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n",
00529          chan->name);
00530       ast_free(chan->tech_pvt);
00531       chan->tech_pvt = NULL;
00532    }
00533 
00534    /* Install the NULL technology and wake up anyone waiting on it. */
00535    chan->tech = &null_tech;
00536    for (idx = 0; idx < AST_MAX_FDS; ++idx) {
00537       switch (idx) {
00538       case AST_ALERT_FD:
00539       case AST_TIMING_FD:
00540       case AST_GENERATOR_FD:
00541          /* Don't clear these fd's. */
00542          break;
00543       default:
00544          ast_channel_set_fd(chan, idx, -1);
00545          break;
00546       }
00547    }
00548    ast_queue_frame(chan, &ast_null_frame);
00549 
00550    ast_channel_unlock(chan);
00551 }
00552 #endif   /* defined(ATXFER_NULL_TECH) */
00553 
00554 #if defined(ATXFER_NULL_TECH)
00555 /*!
00556  * \internal
00557  * \brief Set the channel name to something unique.
00558  *
00559  * \param chan Channel to change name.
00560  *
00561  * \return Nothing
00562  */
00563 static void set_new_chan_name(struct ast_channel *chan)
00564 {
00565    static int seq_num_last;
00566    int seq_num;
00567    int len;
00568    char *chan_name;
00569    char dummy[1];
00570 
00571    /* Create the new channel name string. */
00572    ast_channel_lock(chan);
00573    seq_num = ast_atomic_fetchadd_int(&seq_num_last, +1);
00574    len = snprintf(dummy, sizeof(dummy), "%s<XFER_%x>", chan->name, seq_num) + 1;
00575    chan_name = alloca(len);
00576    snprintf(chan_name, len, "%s<XFER_%x>", chan->name, seq_num);
00577    ast_channel_unlock(chan);
00578 
00579    ast_change_name(chan, chan_name);
00580 }
00581 #endif   /* defined(ATXFER_NULL_TECH) */
00582 
00583 static void *dial_features_duplicate(void *data)
00584 {
00585    struct ast_dial_features *df = data, *df_copy;
00586  
00587    if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
00588       return NULL;
00589    }
00590  
00591    memcpy(df_copy, df, sizeof(*df));
00592  
00593    return df_copy;
00594 }
00595 
00596 static void dial_features_destroy(void *data)
00597 {
00598    struct ast_dial_features *df = data;
00599    if (df) {
00600       ast_free(df);
00601    }
00602 }
00603 
00604 static const struct ast_datastore_info dial_features_info = {
00605    .type = "dial-features",
00606    .destroy = dial_features_destroy,
00607    .duplicate = dial_features_duplicate,
00608  };
00609  
00610 /* Forward declarations */
00611 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
00612 static void parkinglot_unref(struct ast_parkinglot *parkinglot);
00613 static void parkinglot_destroy(void *obj);
00614 int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *fs);
00615 struct ast_parkinglot *find_parkinglot(const char *name);
00616 static struct ast_parkinglot *create_parkinglot(const char *name);
00617 static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
00618 
00619 static int find_parkinglot_by_position_cb(void *obj, void *args, int flags)
00620 {
00621    struct ast_parkinglot *parkinglot = obj;
00622    int *parkpos = args;
00623 
00624    if (*parkpos >= parkinglot->parking_start && *parkpos <= parkinglot->parking_stop) {
00625       return CMP_MATCH | CMP_STOP;
00626    }
00627 
00628    return 0;
00629 }
00630 
00631 static int find_parkinglot_by_exten_cb(void *obj, void *args, int flags)
00632 {
00633    struct ast_parkinglot *parkinglot = obj;
00634    const char *parkext = args;
00635 
00636    if (!strcmp(parkinglot->parkext, parkext)) {
00637       return CMP_MATCH | CMP_STOP;
00638    }
00639 
00640    return 0;
00641 }
00642 
00643 int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
00644 {
00645    struct ast_exten *exten;
00646    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
00647    const char *app_at_exten;
00648 
00649    exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL, E_MATCH);
00650    if (!exten) {
00651       return 0;
00652    }
00653 
00654    app_at_exten = ast_get_extension_app(exten);
00655    if (!app_at_exten || strcmp(PARK_APP_NAME, app_at_exten)) {
00656       return 0;
00657    }
00658 
00659    return 1;
00660 }
00661 
00662 const char *ast_pickup_ext(void)
00663 {
00664    return pickup_ext;
00665 }
00666 
00667 struct ast_bridge_thread_obj 
00668 {
00669    struct ast_bridge_config bconfig;
00670    struct ast_channel *chan;
00671    struct ast_channel *peer;
00672    unsigned int return_to_pbx:1;
00673 };
00674 
00675 static int parkinglot_hash_cb(const void *obj, const int flags)
00676 {
00677    const struct ast_parkinglot *parkinglot = obj;
00678 
00679    return ast_str_case_hash(parkinglot->name);
00680 }
00681 
00682 static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
00683 {
00684    struct ast_parkinglot *parkinglot = obj, *parkinglot2 = arg;
00685 
00686    return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
00687 }
00688 
00689 /*!
00690  * \brief store context, extension and priority 
00691  * \param chan, context, ext, pri
00692 */
00693 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
00694 {
00695    ast_copy_string(chan->context, context, sizeof(chan->context));
00696    ast_copy_string(chan->exten, ext, sizeof(chan->exten));
00697    chan->priority = pri;
00698 }
00699 
00700 /*!
00701  * \brief Check goto on transfer
00702  * \param chan
00703  *
00704  * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
00705  * When found make sure the types are compatible. Check if channel is valid
00706  * if so start the new channel else hangup the call. 
00707 */
00708 static void check_goto_on_transfer(struct ast_channel *chan) 
00709 {
00710    struct ast_channel *xferchan;
00711    const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
00712    char *x, *goto_on_transfer;
00713    struct ast_frame *f;
00714 
00715    if (ast_strlen_zero(val))
00716       return;
00717 
00718    goto_on_transfer = ast_strdupa(val);
00719 
00720    if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0, "%s", chan->name)))
00721       return;
00722 
00723    for (x = goto_on_transfer; x && *x; x++) {
00724       if (*x == '^')
00725          *x = '|';
00726    }
00727    /* Make formats okay */
00728    xferchan->readformat = chan->readformat;
00729    xferchan->writeformat = chan->writeformat;
00730    ast_channel_masquerade(xferchan, chan);
00731    ast_parseable_goto(xferchan, goto_on_transfer);
00732    xferchan->_state = AST_STATE_UP;
00733    ast_clear_flag(xferchan, AST_FLAGS_ALL);  
00734    xferchan->_softhangup = 0;
00735    if ((f = ast_read(xferchan))) {
00736       ast_frfree(f);
00737       f = NULL;
00738       ast_pbx_start(xferchan);
00739    } else {
00740       ast_hangup(xferchan);
00741    }
00742 }
00743 
00744 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
00745    const char *caller_name, struct ast_channel *requestor,
00746    struct ast_channel *transferee, const char *type, int format, void *data,
00747    int timeout, int *outstate, const char *language);
00748 
00749 /*!
00750  * \brief bridge the call 
00751  * \param data thread bridge.
00752  *
00753  * Set Last Data for respective channels, reset cdr for channels
00754  * bridge call, check if we're going back to dialplan
00755  * if not hangup both legs of the call
00756 */
00757 static void *bridge_call_thread(void *data)
00758 {
00759    struct ast_bridge_thread_obj *tobj = data;
00760    int res;
00761 
00762    tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
00763    tobj->chan->data = tobj->peer->name;
00764    tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
00765    tobj->peer->data = tobj->chan->name;
00766 
00767    ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
00768 
00769    if (tobj->return_to_pbx) {
00770       if (!ast_check_hangup(tobj->peer)) {
00771          ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
00772          res = ast_pbx_start(tobj->peer);
00773          if (res != AST_PBX_SUCCESS)
00774             ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
00775       } else
00776          ast_hangup(tobj->peer);
00777       if (!ast_check_hangup(tobj->chan)) {
00778          ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
00779          res = ast_pbx_start(tobj->chan);
00780          if (res != AST_PBX_SUCCESS)
00781             ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
00782       } else
00783          ast_hangup(tobj->chan);
00784    } else {
00785       ast_hangup(tobj->chan);
00786       ast_hangup(tobj->peer);
00787    }
00788 
00789    ast_free(tobj);
00790 
00791    return NULL;
00792 }
00793 
00794 /*!
00795  * \brief create thread for the parked call
00796  * \param data
00797  *
00798  * Create thread and attributes, call bridge_call_thread
00799 */
00800 static void bridge_call_thread_launch(void *data) 
00801 {
00802    pthread_t thread;
00803    pthread_attr_t attr;
00804    struct sched_param sched;
00805 
00806    pthread_attr_init(&attr);
00807    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00808    ast_pthread_create(&thread, &attr, bridge_call_thread, data);
00809    pthread_attr_destroy(&attr);
00810    memset(&sched, 0, sizeof(sched));
00811    pthread_setschedparam(thread, SCHED_RR, &sched);
00812 }
00813 
00814 /*!
00815  * \brief Announce call parking by ADSI
00816  * \param chan .
00817  * \param parkingexten .
00818  * Create message to show for ADSI, display message.
00819  * \retval 0 on success.
00820  * \retval -1 on failure.
00821 */
00822 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
00823 {
00824    int res;
00825    int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
00826    char tmp[256];
00827    char *message[5] = {NULL, NULL, NULL, NULL, NULL};
00828 
00829    snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
00830    message[0] = tmp;
00831    res = ast_adsi_load_session(chan, NULL, 0, 1);
00832    if (res == -1)
00833       return res;
00834    return ast_adsi_print(chan, message, justify, 1);
00835 }
00836 
00837 /*! \brief Find parking lot name from channel */
00838 static const char *findparkinglotname(struct ast_channel *chan)
00839 {
00840    const char *temp, *parkinglot = NULL;
00841 
00842    /* Check if the channel has a parking lot */
00843    if (!ast_strlen_zero(chan->parkinglot))
00844       parkinglot = chan->parkinglot;
00845 
00846    /* Channel variables override everything */
00847 
00848    if ((temp  = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
00849       return temp;
00850 
00851    return parkinglot;
00852 }
00853 
00854 /*! \brief Notify metermaids that we've changed an extension */
00855 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
00856 {
00857    ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'", 
00858       exten, context, ast_devstate2str(state));
00859 
00860    ast_devstate_changed(state, "park:%s@%s", exten, context);
00861 }
00862 
00863 /*! \brief metermaids callback from devicestate.c */
00864 static enum ast_device_state metermaidstate(const char *data)
00865 {
00866    char *context;
00867    char *exten;
00868 
00869    context = ast_strdupa(data);
00870 
00871    exten = strsep(&context, "@");
00872    if (!context)
00873       return AST_DEVICE_INVALID;
00874    
00875    ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
00876 
00877    if (!ast_exists_extension(NULL, context, exten, 1, NULL))
00878       return AST_DEVICE_NOT_INUSE;
00879 
00880    return AST_DEVICE_INUSE;
00881 }
00882 
00883 /*! Options to pass to park_call_full */
00884 enum ast_park_call_options {
00885    /*! Provide ringing to the parked caller instead of music on hold */
00886    AST_PARK_OPT_RINGING =   (1 << 0),
00887    /*! Randomly choose a parking spot for the caller instead of choosing
00888     *  the first one that is available. */
00889    AST_PARK_OPT_RANDOMIZE = (1 << 1),
00890    /*! Do not announce the parking number */
00891    AST_PARK_OPT_SILENCE = (1 << 2),
00892 };
00893 
00894 struct ast_park_call_args {
00895    /*! How long to wait in the parking lot before the call gets sent back
00896     *  to the specified return extension (or a best guess at where it came
00897     *  from if not explicitly specified). */
00898    int timeout;
00899    /*! An output parameter to store the parking space where the parked caller
00900     *  was placed. */
00901    int *extout;
00902    const char *orig_chan_name;
00903    const char *return_con;
00904    const char *return_ext;
00905    int return_pri;
00906    uint32_t flags;
00907    /*! Parked user that has already obtained a parking space */
00908    struct parkeduser *pu;
00909    struct ast_parkinglot *parkinglot; /*! parkinglot to be parked in, based on parkext */
00910 };
00911 
00912 static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
00913 {
00914    struct parkeduser *pu;
00915    int i, parking_space = -1, parking_range;
00916    const char *parkinglotname = NULL;
00917    const char *parkingexten;
00918    struct ast_parkinglot *parkinglot = NULL;
00919 
00920    if (args->parkinglot) {
00921       parkinglot = args->parkinglot;
00922       parkinglotname = parkinglot->name;
00923    } else if (peer) {
00924       parkinglotname = findparkinglotname(peer);
00925    } else { /* peer was NULL, check chan (ParkAndAnnounce / res_agi) */
00926       parkinglotname = findparkinglotname(chan);
00927    }
00928 
00929    if (!args->parkinglot) {
00930       if (parkinglotname) {
00931          parkinglot = find_parkinglot(parkinglotname);
00932       } else {
00933          ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
00934          parkinglot = parkinglot_addref(default_parkinglot);
00935       }
00936       ast_debug(1, "Found chanvar Parkinglot: %s\n", parkinglot->name);
00937    }
00938 
00939    /* Dynamically create parkinglot */
00940    if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
00941       const char *dyn_context, *dyn_range;
00942       const char *parkinglotname_copy = NULL;
00943       struct ast_parkinglot *parkinglot_copy = NULL;
00944       int dyn_start, dyn_end;
00945 
00946       ast_channel_lock(chan);
00947       parkinglotname_copy = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
00948       dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
00949       dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
00950       ast_channel_unlock(chan);
00951 
00952       if (!ast_strlen_zero(parkinglotname_copy)) {
00953          parkinglot_copy = find_parkinglot(parkinglotname_copy);
00954       }
00955       if (!parkinglot_copy) {
00956          parkinglot_copy = parkinglot_addref(default_parkinglot);
00957          ast_debug(1, "Using default parking lot for copy\n");
00958       }
00959       if (!(parkinglot = copy_parkinglot(parkinglotname, parkinglot_copy))) {
00960          ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
00961       } else {
00962          if (!ast_strlen_zero(dyn_context)) {
00963             ast_copy_string(parkinglot->parking_con, dyn_context, sizeof(parkinglot->parking_con));
00964          }
00965          if (!ast_strlen_zero(dyn_range)) {
00966             if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
00967                ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers\n");
00968             } else {
00969                parkinglot->parking_start = dyn_start;
00970                parkinglot->parking_stop = dyn_end;
00971             }
00972          }
00973          ao2_link(parkinglots, parkinglot);
00974       }
00975 
00976       if (parkinglot_copy) {
00977          /* unref our tempory copy */
00978          parkinglot_unref(parkinglot_copy);
00979          parkinglot_copy = NULL;
00980       }
00981    }
00982 
00983    if (!parkinglot) {
00984       parkinglot = parkinglot_addref(default_parkinglot);
00985    }
00986 
00987    ast_debug(1, "Parkinglot: %s\n", parkinglot->name);
00988 
00989    /* Allocate memory for parking data */
00990    if (!(pu = ast_calloc(1, sizeof(*pu)))) {
00991       parkinglot_unref(parkinglot);
00992       return NULL;
00993    }
00994 
00995    /* Lock parking list */
00996    AST_LIST_LOCK(&parkinglot->parkings);
00997    /* Check for channel variable PARKINGEXTEN */
00998    ast_channel_lock(chan);
00999    parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"), ""));
01000    ast_channel_unlock(chan);
01001    if (!ast_strlen_zero(parkingexten)) {
01002       /*!\note The API forces us to specify a numeric parking slot, even
01003        * though the architecture would tend to support non-numeric extensions
01004        * (as are possible with SIP, for example).  Hence, we enforce that
01005        * limitation here.  If extout was not numeric, we could permit
01006        * arbitrary non-numeric extensions.
01007        */
01008         if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space < 0) {
01009          AST_LIST_UNLOCK(&parkinglot->parkings);
01010          parkinglot_unref(parkinglot);
01011             free(pu);
01012             ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
01013             return NULL;
01014         }
01015         snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
01016 
01017       if (ast_exists_extension(NULL, parkinglot->parking_con, pu->parkingexten, 1, NULL)) {
01018          ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
01019          AST_LIST_UNLOCK(&parkinglot->parkings);
01020          parkinglot_unref(parkinglot);
01021          ast_free(pu);
01022          return NULL;
01023       }
01024    } else {
01025       int start;
01026       struct parkeduser *cur = NULL;
01027 
01028       /* Select parking space within range */
01029       parking_range = parkinglot->parking_stop - parkinglot->parking_start + 1;
01030 
01031       if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
01032          start = ast_random() % (parkinglot->parking_stop - parkinglot->parking_start + 1);
01033       } else {
01034          start = parkinglot->parking_start;
01035       }
01036 
01037       for (i = start; 1; i++) {
01038          if (i == parkinglot->parking_stop + 1) {
01039             i = parkinglot->parking_start - 1;
01040             break;
01041          }
01042 
01043          AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
01044             if (cur->parkingnum == i) {
01045                break;
01046             }
01047          }
01048          if (!cur) {
01049             parking_space = i;
01050             break;
01051          }
01052       }
01053 
01054       if (i == start - 1 && cur) {
01055          ast_log(LOG_WARNING, "No more parking spaces\n");
01056          ast_free(pu);
01057          AST_LIST_UNLOCK(&parkinglot->parkings);
01058          parkinglot_unref(parkinglot);
01059          return NULL;
01060       }
01061       /* Set pointer for next parking */
01062       if (parkinglot->parkfindnext) 
01063          parkinglot->parking_offset = parking_space - parkinglot->parking_start + 1;
01064       snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
01065    }
01066 
01067    pu->notquiteyet = 1;
01068    pu->parkingnum = parking_space;
01069    pu->parkinglot = parkinglot;
01070    AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
01071 
01072    return pu;
01073 }
01074 
01075 /* Park a call */
01076 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
01077 {
01078    struct ast_context *con;
01079    int parkingnum_copy;
01080    struct parkeduser *pu = args->pu;
01081    const char *event_from;
01082 
01083    if (pu == NULL)
01084       args->pu = pu = park_space_reserve(chan, peer, args);
01085    if (pu == NULL)
01086       return 1; /* Continue execution if possible */
01087 
01088    snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", pu->parkingnum);
01089 
01090    chan->appl = "Parked Call";
01091    chan->data = NULL;
01092 
01093    pu->chan = chan;
01094 
01095    /* Put the parked channel on hold if we have two different channels */
01096    if (chan != peer) {
01097       if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
01098          ast_indicate(pu->chan, AST_CONTROL_RINGING);
01099       } else {
01100          ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
01101             S_OR(pu->parkinglot->mohclass, NULL),
01102             !ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
01103       }
01104    }
01105    
01106    pu->start = ast_tvnow();
01107    pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->parkingtime;
01108    parkingnum_copy = pu->parkingnum;
01109    if (args->extout)
01110       *(args->extout) = pu->parkingnum;
01111 
01112    if (peer) { 
01113       /* This is so ugly that it hurts, but implementing get_base_channel() on local channels
01114          could have ugly side effects.  We could have transferer<->local,1<->local,2<->parking
01115          and we need the callback name to be that of transferer.  Since local,1/2 have the same
01116          name we can be tricky and just grab the bridged channel from the other side of the local
01117       */
01118       if (!strcasecmp(peer->tech->type, "Local")) {
01119          struct ast_channel *tmpchan, *base_peer;
01120          char other_side[AST_CHANNEL_NAME];
01121          char *c;
01122          ast_copy_string(other_side, S_OR(args->orig_chan_name, peer->name), sizeof(other_side));
01123          if ((c = strrchr(other_side, ';'))) {
01124             *++c = '1';
01125          }
01126          if ((tmpchan = ast_channel_get_by_name(other_side))) {
01127             ast_channel_lock(tmpchan);
01128             if ((base_peer = ast_bridged_channel(tmpchan))) {
01129                ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
01130             }
01131             ast_channel_unlock(tmpchan);
01132             tmpchan = ast_channel_unref(tmpchan);
01133          }
01134       } else {
01135          ast_copy_string(pu->peername, S_OR(args->orig_chan_name, peer->name), sizeof(pu->peername));
01136       }
01137    }
01138 
01139    /* Remember what had been dialed, so that if the parking
01140       expires, we try to come back to the same place */
01141 
01142    pu->options_specified = (!ast_strlen_zero(args->return_con) || !ast_strlen_zero(args->return_ext) || args->return_pri);
01143 
01144    /* If extension has options specified, they override all other possibilities
01145    such as the returntoorigin flag and transferred context. Information on
01146    extension options is lost here, so we set a flag */
01147 
01148    ast_copy_string(pu->context, 
01149       S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)), 
01150       sizeof(pu->context));
01151    ast_copy_string(pu->exten, 
01152       S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)), 
01153       sizeof(pu->exten));
01154    pu->priority = args->return_pri ? args->return_pri : 
01155       (chan->macropriority ? chan->macropriority : chan->priority);
01156 
01157    /* If parking a channel directly, don't quiet yet get parking running on it.
01158     * All parking lot entries are put into the parking lot with notquiteyet on. */
01159    if (peer != chan) 
01160       pu->notquiteyet = 0;
01161 
01162    /* Wake up the (presumably select()ing) thread */
01163    pthread_kill(parking_thread, SIGURG);
01164    ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
01165 
01166    ast_cel_report_event(pu->chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
01167 
01168    if (peer) {
01169       event_from = peer->name;
01170    } else {
01171       event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
01172    }
01173 
01174    ast_manager_event(pu->chan, EVENT_FLAG_CALL, "ParkedCall",
01175       "Exten: %s\r\n"
01176       "Channel: %s\r\n"
01177       "Parkinglot: %s\r\n"
01178       "From: %s\r\n"
01179       "Timeout: %ld\r\n"
01180       "CallerIDNum: %s\r\n"
01181       "CallerIDName: %s\r\n"
01182       "Uniqueid: %s\r\n",
01183       pu->parkingexten, pu->chan->name, pu->parkinglot->name, event_from ? event_from : "",
01184       (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
01185       S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
01186       S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
01187       pu->chan->uniqueid
01188       );
01189 
01190    if (peer && adsipark && ast_adsi_available(peer)) {
01191       adsi_announce_park(peer, pu->parkingexten);  /* Only supports parking numbers */
01192       ast_adsi_unload_session(peer);
01193    }
01194 
01195    con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con, registrar);
01196    if (!con)   /* Still no context? Bad */
01197       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con);
01198    if (con) {
01199       if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
01200          notify_metermaids(pu->parkingexten, pu->parkinglot->parking_con, AST_DEVICE_INUSE);
01201    }
01202 
01203    AST_LIST_UNLOCK(&pu->parkinglot->parkings);
01204 
01205    /* Only say number if it's a number and the channel hasn't been masqueraded away */
01206    if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE) && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
01207       /* If a channel is masqueraded into peer while playing back the parking slot number do not continue playing it back. This is the case if an attended transfer occurs. */
01208       ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
01209       /* Tell the peer channel the number of the parking space */
01210       ast_say_digits(peer, pu->parkingnum, "", peer->language);
01211       ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
01212    }
01213    if (peer == chan) { /* pu->notquiteyet = 1 */
01214       /* Wake up parking thread if we're really done */
01215       ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
01216          S_OR(pu->parkinglot->mohclass, NULL),
01217          !ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
01218       pu->notquiteyet = 0;
01219       pthread_kill(parking_thread, SIGURG);
01220    }
01221    return 0;
01222 }
01223 
01224 /*! \brief Park a call */
01225 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, const char *parkexten, int *extout)
01226 {
01227    struct ast_parkinglot *found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, (void *) parkexten);
01228 
01229    struct ast_park_call_args args = {
01230       .timeout = timeout,
01231       .extout = extout,
01232       .parkinglot = found_lot,
01233    };
01234 
01235    return park_call_full(chan, peer, &args);
01236 }
01237 
01238 /*!
01239  * \param rchan is the transferee
01240  * \param peer is the transferer
01241  */
01242 static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement, struct ast_park_call_args *args)
01243 {
01244    struct ast_channel *chan;
01245    struct ast_frame *f;
01246    struct ast_park_call_args park_args = {0,};
01247 
01248    if (!args) {
01249       args = &park_args;
01250       args->timeout = timeout;
01251       args->extout = extout;
01252    }
01253 
01254    if ((args->pu = park_space_reserve(rchan, peer, args)) == NULL) {
01255       if (peer) {
01256          ast_stream_and_wait(peer, "pbx-parkingfailed", "");
01257       }
01258       return AST_FEATURE_RETURN_PARKFAILED;
01259    }
01260 
01261    /* Make a new, fake channel that we'll use to masquerade in the real one */
01262    if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->linkedid, rchan->amaflags, "Parked/%s",rchan->name))) {
01263       ast_log(LOG_WARNING, "Unable to create parked channel\n");
01264       return -1;
01265    }
01266 
01267    /* Make formats okay */
01268    chan->readformat = rchan->readformat;
01269    chan->writeformat = rchan->writeformat;
01270    ast_channel_masquerade(chan, rchan);
01271 
01272    /* Setup the extensions and such */
01273    set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
01274 
01275    /* Setup the macro extension and such */
01276    ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
01277    ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
01278    chan->macropriority = rchan->macropriority;
01279 
01280    /* Make the masq execute */
01281    if ((f = ast_read(chan)))
01282       ast_frfree(f);
01283 
01284    if (peer == rchan) {
01285       peer = chan;
01286    }
01287 
01288    if (peer && (!play_announcement && args == &park_args)) {
01289       args->orig_chan_name = ast_strdupa(peer->name);
01290    }
01291 
01292    /* parking space reserved, return code check unnecessary */
01293    park_call_full(chan, peer, args);
01294 
01295    return 0;
01296 }
01297 
01298 /* Park call via masqueraded channel */
01299 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
01300 {
01301    return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
01302 }
01303 
01304 static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
01305 {
01306    return masq_park_call(rchan, peer, 0, NULL, 1, args);
01307 }
01308 
01309 #ifdef TEST_FRAMEWORK
01310 static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
01311 {
01312    return 0;
01313 }
01314 
01315 static struct ast_channel *create_test_channel(const struct ast_channel_tech *fake_tech)
01316 {
01317    struct ast_channel *test_channel1;
01318    if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
01319         NULL, NULL, 0, 0, "TestChannel1"))) {
01320       return NULL;
01321    }
01322 
01323    /* normally this is done in the channel driver */
01324    test_channel1->nativeformats = AST_FORMAT_GSM;
01325    test_channel1->writeformat = AST_FORMAT_GSM;
01326    test_channel1->rawwriteformat = AST_FORMAT_GSM;
01327    test_channel1->readformat = AST_FORMAT_GSM;
01328    test_channel1->rawreadformat = AST_FORMAT_GSM;
01329    test_channel1->tech = fake_tech;
01330 
01331    return test_channel1;
01332 }
01333 
01334 static int unpark_test_channel(struct ast_channel *toremove, struct ast_park_call_args *args)
01335 {
01336    struct ast_context *con;
01337    struct parkeduser *pu_toremove;
01338    args->pu->notquiteyet = 1; /* go ahead and stop processing the test parking */
01339    AST_LIST_LOCK(&args->pu->parkinglot->parkings);
01340    AST_LIST_TRAVERSE_SAFE_BEGIN(&args->pu->parkinglot->parkings, pu_toremove, list) {
01341       con = ast_context_find(args->pu->parkinglot->parking_con);
01342       if (con) {
01343          if (ast_context_remove_extension2(con, args->pu->parkingexten, 1, NULL, 0)) {
01344             ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
01345             return -1;
01346          } else {
01347             notify_metermaids(args->pu->parkingexten, pu_toremove->parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
01348          }
01349       } else {
01350          ast_log(LOG_WARNING, "Whoa, no parking context?\n");
01351          return -1;
01352       }
01353       if (pu_toremove == args->pu) {
01354          AST_LIST_REMOVE_CURRENT(list);
01355          break;
01356       }
01357    }
01358    AST_LIST_TRAVERSE_SAFE_END;
01359    AST_LIST_UNLOCK(&args->pu->parkinglot->parkings);
01360 
01361    /* the only way this would be unsafe is if a timeout occurred, which is set at 45 sec */
01362    ast_free(args->pu);
01363    args->pu = NULL;
01364 
01365    ast_hangup(toremove);
01366    return 0;
01367 }
01368 
01369 AST_TEST_DEFINE(features_test)
01370 {
01371    int saved_parkeddynamic;
01372    struct ast_channel *test_channel1 = NULL;
01373    struct ast_channel *parked_chan = NULL;
01374    struct ast_parkinglot *dynlot = NULL;
01375    struct ast_park_call_args args = {
01376       .timeout = DEFAULT_PARK_TIME,
01377    };
01378 
01379    int res = -1;
01380 
01381    static const struct ast_channel_tech fake_tech = {
01382       .fixup = fake_fixup, /* silence warning from masquerade */
01383    };
01384 
01385    static const char unique_parkinglot[] = "myuniquetestparkinglot3141592654";
01386    static const char parkinglot_range[] = "750-760";
01387 
01388    switch (cmd) {
01389    case TEST_INIT:
01390       info->name = "features_test";
01391       info->category = "/main/features/";
01392       info->summary = "Features unit test";
01393       info->description =
01394          "Tests whether parking respects PARKINGLOT settings";
01395       return AST_TEST_NOT_RUN;
01396    case TEST_EXECUTE:
01397       break;
01398    }
01399 
01400    /* changing a config option is a bad practice, but must be done in this case */
01401    saved_parkeddynamic = parkeddynamic;
01402    parkeddynamic = 1;
01403 
01404    if (!(test_channel1 = create_test_channel(&fake_tech))) {
01405       goto exit_features_test;
01406    }
01407 
01408    ast_test_status_update(test, "Test parking functionality with defaults\n");
01409    if (park_call_full(test_channel1, NULL, &args)) {
01410       goto exit_features_test;
01411    }
01412    if (unpark_test_channel(test_channel1, &args)) {
01413       goto exit_features_test;
01414    }
01415 
01416    ast_test_status_update(test, "Check that certain parking options are respected\n");
01417    if (!(test_channel1 = create_test_channel(&fake_tech))) {
01418       goto exit_features_test;
01419    }
01420    pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
01421    pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
01422    if (park_call_full(test_channel1, NULL, &args)) {
01423       goto exit_features_test;
01424    }
01425    /* grab newly created parking lot for destruction in the end */
01426    dynlot = args.pu->parkinglot;
01427    if (!args.pu->parkingnum == 750 || strcasecmp(args.pu->parkinglot->name, unique_parkinglot)) {
01428       ast_test_status_update(test, "Parking settings were not respected\n");
01429       goto exit_features_test;
01430    } else {
01431       ast_test_status_update(test, "Parking settings for non-masquerading park verified\n");
01432    }
01433    if (unpark_test_channel(test_channel1, &args)) {
01434       goto exit_features_test;
01435    }
01436 
01437    ast_test_status_update(test, "Check #2 that certain parking options are respected\n");
01438    if (!(test_channel1 = create_test_channel(&fake_tech))) {
01439       goto exit_features_test;
01440    }
01441    pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
01442    pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
01443    if (masq_park_call(test_channel1, NULL, 0, NULL, 0, &args) == AST_FEATURE_RETURN_PARKFAILED) {
01444       goto exit_features_test;
01445    }
01446    /* hangup zombie channel */
01447    ast_hangup(test_channel1);
01448    test_channel1 = NULL;
01449    if (!args.pu->parkingnum == 750 || strcasecmp(args.pu->parkinglot->name, unique_parkinglot)) {
01450       ast_test_status_update(test, "Parking settings were not respected\n");
01451       goto exit_features_test;
01452    } else {
01453       ast_test_status_update(test, "Parking settings for masquerading park verified\n");
01454    }
01455    /* find the real channel */
01456    parked_chan = ast_channel_get_by_name("TestChannel1");
01457    if (unpark_test_channel(parked_chan, &args)) {
01458       goto exit_features_test;
01459    }
01460 
01461    res = 0;
01462 
01463 exit_features_test:
01464 
01465    if (test_channel1) {
01466       ast_hangup(test_channel1);
01467    }
01468 
01469    /* careful, if PARKINGDYNCONTEXT is tested, need to delete context */
01470    ao2_unlink(parkinglots, dynlot);
01471    parkeddynamic = saved_parkeddynamic;
01472    return res ? AST_TEST_FAIL : AST_TEST_PASS;
01473 }
01474 #endif
01475 
01476 
01477 /*!
01478  * \brief set caller and callee according to the direction
01479  * \param caller, callee, peer, chan, sense
01480  *
01481  * Detect who triggered feature and set callee/caller variables accordingly
01482 */
01483 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
01484    struct ast_channel *peer, struct ast_channel *chan, int sense)
01485 {
01486    if (sense == FEATURE_SENSE_PEER) {
01487       *caller = peer;
01488       *callee = chan;
01489    } else {
01490       *callee = peer;
01491       *caller = chan;
01492    }
01493 }
01494 
01495 static int parkcall_helper(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, struct ast_park_call_args *args)
01496 {
01497    int res = 0;
01498 
01499    if (args) {
01500       ast_debug(1, "Parkinglot specified for builtin_parkcall: %s\n", args->parkinglot->name);
01501    }
01502 
01503    /* we used to set chan's exten and priority to "s" and 1
01504       here, but this generates (in some cases) an invalid
01505       extension, and if "s" exists, could errantly
01506       cause execution of extensions you don't expect. It
01507       makes more sense to let nature take its course
01508       when chan finishes, and let the pbx do its thing
01509       and hang up when the park is over.
01510    */
01511    if (chan->_state != AST_STATE_UP)
01512       res = ast_answer(chan);
01513    if (!res)
01514       res = ast_safe_sleep(chan, 1000);
01515 
01516    if (!res) { /* one direction used to call park_call.... */
01517       struct ast_channel *parker;
01518       struct ast_channel *parkee;
01519       set_peers(&parker, &parkee, peer, chan, sense);
01520       res = masq_park_call_announce(parkee, parker, args);
01521       /* PBX should hangup zombie channel if a masquerade actually occurred (res=0) */
01522    }
01523 
01524    return res;
01525 }
01526 
01527 /*! 
01528  * \brief support routing for one touch call parking
01529  * \param chan channel parking call
01530  * \param peer channel to be parked
01531  * \param config unsed
01532  * \param code unused
01533  * \param sense feature options
01534  *
01535  * \param data
01536  * Setup channel, set return exten,priority to 's,1'
01537  * answer chan, sleep chan, park call
01538 */
01539 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
01540 {
01541    return parkcall_helper(chan, peer, config, code, sense, NULL);
01542 }
01543 
01544 /*! \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
01545    other channel during the message, so please don't use this for very long messages
01546  */
01547 static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
01548 {
01549    /* First play for caller, put other channel on auto service */
01550    if (ast_autoservice_start(callee_chan))
01551       return -1;
01552    ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
01553    if (ast_stream_and_wait(caller_chan, audiofile, "")) {
01554       ast_log(LOG_WARNING, "Failed to play automon message!\n");
01555       ast_autoservice_stop(callee_chan);
01556       return -1;
01557    }
01558    if (ast_autoservice_stop(callee_chan))
01559       return -1;
01560    /* Then play for callee, put other channel on auto service */
01561    if (ast_autoservice_start(caller_chan))
01562       return -1;
01563    ast_autoservice_ignore(caller_chan, AST_FRAME_DTMF_END);
01564    if (ast_stream_and_wait(callee_chan, audiofile, "")) {
01565       ast_log(LOG_WARNING, "Failed to play automon message !\n");
01566       ast_autoservice_stop(caller_chan);
01567       return -1;
01568    }
01569    if (ast_autoservice_stop(caller_chan))
01570       return -1;
01571    return(0);
01572 }
01573 
01574 /*!
01575  * \brief Monitor a channel by DTMF
01576  * \param chan channel requesting monitor
01577  * \param peer channel to be monitored
01578  * \param config
01579  * \param code
01580  * \param sense feature options
01581  *
01582  * \param data
01583  * Check monitor app enabled, setup channels, both caller/callee chans not null
01584  * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
01585  * \retval AST_FEATURE_RETURN_SUCCESS on success.
01586  * \retval -1 on error.
01587 */
01588 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
01589 {
01590    char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
01591    int x = 0;
01592    size_t len;
01593    struct ast_channel *caller_chan, *callee_chan;
01594    const char *automon_message_start = NULL;
01595    const char *automon_message_stop = NULL;
01596 
01597    if (!monitor_ok) {
01598       ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
01599       return -1;
01600    }
01601 
01602    if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
01603       monitor_ok = 0;
01604       ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
01605       return -1;
01606    }
01607 
01608    set_peers(&caller_chan, &callee_chan, peer, chan, sense);
01609    if (caller_chan) {   /* Find extra messages */
01610       automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
01611       automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
01612    }
01613 
01614    if (!ast_strlen_zero(courtesytone)) {  /* Play courtesy tone if configured */
01615       if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
01616          return -1;
01617       }
01618    }
01619    
01620    if (callee_chan->monitor) {
01621       ast_verb(4, "User hit '%s' to stop recording call.\n", code);
01622       if (!ast_strlen_zero(automon_message_stop)) {
01623          play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
01624       }
01625       callee_chan->monitor->stop(callee_chan, 1);
01626       return AST_FEATURE_RETURN_SUCCESS;
01627    }
01628 
01629    if (caller_chan && callee_chan) {
01630       const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
01631       const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
01632       const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
01633 
01634       if (!touch_format)
01635          touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
01636 
01637       if (!touch_monitor)
01638          touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
01639    
01640       if (!touch_monitor_prefix)
01641          touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
01642    
01643       if (touch_monitor) {
01644          len = strlen(touch_monitor) + 50;
01645          args = alloca(len);
01646          touch_filename = alloca(len);
01647          snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
01648          snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
01649       } else {
01650          caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
01651             caller_chan->caller.id.number.str, caller_chan->name));
01652          callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
01653             callee_chan->caller.id.number.str, callee_chan->name));
01654          len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
01655          args = alloca(len);
01656          touch_filename = alloca(len);
01657          snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
01658          snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
01659       }
01660 
01661       for(x = 0; x < strlen(args); x++) {
01662          if (args[x] == '/')
01663             args[x] = '-';
01664       }
01665       
01666       ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
01667 
01668       pbx_exec(callee_chan, monitor_app, args);
01669       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
01670       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
01671 
01672       if (!ast_strlen_zero(automon_message_start)) {  /* Play start message for both channels */
01673          play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
01674       }
01675    
01676       return AST_FEATURE_RETURN_SUCCESS;
01677    }
01678    
01679    ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");  
01680    return -1;
01681 }
01682 
01683 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
01684 {
01685    char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
01686    int x = 0;
01687    size_t len;
01688    struct ast_channel *caller_chan, *callee_chan;
01689    const char *mixmonitor_spy_type = "MixMonitor";
01690    int count = 0;
01691 
01692    if (!mixmonitor_ok) {
01693       ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
01694       return -1;
01695    }
01696 
01697    if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
01698       mixmonitor_ok = 0;
01699       ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
01700       return -1;
01701    }
01702 
01703    set_peers(&caller_chan, &callee_chan, peer, chan, sense);
01704 
01705    if (!ast_strlen_zero(courtesytone)) {
01706       if (ast_autoservice_start(callee_chan))
01707          return -1;
01708       ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
01709       if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
01710          ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
01711          ast_autoservice_stop(callee_chan);
01712          return -1;
01713       }
01714       if (ast_autoservice_stop(callee_chan))
01715          return -1;
01716    }
01717 
01718    ast_channel_lock(callee_chan);
01719    count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
01720    ast_channel_unlock(callee_chan);
01721 
01722    /* This means a mixmonitor is attached to the channel, running or not is unknown. */
01723    if (count > 0) {
01724       
01725       ast_verb(3, "User hit '%s' to stop recording call.\n", code);
01726 
01727       /* Make sure they are running */
01728       ast_channel_lock(callee_chan);
01729       count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
01730       ast_channel_unlock(callee_chan);
01731       if (count > 0) {
01732          if (!stopmixmonitor_ok) {
01733             ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
01734             return -1;
01735          }
01736          if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
01737             stopmixmonitor_ok = 0;
01738             ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
01739             return -1;
01740          } else {
01741             pbx_exec(callee_chan, stopmixmonitor_app, "");
01742             return AST_FEATURE_RETURN_SUCCESS;
01743          }
01744       }
01745       
01746       ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n"); 
01747    }        
01748 
01749    if (caller_chan && callee_chan) {
01750       const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
01751       const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
01752 
01753       if (!touch_format)
01754          touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
01755 
01756       if (!touch_monitor)
01757          touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
01758 
01759       if (touch_monitor) {
01760          len = strlen(touch_monitor) + 50;
01761          args = alloca(len);
01762          touch_filename = alloca(len);
01763          snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
01764          snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
01765       } else {
01766          caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
01767             caller_chan->caller.id.number.str, caller_chan->name));
01768          callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
01769             callee_chan->caller.id.number.str, callee_chan->name));
01770          len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
01771          args = alloca(len);
01772          touch_filename = alloca(len);
01773          snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
01774          snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
01775       }
01776 
01777       for( x = 0; x < strlen(args); x++) {
01778          if (args[x] == '/')
01779             args[x] = '-';
01780       }
01781 
01782       ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
01783 
01784       pbx_exec(callee_chan, mixmonitor_app, args);
01785       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
01786       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
01787       return AST_FEATURE_RETURN_SUCCESS;
01788    
01789    }
01790 
01791    ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
01792    return -1;
01793 
01794 }
01795 
01796 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
01797 {
01798    ast_verb(4, "User hit '%s' to disconnect call.\n", code);
01799    return AST_FEATURE_RETURN_HANGUP;
01800 }
01801 
01802 static int finishup(struct ast_channel *chan)
01803 {
01804    ast_indicate(chan, AST_CONTROL_UNHOLD);
01805 
01806    return ast_autoservice_stop(chan);
01807 }
01808 
01809 /*!
01810  * \brief Find the context for the transfer
01811  * \param transferer
01812  * \param transferee
01813  * 
01814  * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
01815  * \return a context string
01816 */
01817 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
01818 {
01819    const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
01820    if (ast_strlen_zero(s)) {
01821       s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
01822    }
01823    if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
01824       s = transferer->macrocontext;
01825    }
01826    if (ast_strlen_zero(s)) {
01827       s = transferer->context;
01828    }
01829    return s;  
01830 }
01831 
01832 /*!
01833  * \brief Blind transfer user to another extension
01834  * \param chan channel to be transfered
01835  * \param peer channel initiated blind transfer
01836  * \param config
01837  * \param code
01838  * \param data
01839  * \param sense  feature options
01840  * 
01841  * Place chan on hold, check if transferred to parkinglot extension,
01842  * otherwise check extension exists and transfer caller.
01843  * \retval AST_FEATURE_RETURN_SUCCESS.
01844  * \retval -1 on failure.
01845 */
01846 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
01847 {
01848    struct ast_channel *transferer;
01849    struct ast_channel *transferee;
01850    const char *transferer_real_context;
01851    struct ast_parkinglot *found_lot = NULL;
01852    char xferto[256];
01853    int res, parkstatus = 0;
01854 
01855    set_peers(&transferer, &transferee, peer, chan, sense);
01856    transferer_real_context = real_ctx(transferer, transferee);
01857    /* Start autoservice on chan while we talk to the originator */
01858    ast_autoservice_start(transferee);
01859    ast_autoservice_ignore(transferee, AST_FRAME_DTMF_END);
01860    ast_indicate(transferee, AST_CONTROL_HOLD);
01861 
01862    memset(xferto, 0, sizeof(xferto));
01863 
01864    /* Transfer */
01865    res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
01866    if (res < 0) {
01867       finishup(transferee);
01868       return -1; /* error ? */
01869    }
01870    if (res > 0)   /* If they've typed a digit already, handle it */
01871       xferto[0] = (char) res;
01872 
01873    ast_stopstream(transferer);
01874    res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
01875    if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
01876       finishup(transferee);
01877       return res;
01878    }
01879 
01880    found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
01881    if (found_lot) {
01882       struct ast_park_call_args args = {
01883          .parkinglot = found_lot,
01884       };
01885       res = finishup(transferee);
01886       if (res)
01887          res = -1;
01888       else if (!(parkstatus = masq_park_call_announce(transferee, transferer, &args))) {  /* success */
01889          /* We return non-zero, but tell the PBX not to hang the channel when
01890             the thread dies -- We have to be careful now though.  We are responsible for 
01891             hanging up the channel, else it will never be hung up! */
01892 
01893          return 0;
01894       } else {
01895          ast_log(LOG_WARNING, "Unable to park call %s, parkstatus = %d\n", transferee->name, parkstatus);
01896       }
01897       /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
01898    } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1,
01899       S_COR(transferer->caller.id.number.valid, transferer->caller.id.number.str, NULL))) {
01900       ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
01901       pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
01902       pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
01903       res=finishup(transferee);
01904       if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
01905          transferer->cdr=ast_cdr_alloc();
01906          if (transferer->cdr) {
01907             ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
01908             ast_cdr_start(transferer->cdr);
01909          }
01910       }
01911       if (transferer->cdr) {
01912          struct ast_cdr *swap = transferer->cdr;
01913          ast_log(LOG_DEBUG,"transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
01914                transferer->name, transferee->name, transferer->cdr->lastapp, transferer->cdr->lastdata, 
01915                transferer->cdr->channel, transferer->cdr->dstchannel);
01916          ast_log(LOG_DEBUG,"TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
01917                transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel, transferee->cdr->dstchannel);
01918          ast_log(LOG_DEBUG,"transferer_real_context=%s; xferto=%s\n", transferer_real_context, xferto);
01919          /* swap cdrs-- it will save us some time & work */
01920          transferer->cdr = transferee->cdr;
01921          transferee->cdr = swap;
01922       }
01923       if (!transferee->pbx) {
01924          /* Doh!  Use our handy async_goto functions */
01925          ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
01926                         ,transferee->name, xferto, transferer_real_context);
01927          if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
01928             ast_log(LOG_WARNING, "Async goto failed :-(\n");
01929       } else {
01930          /* Set the channel's new extension, since it exists, using transferer context */
01931          ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
01932          ast_log(LOG_DEBUG,"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
01933          if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
01934             ast_channel_update_connected_line(transferer, &transferer->connected, NULL);
01935          }
01936          set_c_e_p(transferee, transferer_real_context, xferto, 0);
01937       }
01938       check_goto_on_transfer(transferer);
01939       return res;
01940    } else {
01941       ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
01942    }
01943    if (parkstatus != AST_FEATURE_RETURN_PARKFAILED && ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) { /* Play 'extension does not exist' */
01944       finishup(transferee);
01945       return -1;
01946    }
01947    ast_stopstream(transferer);
01948    res = finishup(transferee);
01949    if (res) {
01950       ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
01951       return res;
01952    }
01953    return AST_FEATURE_RETURN_SUCCESS;
01954 }
01955 
01956 /*!
01957  * \brief make channels compatible
01958  * \param c
01959  * \param newchan
01960  * \retval 0 on success.
01961  * \retval -1 on failure.
01962 */
01963 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
01964 {
01965    if (ast_channel_make_compatible(c, newchan) < 0) {
01966       ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
01967          c->name, newchan->name);
01968       ast_hangup(newchan);
01969       return -1;
01970    }
01971    return 0;
01972 }
01973 
01974 /*!
01975  * \internal
01976  * \brief Builtin attended transfer failed cleanup.
01977  * \since 1.10
01978  *
01979  * \param transferee Party A in the transfer.
01980  * \param transferer Party B in the transfer.
01981  * \param connected_line Saved connected line info about party A.
01982  *
01983  * \note The connected_line data is freed.
01984  *
01985  * \return Nothing
01986  */
01987 static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
01988 {
01989    finishup(transferee);
01990 
01991    /*
01992     * Restore party B connected line info about party A.
01993     *
01994     * Party B was the caller to party C and is the last known mode
01995     * for party B.
01996     */
01997    if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
01998       ast_channel_update_connected_line(transferer, connected_line, NULL);
01999    }
02000    ast_party_connected_line_free(connected_line);
02001 }
02002 
02003 /*!
02004  * \brief Attended transfer
02005  * \param chan transfered user
02006  * \param peer person transfering call
02007  * \param config
02008  * \param code
02009  * \param sense feature options
02010  *
02011  * \param data
02012  * Get extension to transfer to, if you cannot generate channel (or find extension)
02013  * return to host channel. After called channel answered wait for hangup of transferer,
02014  * bridge call between transfer peer (taking them off hold) to attended transfer channel.
02015  *
02016  * \return -1 on failure
02017 */
02018 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
02019 {
02020    struct ast_channel *transferer;/* Party B */
02021    struct ast_channel *transferee;/* Party A */
02022    const char *transferer_real_context;
02023    char xferto[256] = "";
02024    int res;
02025    int outstate=0;
02026    struct ast_channel *newchan;
02027    struct ast_channel *xferchan;
02028    struct ast_bridge_thread_obj *tobj;
02029    struct ast_bridge_config bconfig;
02030    int l;
02031    struct ast_party_connected_line connected_line;
02032    struct ast_datastore *features_datastore;
02033    struct ast_dial_features *dialfeatures = NULL;
02034    struct ast_parkinglot *parkinglot;
02035    char *transferer_tech;
02036    char *transferer_name;
02037    char *transferer_name_orig;
02038    char *dash;
02039 
02040    ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
02041    set_peers(&transferer, &transferee, peer, chan, sense);
02042    transferer_real_context = real_ctx(transferer, transferee);
02043 
02044    /* Start autoservice on transferee while we talk to the transferer */
02045    ast_autoservice_start(transferee);
02046    ast_indicate(transferee, AST_CONTROL_HOLD);
02047 
02048    /* Transfer */
02049    res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
02050    if (res < 0) {
02051       finishup(transferee);
02052       return -1;
02053    }
02054    if (res > 0) /* If they've typed a digit already, handle it */
02055       xferto[0] = (char) res;
02056 
02057    /* this is specific of atxfer */
02058    res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
02059    if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
02060       finishup(transferee);
02061       return -1;
02062    }
02063    l = strlen(xferto);
02064    if (res == 0) {
02065       if (l) {
02066          ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
02067             xferto, transferer_real_context);
02068       } else {
02069          /* Does anyone care about this case? */
02070          ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
02071       }
02072       ast_stream_and_wait(transferer, "pbx-invalid", "");
02073       finishup(transferee);
02074       return AST_FEATURE_RETURN_SUCCESS;
02075    }
02076 
02077    /* If we are attended transfering to parking, just use parkcall_helper instead of trying to track all of
02078     * the different variables for handling this properly with a builtin_atxfer */
02079    parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
02080    if (parkinglot) {
02081       struct ast_park_call_args args = {
02082          .parkinglot = parkinglot,
02083       };
02084       finishup(transferee);
02085       return parkcall_helper(chan, peer, config, code, sense, &args);
02086    }
02087 
02088    /* Append context to dialed transfer number. */
02089    snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
02090 
02091    /* If we are performing an attended transfer and we have two channels involved then
02092       copy sound file information to play upon attended transfer completion */
02093    if (transferee) {
02094       const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
02095       const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
02096 
02097       if (!ast_strlen_zero(chan1_attended_sound)) {
02098          pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
02099       }
02100       if (!ast_strlen_zero(chan2_attended_sound)) {
02101          pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
02102       }
02103    }
02104 
02105    /* Extract redial transferer information from the channel name. */
02106    transferer_name_orig = ast_strdupa(transferer->name);
02107    transferer_name = ast_strdupa(transferer_name_orig);
02108    transferer_tech = strsep(&transferer_name, "/");
02109    dash = strrchr(transferer_name, '-');
02110    if (dash) {
02111       /* Trim off channel name sequence/serial number. */
02112       *dash = '\0';
02113    }
02114 
02115    /* Stop autoservice so we can monitor all parties involved in the transfer. */
02116    if (ast_autoservice_stop(transferee) < 0) {
02117       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02118       return -1;
02119    }
02120 
02121    /* Save connected line info for party B about party A in case transfer fails. */
02122    ast_party_connected_line_init(&connected_line);
02123    ast_channel_lock(transferer);
02124    ast_party_connected_line_copy(&connected_line, &transferer->connected);
02125    ast_channel_unlock(transferer);
02126    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02127 
02128    /* Dial party C */
02129    newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
02130       transferee, "Local", ast_best_codec(transferer->nativeformats), xferto,
02131       atxfernoanswertimeout, &outstate, transferer->language);
02132    ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
02133 
02134    if (!ast_check_hangup(transferer)) {
02135       int hangup_dont = 0;
02136 
02137       /* Transferer (party B) is up */
02138       ast_debug(1, "Actually doing an attended transfer.\n");
02139 
02140       /* Start autoservice on transferee while the transferer deals with party C. */
02141       ast_autoservice_start(transferee);
02142 
02143       ast_indicate(transferer, -1);
02144       if (!newchan) {
02145          /* any reason besides user requested cancel and busy triggers the failed sound */
02146          switch (outstate) {
02147          case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
02148          case AST_CONTROL_BUSY:
02149          case AST_CONTROL_CONGESTION:
02150             if (ast_stream_and_wait(transferer, xfersound, "")) {
02151                ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02152             }
02153             break;
02154          default:
02155             if (ast_stream_and_wait(transferer, xferfailsound, "")) {
02156                ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
02157             }
02158             break;
02159          }
02160          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02161          return AST_FEATURE_RETURN_SUCCESS;
02162       }
02163 
02164       if (check_compat(transferer, newchan)) {
02165          if (ast_stream_and_wait(transferer, xferfailsound, "")) {
02166             ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
02167          }
02168          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02169          return AST_FEATURE_RETURN_SUCCESS;
02170       }
02171       memset(&bconfig,0,sizeof(struct ast_bridge_config));
02172       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
02173       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
02174 
02175       /* ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we don't
02176          want that to happen here because we're also in another bridge already
02177        */
02178       if (ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)) {
02179          hangup_dont = 1;
02180       }
02181       /* Let party B and party C talk as long as they want. */
02182       ast_bridge_call(transferer, newchan, &bconfig);
02183       if (hangup_dont) {
02184          ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
02185       }
02186 
02187       if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
02188          ast_hangup(newchan);
02189          if (ast_stream_and_wait(transferer, xfersound, "")) {
02190             ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02191          }
02192          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02193          return AST_FEATURE_RETURN_SUCCESS;
02194       }
02195 
02196       /* Transferer (party B) is confirmed hung up at this point. */
02197       if (check_compat(transferee, newchan)) {
02198          finishup(transferee);
02199          ast_party_connected_line_free(&connected_line);
02200          return -1;
02201       }
02202 
02203       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02204       if ((ast_autoservice_stop(transferee) < 0)
02205          || (ast_waitfordigit(transferee, 100) < 0)
02206          || (ast_waitfordigit(newchan, 100) < 0)
02207          || ast_check_hangup(transferee)
02208          || ast_check_hangup(newchan)) {
02209          ast_hangup(newchan);
02210          ast_party_connected_line_free(&connected_line);
02211          return -1;
02212       }
02213    } else if (!ast_check_hangup(transferee)) {
02214       /* Transferer (party B) has hung up at this point.  Doing blonde transfer. */
02215       ast_debug(1, "Actually doing a blonde transfer.\n");
02216 
02217       if (!newchan && !atxferdropcall) {
02218          /* Party C is not available, try to call party B back. */
02219          unsigned int tries = 0;
02220 
02221          if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
02222             ast_log(LOG_WARNING,
02223                "Transferer channel name: '%s' cannot be used for callback.\n",
02224                transferer_name_orig);
02225             ast_indicate(transferee, AST_CONTROL_UNHOLD);
02226             ast_party_connected_line_free(&connected_line);
02227             return -1;
02228          }
02229 
02230          tries = 0;
02231          for (;;) {
02232             /* Try to get party B back. */
02233             ast_debug(1, "We're trying to callback %s/%s\n",
02234                transferer_tech, transferer_name);
02235             newchan = feature_request_and_dial(transferer, transferer_name_orig,
02236                transferee, transferee, transferer_tech,
02237                ast_best_codec(transferee->nativeformats), transferer_name,
02238                atxfernoanswertimeout, &outstate, transferer->language);
02239             ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
02240                !!newchan, outstate);
02241             if (newchan || ast_check_hangup(transferee)) {
02242                break;
02243             }
02244 
02245             ++tries;
02246             if (atxfercallbackretries <= tries) {
02247                /* No more callback tries remaining. */
02248                break;
02249             }
02250 
02251             if (atxferloopdelay) {
02252                /* Transfer failed, sleeping */
02253                ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
02254                   atxferloopdelay);
02255                ast_safe_sleep(transferee, atxferloopdelay);
02256                if (ast_check_hangup(transferee)) {
02257                   ast_party_connected_line_free(&connected_line);
02258                   return -1;
02259                }
02260             }
02261 
02262             /* Retry dialing party C. */
02263             ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
02264             newchan = feature_request_and_dial(transferer, transferer_name_orig,
02265                transferer, transferee, "Local",
02266                ast_best_codec(transferee->nativeformats), xferto,
02267                atxfernoanswertimeout, &outstate, transferer->language);
02268             ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
02269                !!newchan, outstate);
02270             if (newchan || ast_check_hangup(transferee)) {
02271                break;
02272             }
02273          }
02274       }
02275       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02276       if (!newchan) {
02277          /* No party C or could not callback party B. */
02278          ast_party_connected_line_free(&connected_line);
02279          return -1;
02280       }
02281 
02282       /* newchan is up, we should prepare transferee and bridge them */
02283       if (ast_check_hangup(newchan)) {
02284          ast_hangup(newchan);
02285          ast_party_connected_line_free(&connected_line);
02286          return -1;
02287       }
02288       if (check_compat(transferee, newchan)) {
02289          ast_party_connected_line_free(&connected_line);
02290          return -1;
02291       }
02292    } else {
02293       /*
02294        * Both the transferer and transferee have hungup.  If newchan
02295        * is up, hang it up as it has no one to talk to.
02296        */
02297       ast_debug(1, "Everyone is hungup.\n");
02298       if (newchan) {
02299          ast_hangup(newchan);
02300       }
02301       ast_party_connected_line_free(&connected_line);
02302       return -1;
02303    }
02304 
02305    /* Initiate the channel transfer of party A to party C (or recalled party B). */
02306    ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
02307 
02308    xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", transferee->linkedid, 0, "Transfered/%s", transferee->name);
02309    if (!xferchan) {
02310       ast_hangup(newchan);
02311       ast_party_connected_line_free(&connected_line);
02312       return -1;
02313    }
02314 
02315    /* Give party A a momentary ringback tone during transfer. */
02316    xferchan->visible_indication = AST_CONTROL_RINGING;
02317 
02318    /* Make formats okay */
02319    xferchan->readformat = transferee->readformat;
02320    xferchan->writeformat = transferee->writeformat;
02321 
02322    ast_channel_masquerade(xferchan, transferee);
02323    ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
02324    xferchan->_state = AST_STATE_UP;
02325    ast_clear_flag(xferchan, AST_FLAGS_ALL);
02326 
02327    /* Do the masquerade manually to make sure that is is completed. */
02328    ast_do_masquerade(xferchan);
02329 
02330    newchan->_state = AST_STATE_UP;
02331    ast_clear_flag(newchan, AST_FLAGS_ALL);
02332    tobj = ast_calloc(1, sizeof(*tobj));
02333    if (!tobj) {
02334       ast_hangup(xferchan);
02335       ast_hangup(newchan);
02336       ast_party_connected_line_free(&connected_line);
02337       return -1;
02338    }
02339 
02340    ast_channel_lock(newchan);
02341    if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
02342       dialfeatures = features_datastore->data;
02343    }
02344    ast_channel_unlock(newchan);
02345 
02346    if (dialfeatures) {
02347       /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
02348          I don't currently understand, the abilities of newchan seem to be stored on the caller side */
02349       ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
02350       dialfeatures = NULL;
02351    }
02352 
02353    ast_channel_lock(xferchan);
02354    if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
02355       dialfeatures = features_datastore->data;
02356    }
02357    ast_channel_unlock(xferchan);
02358 
02359    if (dialfeatures) {
02360       ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
02361    }
02362 
02363    tobj->chan = newchan;
02364    tobj->peer = xferchan;
02365    tobj->bconfig = *config;
02366 
02367    if (tobj->bconfig.end_bridge_callback_data_fixup) {
02368       tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
02369    }
02370 
02371    /*
02372     * xferchan is transferee, and newchan is the transfer target
02373     * So...in a transfer, who is the caller and who is the callee?
02374     *
02375     * When the call is originally made, it is clear who is caller and callee.
02376     * When a transfer occurs, it is my humble opinion that the transferee becomes
02377     * the caller, and the transfer target is the callee.
02378     *
02379     * The problem is that these macros were set with the intention of the original
02380     * caller and callee taking those roles.  A transfer can totally mess things up,
02381     * to be technical.  What sucks even more is that you can't effectively change
02382     * the macros in the dialplan during the call from the transferer to the transfer
02383     * target because the transferee is stuck with whatever role he originally had.
02384     *
02385     * I think the answer here is just to make sure that it is well documented that
02386     * during a transfer, the transferee is the "caller" and the transfer target
02387     * is the "callee."
02388     *
02389     * This means that if party B calls party A, and party B transfers party A to
02390     * party C, then A has switched roles for the call.  Now party A will have the
02391     * caller macro called on his channel instead of the callee macro.
02392     *
02393     * Luckily, the method by which the party B to party C bridge is
02394     * launched above ensures that the transferee is the "chan" on
02395     * the bridge and the transfer target is the "peer," so my idea
02396     * for the roles post-transfer does not require extensive code
02397     * changes.
02398     */
02399 
02400    /* Transfer party C connected line to party A */
02401    ast_channel_lock(transferer);
02402    /*
02403     * Due to a limitation regarding when callerID is set on a Local channel,
02404     * we use the transferer's connected line information here.
02405     */
02406    ast_party_connected_line_copy(&connected_line, &transferer->connected);
02407    ast_channel_unlock(transferer);
02408    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02409    if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
02410       ast_channel_update_connected_line(xferchan, &connected_line, NULL);
02411    }
02412 
02413    /* Transfer party A connected line to party C */
02414    ast_channel_lock(xferchan);
02415    ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
02416    ast_channel_unlock(xferchan);
02417    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02418    if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
02419       ast_channel_update_connected_line(newchan, &connected_line, NULL);
02420    }
02421 
02422    if (ast_stream_and_wait(newchan, xfersound, ""))
02423       ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02424    bridge_call_thread_launch(tobj);
02425 
02426    ast_party_connected_line_free(&connected_line);
02427    return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
02428 }
02429 
02430 /* add atxfer and automon as undefined so you can only use em if you configure them */
02431 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
02432 
02433 AST_RWLOCK_DEFINE_STATIC(features_lock);
02434 
02435 static struct ast_call_feature builtin_features[] = {
02436    { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02437    { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02438    { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02439    { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02440    { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02441    { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02442 };
02443 
02444 
02445 static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
02446 
02447 /*! \brief register new feature into feature_list*/
02448 void ast_register_feature(struct ast_call_feature *feature)
02449 {
02450    if (!feature) {
02451       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
02452       return;
02453    }
02454   
02455    AST_RWLIST_WRLOCK(&feature_list);
02456    AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
02457    AST_RWLIST_UNLOCK(&feature_list);
02458 
02459    ast_verb(2, "Registered Feature '%s'\n",feature->sname);
02460 }
02461 
02462 /*! 
02463  * \brief Add new feature group
02464  * \param fgname feature group name.
02465  *
02466  * Add new feature group to the feature group list insert at head of list.
02467  * \note This function MUST be called while feature_groups is locked.
02468 */
02469 static struct feature_group *register_group(const char *fgname)
02470 {
02471    struct feature_group *fg;
02472 
02473    if (!fgname) {
02474       ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
02475       return NULL;
02476    }
02477 
02478    if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
02479       return NULL;
02480    }
02481 
02482    ast_string_field_set(fg, gname, fgname);
02483 
02484    AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
02485 
02486    ast_verb(2, "Registered group '%s'\n", fg->gname);
02487 
02488    return fg;
02489 }
02490 
02491 /*! 
02492  * \brief Add feature to group
02493  * \param fg feature group
02494  * \param exten
02495  * \param feature feature to add.
02496  *
02497  * Check fg and feature specified, add feature to list
02498  * \note This function MUST be called while feature_groups is locked. 
02499 */
02500 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
02501 {
02502    struct feature_group_exten *fge;
02503 
02504    if (!fg) {
02505       ast_log(LOG_NOTICE, "You didn't pass a group!\n");
02506       return;
02507    }
02508 
02509    if (!feature) {
02510       ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
02511       return;
02512    }
02513 
02514    if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
02515       return;
02516    }
02517 
02518    ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
02519 
02520    fge->feature = feature;
02521 
02522    AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
02523 
02524    ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
02525                feature->sname, fg->gname, fge->exten);
02526 }
02527 
02528 void ast_unregister_feature(struct ast_call_feature *feature)
02529 {
02530    if (!feature) {
02531       return;
02532    }
02533 
02534    AST_RWLIST_WRLOCK(&feature_list);
02535    AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
02536    AST_RWLIST_UNLOCK(&feature_list);
02537 
02538    ast_free(feature);
02539 }
02540 
02541 /*! \brief Remove all features in the list */
02542 static void ast_unregister_features(void)
02543 {
02544    struct ast_call_feature *feature;
02545 
02546    AST_RWLIST_WRLOCK(&feature_list);
02547    while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
02548       ast_free(feature);
02549    }
02550    AST_RWLIST_UNLOCK(&feature_list);
02551 }
02552 
02553 /*! \brief find a call feature by name */
02554 static struct ast_call_feature *find_dynamic_feature(const char *name)
02555 {
02556    struct ast_call_feature *tmp;
02557 
02558    AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
02559       if (!strcasecmp(tmp->sname, name)) {
02560          break;
02561       }
02562    }
02563 
02564    return tmp;
02565 }
02566 
02567 /*! \brief Remove all feature groups in the list */
02568 static void ast_unregister_groups(void)
02569 {
02570    struct feature_group *fg;
02571    struct feature_group_exten *fge;
02572 
02573    AST_RWLIST_WRLOCK(&feature_groups);
02574    while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
02575       while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
02576          ast_string_field_free_memory(fge);
02577          ast_free(fge);
02578       }
02579 
02580       ast_string_field_free_memory(fg);
02581       ast_free(fg);
02582    }
02583    AST_RWLIST_UNLOCK(&feature_groups);
02584 }
02585 
02586 /*! 
02587  * \brief Find a group by name 
02588  * \param name feature name
02589  * \retval feature group on success.
02590  * \retval NULL on failure.
02591 */
02592 static struct feature_group *find_group(const char *name)
02593 {
02594    struct feature_group *fg = NULL;
02595 
02596    AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
02597       if (!strcasecmp(fg->gname, name))
02598          break;
02599    }
02600 
02601    return fg;
02602 }
02603 
02604 void ast_rdlock_call_features(void)
02605 {
02606    ast_rwlock_rdlock(&features_lock);
02607 }
02608 
02609 void ast_unlock_call_features(void)
02610 {
02611    ast_rwlock_unlock(&features_lock);
02612 }
02613 
02614 struct ast_call_feature *ast_find_call_feature(const char *name)
02615 {
02616    int x;
02617    for (x = 0; x < FEATURES_COUNT; x++) {
02618       if (!strcasecmp(name, builtin_features[x].sname))
02619          return &builtin_features[x];
02620    }
02621    return NULL;
02622 }
02623 
02624 /*!
02625  * \brief exec an app by feature 
02626  * \param chan,peer,config,code,sense,data
02627  *
02628  * Find a feature, determine which channel activated
02629  * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
02630  * \retval -1 error.
02631  * \retval -2 when an application cannot be found.
02632 */
02633 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)
02634 {
02635    struct ast_app *app;
02636    struct ast_call_feature *feature = data;
02637    struct ast_channel *work, *idle;
02638    int res;
02639 
02640    if (!feature) { /* shouldn't ever happen! */
02641       ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
02642       return -1; 
02643    }
02644 
02645    if (sense == FEATURE_SENSE_CHAN) {
02646       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
02647          return AST_FEATURE_RETURN_KEEPTRYING;
02648       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
02649          work = chan;
02650          idle = peer;
02651       } else {
02652          work = peer;
02653          idle = chan;
02654       }
02655    } else {
02656       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
02657          return AST_FEATURE_RETURN_KEEPTRYING;
02658       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
02659          work = peer;
02660          idle = chan;
02661       } else {
02662          work = chan;
02663          idle = peer;
02664       }
02665    }
02666 
02667    if (!(app = pbx_findapp(feature->app))) {
02668       ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
02669       return -2;
02670    }
02671 
02672    ast_autoservice_start(idle);
02673    ast_autoservice_ignore(idle, AST_FRAME_DTMF_END);
02674    
02675    if(work && idle) {
02676       pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", idle->name);
02677       pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", work->name);
02678       pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
02679       pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
02680    }
02681 
02682    if (!ast_strlen_zero(feature->moh_class))
02683       ast_moh_start(idle, feature->moh_class, NULL);
02684 
02685    res = pbx_exec(work, app, feature->app_args);
02686 
02687    if (!ast_strlen_zero(feature->moh_class))
02688       ast_moh_stop(idle);
02689 
02690    ast_autoservice_stop(idle);
02691 
02692    if (res) {
02693       return AST_FEATURE_RETURN_SUCCESSBREAK;
02694    }
02695    return AST_FEATURE_RETURN_SUCCESS;  /*! \todo XXX should probably return res */
02696 }
02697 
02698 static void unmap_features(void)
02699 {
02700    int x;
02701 
02702    ast_rwlock_wrlock(&features_lock);
02703    for (x = 0; x < FEATURES_COUNT; x++)
02704       strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
02705    ast_rwlock_unlock(&features_lock);
02706 }
02707 
02708 static int remap_feature(const char *name, const char *value)
02709 {
02710    int x, res = -1;
02711 
02712    ast_rwlock_wrlock(&features_lock);
02713    for (x = 0; x < FEATURES_COUNT; x++) {
02714       if (strcasecmp(builtin_features[x].sname, name))
02715          continue;
02716 
02717       ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
02718       res = 0;
02719       break;
02720    }
02721    ast_rwlock_unlock(&features_lock);
02722 
02723    return res;
02724 }
02725 
02726 /*!
02727  * \brief Helper function for feature_interpret and ast_feature_detect
02728  * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
02729  *
02730  * Lock features list, browse for code, unlock list
02731  * If a feature is found and the operation variable is set, that feature's
02732  * operation is executed.  The first feature found is copied to the feature parameter.
02733  * \retval res on success.
02734  * \retval -1 on failure.
02735 */
02736 static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
02737    struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
02738    struct ast_flags *features, int operation, struct ast_call_feature *feature)
02739 {
02740    int x;
02741    struct feature_group *fg = NULL;
02742    struct feature_group_exten *fge;
02743    struct ast_call_feature *tmpfeature;
02744    char *tmp, *tok;
02745    int res = AST_FEATURE_RETURN_PASSDIGITS;
02746    int feature_detected = 0;
02747 
02748    if (!(peer && chan && config) && operation) {
02749       return -1; /* can not run feature operation */
02750    }
02751 
02752    ast_rwlock_rdlock(&features_lock);
02753    for (x = 0; x < FEATURES_COUNT; x++) {
02754       if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
02755           !ast_strlen_zero(builtin_features[x].exten)) {
02756          /* Feature is up for consideration */
02757          if (!strcmp(builtin_features[x].exten, code)) {
02758             ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
02759             if (operation) {
02760                res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
02761             }
02762             memcpy(feature, &builtin_features[x], sizeof(feature));
02763             feature_detected = 1;
02764             break;
02765          } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
02766             if (res == AST_FEATURE_RETURN_PASSDIGITS)
02767                res = AST_FEATURE_RETURN_STOREDIGITS;
02768          }
02769       }
02770    }
02771    ast_rwlock_unlock(&features_lock);
02772 
02773    if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
02774       return res;
02775    }
02776 
02777    tmp = dynamic_features_buf;
02778 
02779    while ((tok = strsep(&tmp, "#"))) {
02780       AST_RWLIST_RDLOCK(&feature_groups);
02781 
02782       fg = find_group(tok);
02783 
02784       if (fg) {
02785          AST_LIST_TRAVERSE(&fg->features, fge, entry) {
02786             if (!strcmp(fge->exten, code)) {
02787                if (operation) {
02788                   res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
02789                }
02790                memcpy(feature, fge->feature, sizeof(feature));
02791                if (res != AST_FEATURE_RETURN_KEEPTRYING) {
02792                   AST_RWLIST_UNLOCK(&feature_groups);
02793                   break;
02794                }
02795                res = AST_FEATURE_RETURN_PASSDIGITS;
02796             } else if (!strncmp(fge->exten, code, strlen(code))) {
02797                res = AST_FEATURE_RETURN_STOREDIGITS;
02798             }
02799          }
02800          if (fge) {
02801             break;
02802          }
02803       }
02804 
02805       AST_RWLIST_UNLOCK(&feature_groups);
02806 
02807       AST_RWLIST_RDLOCK(&feature_list);
02808 
02809       if (!(tmpfeature = find_dynamic_feature(tok))) {
02810          AST_RWLIST_UNLOCK(&feature_list);
02811          continue;
02812       }
02813 
02814       /* Feature is up for consideration */
02815       if (!strcmp(tmpfeature->exten, code)) {
02816          ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
02817          if (operation) {
02818             res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
02819          }
02820          memcpy(feature, tmpfeature, sizeof(feature));
02821          if (res != AST_FEATURE_RETURN_KEEPTRYING) {
02822             AST_RWLIST_UNLOCK(&feature_list);
02823             break;
02824          }
02825          res = AST_FEATURE_RETURN_PASSDIGITS;
02826       } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
02827          res = AST_FEATURE_RETURN_STOREDIGITS;
02828 
02829       AST_RWLIST_UNLOCK(&feature_list);
02830    }
02831 
02832    return res;
02833 }
02834 
02835 /*!
02836  * \brief Check the dynamic features
02837  * \param chan,peer,config,code,sense
02838  *
02839  * \retval res on success.
02840  * \retval -1 on failure.
02841 */
02842 
02843 static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense) {
02844 
02845    char dynamic_features_buf[128];
02846    const char *peer_dynamic_features, *chan_dynamic_features;
02847    struct ast_flags features;
02848    struct ast_call_feature feature;
02849    if (sense == FEATURE_SENSE_CHAN) {
02850       ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
02851    }
02852    else {
02853       ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
02854    }
02855 
02856    ast_channel_lock(peer);
02857    peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
02858    ast_channel_unlock(peer);
02859 
02860    ast_channel_lock(chan);
02861    chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
02862    ast_channel_unlock(chan);
02863 
02864    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,""));
02865 
02866    ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
02867 
02868    return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, 1, &feature);
02869 }
02870 
02871 
02872 int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
02873 
02874    return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature);
02875 }
02876 
02877 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
02878 {
02879    int x;
02880 
02881    ast_clear_flag(config, AST_FLAGS_ALL);
02882 
02883    ast_rwlock_rdlock(&features_lock);
02884    for (x = 0; x < FEATURES_COUNT; x++) {
02885       if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
02886          continue;
02887 
02888       if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
02889          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
02890 
02891       if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
02892          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
02893    }
02894    ast_rwlock_unlock(&features_lock);
02895 
02896    if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
02897       const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
02898 
02899       if (dynamic_features) {
02900          char *tmp = ast_strdupa(dynamic_features);
02901          char *tok;
02902          struct ast_call_feature *feature;
02903 
02904          /* while we have a feature */
02905          while ((tok = strsep(&tmp, "#"))) {
02906             struct feature_group *fg;
02907 
02908             AST_RWLIST_RDLOCK(&feature_groups);
02909             AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
02910                struct feature_group_exten *fge;
02911 
02912                AST_LIST_TRAVERSE(&fg->features, fge, entry) {
02913                   if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLER)) {
02914                      ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
02915                   }
02916                   if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLEE)) {
02917                      ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
02918                   }
02919                }
02920             }
02921             AST_RWLIST_UNLOCK(&feature_groups);
02922 
02923             AST_RWLIST_RDLOCK(&feature_list);
02924             if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
02925                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
02926                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
02927                }
02928                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE)) {
02929                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
02930                }
02931             }
02932             AST_RWLIST_UNLOCK(&feature_list);
02933          }
02934       }
02935    }
02936 }
02937 
02938 /*!
02939  * \internal
02940  * \brief Get feature and dial.
02941  *
02942  * \param caller Channel to represent as the calling channel for the dialed channel.
02943  * \param caller_name Original caller channel name.
02944  * \param requestor Channel to say is requesting the dial (usually the caller).
02945  * \param transferee Channel that the dialed channel will be transferred to.
02946  * \param type Channel technology type to dial.
02947  * \param format Codec formats for dialed channel.
02948  * \param data Dialed channel extra parameters for ast_request() and ast_call().
02949  * \param timeout Time limit for dialed channel to answer in ms. Must be greater than zero.
02950  * \param outstate Status of dialed channel if unsuccessful.
02951  * \param language Language of the caller.
02952  *
02953  * \note
02954  * outstate can be:
02955  * 0, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION,
02956  * AST_CONTROL_ANSWER, or AST_CONTROL_UNHOLD.  If
02957  * AST_CONTROL_UNHOLD then the caller channel cancelled the
02958  * transfer or the dialed channel did not answer before the
02959  * timeout.
02960  *
02961  * \details
02962  * Request channel, set channel variables, initiate call,
02963  * check if they want to disconnect, go into loop, check if timeout has elapsed,
02964  * check if person to be transfered hung up, check for answer break loop,
02965  * set cdr return channel.
02966  *
02967  * \retval Channel Connected channel for transfer.
02968  * \retval NULL on failure to get third party connected.
02969  *
02970  * \note This is similar to __ast_request_and_dial() in channel.c
02971  */
02972 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
02973    const char *caller_name, struct ast_channel *requestor,
02974    struct ast_channel *transferee, const char *type, int format, void *data,
02975    int timeout, int *outstate, const char *language)
02976 {
02977    int state = 0;
02978    int cause = 0;
02979    int to;
02980    int caller_hungup;
02981    int transferee_hungup;
02982    struct ast_channel *chan;
02983    struct ast_channel *monitor_chans[3];
02984    struct ast_channel *active_channel;
02985    int res;
02986    int ready = 0;
02987    struct timeval started;
02988    int x, len = 0;
02989    char *disconnect_code = NULL, *dialed_code = NULL;
02990    struct ast_frame *f;
02991    AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
02992 
02993    caller_hungup = ast_check_hangup(caller);
02994 
02995    if (!(chan = ast_request(type, format, requestor, data, &cause))) {
02996       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
02997       switch (cause) {
02998       case AST_CAUSE_BUSY:
02999          state = AST_CONTROL_BUSY;
03000          break;
03001       case AST_CAUSE_CONGESTION:
03002          state = AST_CONTROL_CONGESTION;
03003          break;
03004       default:
03005          state = 0;
03006          break;
03007       }
03008       goto done;
03009    }
03010 
03011    ast_string_field_set(chan, language, language);
03012    ast_channel_inherit_variables(caller, chan);
03013    pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
03014 
03015    ast_channel_lock(chan);
03016    ast_connected_line_copy_from_caller(&chan->connected, &requestor->caller);
03017    ast_channel_unlock(chan);
03018 
03019    if (ast_call(chan, data, timeout)) {
03020       ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
03021       switch (chan->hangupcause) {
03022       case AST_CAUSE_BUSY:
03023          state = AST_CONTROL_BUSY;
03024          break;
03025       case AST_CAUSE_CONGESTION:
03026          state = AST_CONTROL_CONGESTION;
03027          break;
03028       default:
03029          state = 0;
03030          break;
03031       }
03032       goto done;
03033    }
03034 
03035    /* support dialing of the featuremap disconnect code while performing an attended tranfer */
03036    ast_rwlock_rdlock(&features_lock);
03037    for (x = 0; x < FEATURES_COUNT; x++) {
03038       if (strcasecmp(builtin_features[x].sname, "disconnect"))
03039          continue;
03040 
03041       disconnect_code = builtin_features[x].exten;
03042       len = strlen(disconnect_code) + 1;
03043       dialed_code = alloca(len);
03044       memset(dialed_code, 0, len);
03045       break;
03046    }
03047    ast_rwlock_unlock(&features_lock);
03048    x = 0;
03049    started = ast_tvnow();
03050    to = timeout;
03051    AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
03052 
03053    ast_poll_channel_add(caller, chan);
03054 
03055    transferee_hungup = 0;
03056    while (!ast_check_hangup(transferee) && (chan->_state != AST_STATE_UP)) {
03057       int num_chans = 0;
03058 
03059       monitor_chans[num_chans++] = transferee;
03060       monitor_chans[num_chans++] = chan;
03061       if (!caller_hungup) {
03062          if (ast_check_hangup(caller)) {
03063             caller_hungup = 1;
03064 
03065 #if defined(ATXFER_NULL_TECH)
03066             /* Change caller's name to ensure that it will remain unique. */
03067             set_new_chan_name(caller);
03068 
03069             /*
03070              * Get rid of caller's physical technology so it is free for
03071              * other calls.
03072              */
03073             set_null_chan_tech(caller);
03074 #endif   /* defined(ATXFER_NULL_TECH) */
03075          } else {
03076             /* caller is not hungup so monitor it. */
03077             monitor_chans[num_chans++] = caller;
03078          }
03079       }
03080 
03081       /* see if the timeout has been violated */
03082       if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
03083          state = AST_CONTROL_UNHOLD;
03084          ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", chan->name);
03085          break; /*doh! timeout*/
03086       }
03087 
03088       active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
03089       if (!active_channel)
03090          continue;
03091 
03092       f = NULL;
03093       if (transferee == active_channel) {
03094          struct ast_frame *dup_f;
03095 
03096          f = ast_read(transferee);
03097          if (f == NULL) { /*doh! where'd he go?*/
03098             transferee_hungup = 1;
03099             state = 0;
03100             break;
03101          }
03102          if (ast_is_deferrable_frame(f)) {
03103             dup_f = ast_frisolate(f);
03104             if (dup_f) {
03105                if (dup_f == f) {
03106                   f = NULL;
03107                }
03108                AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
03109             }
03110          }
03111       } else if (chan == active_channel) {
03112          if (!ast_strlen_zero(chan->call_forward)) {
03113             state = 0;
03114             chan = ast_call_forward(caller, chan, NULL, format, NULL, &state);
03115             if (!chan) {
03116                break;
03117             }
03118             continue;
03119          }
03120          f = ast_read(chan);
03121          if (f == NULL) { /*doh! where'd he go?*/
03122             switch (chan->hangupcause) {
03123             case AST_CAUSE_BUSY:
03124                state = AST_CONTROL_BUSY;
03125                break;
03126             case AST_CAUSE_CONGESTION:
03127                state = AST_CONTROL_CONGESTION;
03128                break;
03129             default:
03130                state = 0;
03131                break;
03132             }
03133             break;
03134          }
03135 
03136          if (f->frametype == AST_FRAME_CONTROL) {
03137             if (f->subclass.integer == AST_CONTROL_RINGING) {
03138                ast_verb(3, "%s is ringing\n", chan->name);
03139                ast_indicate(caller, AST_CONTROL_RINGING);
03140             } else if (f->subclass.integer == AST_CONTROL_BUSY) {
03141                state = f->subclass.integer;
03142                ast_verb(3, "%s is busy\n", chan->name);
03143                ast_indicate(caller, AST_CONTROL_BUSY);
03144                ast_frfree(f);
03145                break;
03146             } else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
03147                state = f->subclass.integer;
03148                ast_verb(3, "%s is congested\n", chan->name);
03149                ast_indicate(caller, AST_CONTROL_CONGESTION);
03150                ast_frfree(f);
03151                break;
03152             } else if (f->subclass.integer == AST_CONTROL_ANSWER) {
03153                /* This is what we are hoping for */
03154                state = f->subclass.integer;
03155                ast_frfree(f);
03156                ready=1;
03157                break;
03158             } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
03159                if (caller_hungup) {
03160                   struct ast_party_connected_line connected;
03161 
03162                   /* Just save it for the transfer. */
03163                   ast_party_connected_line_set_init(&connected, &caller->connected);
03164                   res = ast_connected_line_parse_data(f->data.ptr, f->datalen,
03165                      &connected);
03166                   if (!res) {
03167                      ast_channel_set_connected_line(caller, &connected, NULL);
03168                   }
03169                   ast_party_connected_line_free(&connected);
03170                } else {
03171                   ast_autoservice_start(transferee);
03172                   if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
03173                      ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE,
03174                         f->data.ptr, f->datalen);
03175                   }
03176                   ast_autoservice_stop(transferee);
03177                }
03178             } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
03179                if (!caller_hungup) {
03180                   ast_autoservice_start(transferee);
03181                   if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
03182                      ast_indicate_data(caller, AST_CONTROL_REDIRECTING,
03183                         f->data.ptr, f->datalen);
03184                   }
03185                   ast_autoservice_stop(transferee);
03186                }
03187             } else if (f->subclass.integer != -1 && f->subclass.integer != AST_CONTROL_PROGRESS) {
03188                ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
03189             }
03190             /* else who cares */
03191          } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
03192             ast_write(caller, f);
03193          }
03194       } else if (caller == active_channel) {
03195          f = ast_read(caller);
03196          if (f) {
03197             if (f->frametype == AST_FRAME_DTMF) {
03198                dialed_code[x++] = f->subclass.integer;
03199                dialed_code[x] = '\0';
03200                if (strlen(dialed_code) == len) {
03201                   x = 0;
03202                } else if (x && strncmp(dialed_code, disconnect_code, x)) {
03203                   x = 0;
03204                   dialed_code[x] = '\0';
03205                }
03206                if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
03207                   /* Caller Canceled the call */
03208                   state = AST_CONTROL_UNHOLD;
03209                   ast_frfree(f);
03210                   break;
03211                }
03212             } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
03213                ast_write(chan, f);
03214             }
03215          }
03216       }
03217       if (f)
03218          ast_frfree(f);
03219    } /* end while */
03220 
03221    ast_poll_channel_del(caller, chan);
03222 
03223    /*
03224     * We need to free all the deferred frames, but we only need to
03225     * queue the deferred frames if no hangup was received.
03226     */
03227    ast_channel_lock(transferee);
03228    transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
03229    while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
03230       if (!transferee_hungup) {
03231          ast_queue_frame_head(transferee, f);
03232       }
03233       ast_frfree(f);
03234    }
03235    ast_channel_unlock(transferee);
03236 
03237 done:
03238    ast_indicate(caller, -1);
03239    if (chan && ready) {
03240       if (chan->_state == AST_STATE_UP)
03241          state = AST_CONTROL_ANSWER;
03242    } else if (chan) {
03243       ast_hangup(chan);
03244       chan = NULL;
03245    }
03246 
03247    if (outstate)
03248       *outstate = state;
03249 
03250    return chan;
03251 }
03252 
03253 void ast_channel_log(char *title, struct ast_channel *chan);
03254 
03255 void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */
03256 {
03257        ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long)chan);
03258        ast_log(LOG_NOTICE, "CHAN: name: %s;  appl: %s; data: %s; contxt: %s;  exten: %s; pri: %d;\n",
03259                        chan->name, chan->appl, chan->data, chan->context, chan->exten, chan->priority);
03260        ast_log(LOG_NOTICE, "CHAN: acctcode: %s;  dialcontext: %s; amaflags: %x; maccontxt: %s;  macexten: %s; macpri: %d;\n",
03261                        chan->accountcode, chan->dialcontext, chan->amaflags, chan->macrocontext, chan->macroexten, chan->macropriority);
03262        ast_log(LOG_NOTICE, "CHAN: masq: %p;  masqr: %p; _bridge: %p; uniqueID: %s; linkedID:%s\n",
03263                        chan->masq, chan->masqr,
03264                        chan->_bridge, chan->uniqueid, chan->linkedid);
03265        if (chan->masqr)
03266                ast_log(LOG_NOTICE, "CHAN: masquerading as: %s;  cdr: %p;\n",
03267                                chan->masqr->name, chan->masqr->cdr);
03268        if (chan->_bridge)
03269                ast_log(LOG_NOTICE, "CHAN: Bridged to %s\n", chan->_bridge->name);
03270 
03271    ast_log(LOG_NOTICE, "===== done ====\n");
03272 }
03273 
03274 /*!
03275  * \brief return the first unlocked cdr in a possible chain
03276 */
03277 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
03278 {
03279    struct ast_cdr *cdr_orig = cdr;
03280    while (cdr) {
03281       if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
03282          return cdr;
03283       cdr = cdr->next;
03284    }
03285    return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
03286 }
03287 
03288 static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
03289 {
03290    const char *feature;
03291 
03292    if (ast_strlen_zero(features)) {
03293       return;
03294    }
03295 
03296    for (feature = features; *feature; feature++) {
03297       switch (*feature) {
03298       case 'T' :
03299       case 't' :
03300          ast_set_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
03301          break;
03302       case 'K' :
03303       case 'k' :
03304          ast_set_flag(&(config->features_caller), AST_FEATURE_PARKCALL);
03305          break;
03306       case 'H' :
03307       case 'h' :
03308          ast_set_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
03309          break;
03310       case 'W' :
03311       case 'w' :
03312          ast_set_flag(&(config->features_caller), AST_FEATURE_AUTOMON);
03313          break;
03314       default :
03315          ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
03316       }
03317    }
03318 }
03319 
03320 static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
03321 {
03322    struct ast_datastore *ds_callee_features = NULL, *ds_caller_features = NULL;
03323    struct ast_dial_features *callee_features = NULL, *caller_features = NULL;
03324 
03325    ast_channel_lock(caller);
03326    ds_caller_features = ast_channel_datastore_find(caller, &dial_features_info, NULL);
03327    ast_channel_unlock(caller);
03328    if (!ds_caller_features) {
03329       if (!(ds_caller_features = ast_datastore_alloc(&dial_features_info, NULL))) {
03330          ast_log(LOG_WARNING, "Unable to create channel datastore for caller features. Aborting!\n");
03331          return;
03332       }
03333       if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
03334          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
03335          ast_datastore_free(ds_caller_features);
03336          return;
03337       }
03338       ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
03339       caller_features->is_caller = 1;
03340       ast_copy_flags(&(caller_features->features_callee), &(config->features_callee), AST_FLAGS_ALL);
03341       ast_copy_flags(&(caller_features->features_caller), &(config->features_caller), AST_FLAGS_ALL);
03342       ds_caller_features->data = caller_features;
03343       ast_channel_lock(caller);
03344       ast_channel_datastore_add(caller, ds_caller_features);
03345       ast_channel_unlock(caller);
03346    } else {
03347       /* If we don't return here, then when we do a builtin_atxfer we will copy the disconnect
03348        * flags over from the atxfer to the caller */
03349       return;
03350    }
03351 
03352    ast_channel_lock(callee);
03353    ds_callee_features = ast_channel_datastore_find(callee, &dial_features_info, NULL);
03354    ast_channel_unlock(callee);
03355    if (!ds_callee_features) {
03356       if (!(ds_callee_features = ast_datastore_alloc(&dial_features_info, NULL))) {
03357          ast_log(LOG_WARNING, "Unable to create channel datastore for callee features. Aborting!\n");
03358          return;
03359       }
03360       if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
03361          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
03362          ast_datastore_free(ds_callee_features);
03363          return;
03364       }
03365       ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
03366       callee_features->is_caller = 0;
03367       ast_copy_flags(&(callee_features->features_callee), &(config->features_caller), AST_FLAGS_ALL);
03368       ast_copy_flags(&(callee_features->features_caller), &(config->features_callee), AST_FLAGS_ALL);
03369       ds_callee_features->data = callee_features;
03370       ast_channel_lock(callee);
03371       ast_channel_datastore_add(callee, ds_callee_features);
03372       ast_channel_unlock(callee);
03373    }
03374 
03375    return;
03376 }
03377 
03378 /*!
03379  * \brief bridge the call and set CDR
03380  * \param chan,peer,config
03381  * 
03382  * Set start time, check for two channels,check if monitor on
03383  * check for feature activation, create new CDR
03384  * \retval res on success.
03385  * \retval -1 on failure to bridge.
03386 */
03387 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
03388 {
03389    /* Copy voice back and forth between the two channels.  Give the peer
03390       the ability to transfer calls with '#<extension' syntax. */
03391    struct ast_frame *f;
03392    struct ast_channel *who;
03393    char chan_featurecode[FEATURE_MAX_LEN + 1]="";
03394    char peer_featurecode[FEATURE_MAX_LEN + 1]="";
03395    char orig_channame[AST_MAX_EXTENSION];
03396    char orig_peername[AST_MAX_EXTENSION];
03397    int res;
03398    int diff;
03399    int hasfeatures=0;
03400    int hadfeatures=0;
03401    int autoloopflag;
03402    int we_disabled_peer_cdr = 0;
03403    struct ast_option_header *aoh;
03404    struct ast_cdr *bridge_cdr = NULL;
03405    struct ast_cdr *orig_peer_cdr = NULL;
03406    struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */
03407    struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
03408    struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
03409    struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
03410 
03411    if (chan && peer) {
03412       pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
03413       pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
03414    } else if (chan) {
03415       pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
03416    }
03417 
03418    set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
03419    add_features_datastores(chan, peer, config);
03420 
03421    /* This is an interesting case.  One example is if a ringing channel gets redirected to
03422     * an extension that picks up a parked call.  This will make sure that the call taken
03423     * out of parking gets told that the channel it just got bridged to is still ringing. */
03424    if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
03425       ast_indicate(peer, AST_CONTROL_RINGING);
03426    }
03427 
03428    if (monitor_ok) {
03429       const char *monitor_exec;
03430       struct ast_channel *src = NULL;
03431       if (!monitor_app) {
03432          if (!(monitor_app = pbx_findapp("Monitor")))
03433             monitor_ok=0;
03434       }
03435       if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
03436          src = chan;
03437       else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
03438          src = peer;
03439       if (monitor_app && src) {
03440          char *tmp = ast_strdupa(monitor_exec);
03441          pbx_exec(src, monitor_app, tmp);
03442       }
03443    }
03444 
03445    set_config_flags(chan, peer, config);
03446 
03447    /* Answer if need be */
03448    if (chan->_state != AST_STATE_UP) {
03449       if (ast_raw_answer(chan, 1)) {
03450          return -1;
03451       }
03452    }
03453 
03454 #ifdef FOR_DEBUG
03455    /* show the two channels and cdrs involved in the bridge for debug & devel purposes */
03456    ast_channel_log("Pre-bridge CHAN Channel info", chan);
03457    ast_channel_log("Pre-bridge PEER Channel info", peer);
03458 #endif
03459    /* two channels are being marked as linked here */
03460    ast_channel_set_linkgroup(chan,peer);
03461 
03462    /* copy the userfield from the B-leg to A-leg if applicable */
03463    if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
03464       char tmp[256];
03465       if (!ast_strlen_zero(chan->cdr->userfield)) {
03466          snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
03467          ast_cdr_appenduserfield(chan, tmp);
03468       } else
03469          ast_cdr_setuserfield(chan, peer->cdr->userfield);
03470       /* Don't delete the CDR; just disable it. */
03471       ast_set_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED);
03472       we_disabled_peer_cdr = 1;
03473    }
03474    ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
03475    ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
03476    orig_peer_cdr = peer_cdr;
03477    
03478    if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
03479       
03480       if (chan_cdr) {
03481          ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
03482          ast_cdr_update(chan);
03483          bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr);
03484          /* rip any forked CDR's off of the chan_cdr and attach
03485           * them to the bridge_cdr instead */
03486          bridge_cdr->next = chan_cdr->next;
03487          chan_cdr->next = NULL;
03488          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
03489          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
03490          if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) {
03491             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
03492          }
03493          ast_cdr_setaccount(peer, chan->accountcode);
03494 
03495       } else {
03496          /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
03497          bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
03498          ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
03499          ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
03500          ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
03501          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
03502          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
03503          ast_cdr_setcid(bridge_cdr, chan);
03504          bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
03505          bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
03506          ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
03507          /* Destination information */
03508          ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
03509          ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
03510          if (peer_cdr) {
03511             bridge_cdr->start = peer_cdr->start;
03512             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
03513          } else {
03514             ast_cdr_start(bridge_cdr);
03515          }
03516       }
03517       ast_debug(4,"bridge answer set, chan answer set\n");
03518       /* peer_cdr->answer will be set when a macro runs on the peer;
03519          in that case, the bridge answer will be delayed while the
03520          macro plays on the peer channel. The peer answered the call
03521          before the macro started playing. To the phone system,
03522          this is billable time for the call, even tho the caller
03523          hears nothing but ringing while the macro does its thing. */
03524 
03525       /* Another case where the peer cdr's time will be set, is when
03526          A self-parks by pickup up phone and dialing 700, then B
03527          picks up A by dialing its parking slot; there may be more 
03528          practical paths that get the same result, tho... in which
03529          case you get the previous answer time from the Park... which
03530          is before the bridge's start time, so I added in the 
03531          tvcmp check to the if below */
03532 
03533       if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) {
03534          ast_cdr_setanswer(bridge_cdr, peer_cdr->answer);
03535          ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition);
03536          if (chan_cdr) {
03537             ast_cdr_setanswer(chan_cdr, peer_cdr->answer);
03538             ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition);
03539          }
03540       } else {
03541          ast_cdr_answer(bridge_cdr);
03542          if (chan_cdr) {
03543             ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
03544          }
03545       }
03546       if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
03547          if (chan_cdr) {
03548             ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
03549          }
03550          if (peer_cdr) {
03551             ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
03552          }
03553       }
03554       /* the DIALED flag may be set if a dialed channel is transfered
03555        * and then bridged to another channel.  In order for the
03556        * bridge CDR to be written, the DIALED flag must not be
03557        * present. */
03558       ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED);
03559    }
03560    ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, NULL);
03561    for (;;) {
03562       struct ast_channel *other; /* used later */
03563    
03564       res = ast_channel_bridge(chan, peer, config, &f, &who);
03565       
03566       /* When frame is not set, we are probably involved in a situation
03567          where we've timed out.
03568          When frame is set, we'll come this code twice; once for DTMF_BEGIN
03569          and also for DTMF_END. If we flow into the following 'if' for both, then 
03570          our wait times are cut in half, as both will subtract from the
03571          feature_timer. Not good!
03572       */
03573       if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
03574          /* Update feature timer for next pass */
03575          diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time);
03576          if (res == AST_BRIDGE_RETRY) {
03577             /* The feature fully timed out but has not been updated. Skip
03578              * the potential round error from the diff calculation and
03579              * explicitly set to expired. */
03580             config->feature_timer = -1;
03581          } else {
03582             config->feature_timer -= diff;
03583          }
03584 
03585          if (hasfeatures) {
03586             if (config->feature_timer <= 0) {
03587                /* Not *really* out of time, just out of time for
03588                   digits to come in for features. */
03589                ast_debug(1, "Timed out for feature!\n");
03590                if (!ast_strlen_zero(peer_featurecode)) {
03591                   ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
03592                   memset(peer_featurecode, 0, sizeof(peer_featurecode));
03593                }
03594                if (!ast_strlen_zero(chan_featurecode)) {
03595                   ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
03596                   memset(chan_featurecode, 0, sizeof(chan_featurecode));
03597                }
03598                if (f)
03599                   ast_frfree(f);
03600                hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
03601                if (!hasfeatures) {
03602                   /* No more digits expected - reset the timer */
03603                   config->feature_timer = 0;
03604                }
03605                hadfeatures = hasfeatures;
03606                /* Continue as we were */
03607                continue;
03608             } else if (!f) {
03609                /* The bridge returned without a frame and there is a feature in progress.
03610                 * However, we don't think the feature has quite yet timed out, so just
03611                 * go back into the bridge. */
03612                continue;
03613             }
03614          } else {
03615             if (config->feature_timer <=0) {
03616                /* We ran out of time */
03617                config->feature_timer = 0;
03618                who = chan;
03619                if (f)
03620                   ast_frfree(f);
03621                f = NULL;
03622                res = 0;
03623             }
03624          }
03625       }
03626       if (res < 0) {
03627          if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) {
03628             ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
03629          }
03630          goto before_you_go;
03631       }
03632       
03633       if (!f || (f->frametype == AST_FRAME_CONTROL &&
03634             (f->subclass.integer == AST_CONTROL_HANGUP || f->subclass.integer == AST_CONTROL_BUSY ||
03635                f->subclass.integer == AST_CONTROL_CONGESTION))) {
03636          res = -1;
03637          break;
03638       }
03639       /* many things should be sent to the 'other' channel */
03640       other = (who == chan) ? peer : chan;
03641       if (f->frametype == AST_FRAME_CONTROL) {
03642          switch (f->subclass.integer) {
03643          case AST_CONTROL_RINGING:
03644          case AST_CONTROL_FLASH:
03645          case -1:
03646             ast_indicate(other, f->subclass.integer);
03647             break;
03648          case AST_CONTROL_CONNECTED_LINE:
03649             if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
03650                break;
03651             }
03652             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
03653             break;
03654          case AST_CONTROL_REDIRECTING:
03655             if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
03656                break;
03657             }
03658             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
03659             break;
03660          case AST_CONTROL_AOC:
03661          case AST_CONTROL_HOLD:
03662          case AST_CONTROL_UNHOLD:
03663             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
03664             break;
03665          case AST_CONTROL_OPTION:
03666             aoh = f->data.ptr;
03667             /* Forward option Requests */
03668             if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
03669                ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 
03670                   f->datalen - sizeof(struct ast_option_header), 0);
03671             }
03672             break;
03673          }
03674       } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
03675          /* eat it */
03676       } else if (f->frametype == AST_FRAME_DTMF) {
03677          char *featurecode;
03678          int sense;
03679 
03680          hadfeatures = hasfeatures;
03681          /* This cannot overrun because the longest feature is one shorter than our buffer */
03682          if (who == chan) {
03683             sense = FEATURE_SENSE_CHAN;
03684             featurecode = chan_featurecode;
03685          } else  {
03686             sense = FEATURE_SENSE_PEER;
03687             featurecode = peer_featurecode;
03688          }
03689          /*! append the event to featurecode. we rely on the string being zero-filled, and
03690           * not overflowing it. 
03691           * \todo XXX how do we guarantee the latter ?
03692           */
03693          featurecode[strlen(featurecode)] = f->subclass.integer;
03694          /* Get rid of the frame before we start doing "stuff" with the channels */
03695          ast_frfree(f);
03696          f = NULL;
03697          config->feature_timer = 0;
03698          res = feature_interpret(chan, peer, config, featurecode, sense);
03699          switch(res) {
03700          case AST_FEATURE_RETURN_PASSDIGITS:
03701             ast_dtmf_stream(other, who, featurecode, 0, 0);
03702             /* Fall through */
03703          case AST_FEATURE_RETURN_SUCCESS:
03704             memset(featurecode, 0, sizeof(chan_featurecode));
03705             break;
03706          }
03707          if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
03708             res = 0;
03709          } else {
03710             break;
03711          }
03712          hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
03713          if (hadfeatures && !hasfeatures) {
03714             /* Feature completed or timed out */
03715             config->feature_timer = 0;
03716          } else if (hasfeatures) {
03717             if (config->timelimit) {
03718                /* No warning next time - we are waiting for future */
03719                ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
03720             }
03721             config->feature_start_time = ast_tvnow();
03722             config->feature_timer = featuredigittimeout;
03723             ast_debug(1, "Set feature timer to %ld ms\n", config->feature_timer);
03724          }
03725       }
03726       if (f)
03727          ast_frfree(f);
03728 
03729    }
03730    ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, NULL);
03731    before_you_go:
03732 
03733    if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) {
03734       ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
03735       if (bridge_cdr) {
03736          ast_cdr_discard(bridge_cdr);
03737          /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */
03738       }
03739       return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */
03740    }
03741 
03742    if (config->end_bridge_callback) {
03743       config->end_bridge_callback(config->end_bridge_callback_data);
03744    }
03745 
03746    /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation 
03747     * if it were, then chan belongs to a different thread now, and might have been hung up long
03748      * ago.
03749     */
03750    if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN)
03751       && ast_exists_extension(chan, chan->context, "h", 1,
03752          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
03753       struct ast_cdr *swapper = NULL;
03754       char savelastapp[AST_MAX_EXTENSION];
03755       char savelastdata[AST_MAX_EXTENSION];
03756       char save_exten[AST_MAX_EXTENSION];
03757       int  save_prio;
03758       int  found = 0;   /* set if we find at least one match */
03759       int  spawn_error = 0;
03760       
03761       autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
03762       ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
03763       if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
03764          ast_cdr_end(bridge_cdr);
03765       }
03766       /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
03767          dialplan code operate on it */
03768       ast_channel_lock(chan);
03769       if (bridge_cdr) {
03770          swapper = chan->cdr;
03771          ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
03772          ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
03773          chan->cdr = bridge_cdr;
03774       }
03775       ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
03776       save_prio = chan->priority;
03777       ast_copy_string(chan->exten, "h", sizeof(chan->exten));
03778       chan->priority = 1;
03779       ast_channel_unlock(chan);
03780       while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten,
03781          chan->priority,
03782          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
03783          &found, 1)) == 0) {
03784          chan->priority++;
03785       }
03786       if (spawn_error
03787          && (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
03788             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
03789             || ast_check_hangup(chan))) {
03790          /* if the extension doesn't exist or a hangup occurred, this isn't really a spawn error */
03791          spawn_error = 0;
03792       }
03793       if (found && spawn_error) {
03794          /* Something bad happened, or a hangup has been requested. */
03795          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
03796          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
03797       }
03798       /* swap it back */
03799       ast_channel_lock(chan);
03800       ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
03801       chan->priority = save_prio;
03802       if (bridge_cdr) {
03803          if (chan->cdr == bridge_cdr) {
03804             chan->cdr = swapper;
03805          } else {
03806             bridge_cdr = NULL;
03807          }
03808       }
03809       if (!spawn_error) {
03810          ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
03811       }
03812       ast_channel_unlock(chan);
03813       /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
03814       if (bridge_cdr) {
03815          ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
03816          ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
03817       }
03818       ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
03819    }
03820    
03821    /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
03822    new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
03823    if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))
03824       ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
03825 
03826    /* we can post the bridge CDR at this point */
03827    if (bridge_cdr) {
03828       ast_cdr_end(bridge_cdr);
03829       ast_cdr_detach(bridge_cdr);
03830    }
03831    
03832    /* do a specialized reset on the beginning channel
03833       CDR's, if they still exist, so as not to mess up
03834       issues in future bridges;
03835       
03836       Here are the rules of the game:
03837       1. The chan and peer channel pointers will not change
03838          during the life of the bridge.
03839       2. But, in transfers, the channel names will change.
03840          between the time the bridge is started, and the
03841          time the channel ends. 
03842          Usually, when a channel changes names, it will
03843          also change CDR pointers.
03844       3. Usually, only one of the two channels (chan or peer)
03845          will change names.
03846       4. Usually, if a channel changes names during a bridge,
03847          it is because of a transfer. Usually, in these situations,
03848          it is normal to see 2 bridges running simultaneously, and
03849          it is not unusual to see the two channels that change
03850          swapped between bridges.
03851       5. After a bridge occurs, we have 2 or 3 channels' CDRs
03852          to attend to; if the chan or peer changed names,
03853          we have the before and after attached CDR's.
03854    */
03855 
03856    if (new_chan_cdr) {
03857       struct ast_channel *chan_ptr = NULL;
03858 
03859       if (strcasecmp(orig_channame, chan->name) != 0) { 
03860          /* old channel */
03861          if ((chan_ptr = ast_channel_get_by_name(orig_channame))) {
03862             ast_channel_lock(chan_ptr);
03863             if (!ast_bridged_channel(chan_ptr)) {
03864                struct ast_cdr *cur;
03865                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
03866                   if (cur == chan_cdr) {
03867                      break;
03868                   }
03869                }
03870                if (cur) {
03871                   ast_cdr_specialized_reset(chan_cdr, 0);
03872                }
03873             }
03874             ast_channel_unlock(chan_ptr);
03875             chan_ptr = ast_channel_unref(chan_ptr);
03876          }
03877          /* new channel */
03878          ast_cdr_specialized_reset(new_chan_cdr, 0);
03879       } else {
03880          ast_cdr_specialized_reset(chan->cdr, 0); /* nothing changed, reset the chan cdr  */
03881       }
03882    }
03883 
03884    {
03885       struct ast_channel *chan_ptr = NULL;
03886       new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
03887       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))
03888          ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
03889       if (strcasecmp(orig_peername, peer->name) != 0) { 
03890          /* old channel */
03891          if ((chan_ptr = ast_channel_get_by_name(orig_peername))) {
03892             ast_channel_lock(chan_ptr);
03893             if (!ast_bridged_channel(chan_ptr)) {
03894                struct ast_cdr *cur;
03895                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
03896                   if (cur == peer_cdr) {
03897                      break;
03898                   }
03899                }
03900                if (cur) {
03901                   ast_cdr_specialized_reset(peer_cdr, 0);
03902                }
03903             }
03904             ast_channel_unlock(chan_ptr);
03905             chan_ptr = ast_channel_unref(chan_ptr);
03906          }
03907          /* new channel */
03908          if (new_peer_cdr) {
03909             ast_cdr_specialized_reset(new_peer_cdr, 0);
03910          }
03911       } else {
03912          if (we_disabled_peer_cdr) {
03913             ast_clear_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED);
03914          }
03915          ast_cdr_specialized_reset(peer->cdr, 0); /* nothing changed, reset the peer cdr  */
03916       }
03917    }
03918    
03919    return res;
03920 }
03921 
03922 /*! \brief Output parking event to manager */
03923 static void post_manager_event(const char *s, struct parkeduser *pu)
03924 {
03925    manager_event(EVENT_FLAG_CALL, s,
03926       "Exten: %s\r\n"
03927       "Channel: %s\r\n"
03928       "Parkinglot: %s\r\n"
03929       "CallerIDNum: %s\r\n"
03930       "CallerIDName: %s\r\n"
03931       "UniqueID: %s\r\n\r\n",
03932       pu->parkingexten, 
03933       pu->chan->name,
03934       pu->parkinglot->name,
03935       S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
03936       S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
03937       pu->chan->uniqueid
03938       );
03939 }
03940 
03941 static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
03942 {
03943    int i = 0;
03944    enum {
03945       OPT_CALLEE_REDIRECT   = 't',
03946       OPT_CALLER_REDIRECT   = 'T',
03947       OPT_CALLEE_AUTOMON    = 'w',
03948       OPT_CALLER_AUTOMON    = 'W',
03949       OPT_CALLEE_DISCONNECT = 'h',
03950       OPT_CALLER_DISCONNECT = 'H',
03951       OPT_CALLEE_PARKCALL   = 'k',
03952       OPT_CALLER_PARKCALL   = 'K',
03953    };
03954 
03955    memset(options, 0, len);
03956    if (ast_test_flag(features_caller, AST_FEATURE_REDIRECT) && i < len) {
03957       options[i++] = OPT_CALLER_REDIRECT;
03958    }
03959    if (ast_test_flag(features_caller, AST_FEATURE_AUTOMON) && i < len) {
03960       options[i++] = OPT_CALLER_AUTOMON;
03961    }
03962    if (ast_test_flag(features_caller, AST_FEATURE_DISCONNECT) && i < len) {
03963       options[i++] = OPT_CALLER_DISCONNECT;
03964    }
03965    if (ast_test_flag(features_caller, AST_FEATURE_PARKCALL) && i < len) {
03966       options[i++] = OPT_CALLER_PARKCALL;
03967    }
03968 
03969    if (ast_test_flag(features_callee, AST_FEATURE_REDIRECT) && i < len) {
03970       options[i++] = OPT_CALLEE_REDIRECT;
03971    }
03972    if (ast_test_flag(features_callee, AST_FEATURE_AUTOMON) && i < len) {
03973       options[i++] = OPT_CALLEE_AUTOMON;
03974    }
03975    if (ast_test_flag(features_callee, AST_FEATURE_DISCONNECT) && i < len) {
03976       options[i++] = OPT_CALLEE_DISCONNECT;
03977    }
03978    if (ast_test_flag(features_callee, AST_FEATURE_PARKCALL) && i < len) {
03979       options[i++] = OPT_CALLEE_PARKCALL;
03980    }
03981 
03982    return options;
03983 }
03984 
03985 /*! \brief Run management on parkinglots, called once per parkinglot */
03986 int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
03987 {
03988    struct parkeduser *pu;
03989    int res = 0;
03990    char parkingslot[AST_MAX_EXTENSION];
03991 
03992    /* Lock parking list */
03993    AST_LIST_LOCK(&curlot->parkings);
03994    AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
03995       struct ast_channel *chan = pu->chan;   /* shorthand */
03996       int tms;        /* timeout for this item */
03997       int x;          /* fd index in channel */
03998       struct ast_context *con;
03999 
04000       if (pu->notquiteyet) { /* Pretend this one isn't here yet */
04001          continue;
04002       }
04003       tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
04004       if (tms > pu->parkingtime) {
04005          /* Stop music on hold */
04006          ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
04007          /* Get chan, exten from derived kludge */
04008          if (pu->peername[0]) {
04009             char *peername = ast_strdupa(pu->peername);
04010             char *dash = strrchr(peername, '-');
04011             char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
04012             int i;
04013 
04014             if (dash) {
04015                *dash = '\0';
04016             }
04017 
04018             peername_flat = ast_strdupa(peername);
04019             for (i = 0; peername_flat[i]; i++) {
04020                if (peername_flat[i] == '/') {
04021                   peername_flat[i]= '_';
04022                }
04023             }
04024 
04025             con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
04026             if (!con) {
04027                ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
04028             } else {
04029                char returnexten[AST_MAX_EXTENSION];
04030                struct ast_datastore *features_datastore;
04031                struct ast_dial_features *dialfeatures = NULL;
04032 
04033                ast_channel_lock(chan);
04034 
04035                if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
04036                   dialfeatures = features_datastore->data;
04037 
04038                ast_channel_unlock(chan);
04039 
04040                if (!strncmp(peername, "Parked/", 7)) {
04041                   peername += 7;
04042                }
04043 
04044                if (dialfeatures) {
04045                   char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
04046                   snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername, callback_dialoptions(&(dialfeatures->features_callee), &(dialfeatures->features_caller), buf, sizeof(buf)));
04047                } else { /* Existing default */
04048                   ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n", chan->name);
04049                   snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
04050                }
04051 
04052                ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
04053             }
04054             if (pu->options_specified == 1) {
04055                /* Park() was called with overriding return arguments, respect those arguments */
04056                set_c_e_p(chan, pu->context, pu->exten, pu->priority);
04057             } else {
04058                if (comebacktoorigin) {
04059                   set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername_flat, 1);
04060                } else {
04061                   snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
04062                   pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
04063                   set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
04064                }
04065             }
04066          } else {
04067             /* They've been waiting too long, send them back to where they came.  Theoretically they
04068                should have their original extensions and such, but we copy to be on the safe side */
04069             set_c_e_p(chan, pu->context, pu->exten, pu->priority);
04070          }
04071          post_manager_event("ParkedCallTimeOut", pu);
04072          ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
04073 
04074          ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context, pu->chan->exten, pu->chan->priority);
04075          /* Start up the PBX, or hang them up */
04076          if (ast_pbx_start(chan))  {
04077             ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
04078             ast_hangup(chan);
04079          }
04080          /* And take them out of the parking lot */
04081          con = ast_context_find(pu->parkinglot->parking_con);
04082          if (con) {
04083             if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
04084                ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
04085             else
04086                notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
04087          } else
04088             ast_log(LOG_WARNING, "Whoa, no parking context?\n");
04089          AST_LIST_REMOVE_CURRENT(list);
04090          free(pu);
04091       } else { /* still within parking time, process descriptors */
04092          for (x = 0; x < AST_MAX_FDS; x++) {
04093             struct ast_frame *f;
04094             int y;
04095 
04096             if (chan->fds[x] == -1) {
04097                continue;   /* nothing on this descriptor */
04098             }
04099 
04100             for (y = 0; y < nfds; y++) {
04101                if (pfds[y].fd == chan->fds[x]) {
04102                   /* Found poll record! */
04103                   break;
04104                }
04105             }
04106             if (y == nfds) {
04107                /* Not found */
04108                continue;
04109             }
04110 
04111             if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
04112                /* Next x */
04113                continue;
04114             }
04115 
04116             if (pfds[y].revents & POLLERR) {
04117                ast_set_flag(chan, AST_FLAG_EXCEPTION);
04118             } else {
04119                ast_clear_flag(chan, AST_FLAG_EXCEPTION);
04120             }
04121             chan->fdno = x;
04122 
04123             /* See if they need servicing */
04124             f = ast_read(pu->chan);
04125             /* Hangup? */
04126             if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer ==  AST_CONTROL_HANGUP))) {
04127                if (f)
04128                   ast_frfree(f);
04129                post_manager_event("ParkedCallGiveUp", pu);
04130                ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp", NULL);
04131 
04132                /* There's a problem, hang them up*/
04133                ast_verb(2, "%s got tired of being parked\n", chan->name);
04134                ast_hangup(chan);
04135                /* And take them out of the parking lot */
04136                con = ast_context_find(curlot->parking_con);
04137                if (con) {
04138                   if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
04139                      ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
04140                   else
04141                      notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
04142                } else
04143                   ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
04144                AST_LIST_REMOVE_CURRENT(list);
04145                parkinglot_unref(pu->parkinglot);
04146                free(pu);
04147                break;
04148             } else {
04149                /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
04150                ast_frfree(f);
04151                if (pu->moh_trys < 3 && !chan->generatordata) {
04152                   ast_debug(1, "MOH on parked call stopped by outside source.  Restarting on channel %s.\n", chan->name);
04153                   ast_indicate_data(chan, AST_CONTROL_HOLD, 
04154                      S_OR(curlot->mohclass, NULL),
04155                      (!ast_strlen_zero(curlot->mohclass) ? strlen(curlot->mohclass) + 1 : 0));
04156                   pu->moh_trys++;
04157                }
04158                goto std;   /* XXX Ick: jumping into an else statement??? XXX */
04159             }
04160          } /* End for */
04161          if (x >= AST_MAX_FDS) {
04162 std:        for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
04163                if (chan->fds[x] > -1) {
04164                   void *tmp = ast_realloc(*new_pfds, (*new_nfds + 1) * sizeof(struct pollfd));
04165                   if (!tmp) {
04166                      continue;
04167                   }
04168                   *new_pfds = tmp;
04169                   (*new_pfds)[*new_nfds].fd = chan->fds[x];
04170                   (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
04171                   (*new_pfds)[*new_nfds].revents = 0;
04172                   (*new_nfds)++;
04173                }
04174             }
04175             /* Keep track of our shortest wait */
04176             if (tms < *ms || *ms < 0) {
04177                *ms = tms;
04178             }
04179          }
04180       }
04181    }
04182    AST_LIST_TRAVERSE_SAFE_END;
04183    AST_LIST_UNLOCK(&curlot->parkings);
04184 
04185    return res;
04186 }
04187 
04188 /*! 
04189  * \brief Take care of parked calls and unpark them if needed 
04190  * \param ignore unused var.
04191  * 
04192  * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
04193  * if so, remove channel from parking lot and return it to the extension that parked it.
04194  * Check if parked channel decided to hangup, wait until next FD via select().
04195 */
04196 static void *do_parking_thread(void *ignore)
04197 {
04198    struct pollfd *pfds = NULL, *new_pfds = NULL;
04199    int nfds = 0, new_nfds = 0;
04200 
04201    for (;;) {
04202       struct ao2_iterator iter;
04203       struct ast_parkinglot *curlot;
04204       int ms = -1;   /* poll2 timeout, uninitialized */
04205       iter = ao2_iterator_init(parkinglots, 0);
04206 
04207       while ((curlot = ao2_iterator_next(&iter))) {
04208          manage_parkinglot(curlot, pfds, nfds, &new_pfds, &new_nfds, &ms);
04209          ao2_ref(curlot, -1);
04210       }
04211       ao2_iterator_destroy(&iter);
04212 
04213       /* Recycle */
04214       ast_free(pfds);
04215       pfds = new_pfds;
04216       nfds = new_nfds;
04217       new_pfds = NULL;
04218       new_nfds = 0;
04219 
04220       /* Wait for something to happen */
04221       ast_poll(pfds, nfds, ms);
04222       pthread_testcancel();
04223    }
04224    /* If this WERE reached, we'd need to free(pfds) */
04225    return NULL;   /* Never reached */
04226 }
04227 
04228 /*! \brief Find parkinglot by name */
04229 struct ast_parkinglot *find_parkinglot(const char *name)
04230 {
04231    struct ast_parkinglot *parkinglot;
04232 
04233    if (ast_strlen_zero(name)) {
04234       return NULL;
04235    }
04236 
04237    parkinglot = ao2_find(parkinglots, (void *) name, 0);
04238    if (parkinglot) {
04239       ast_debug(1, "Found Parkinglot: %s\n", parkinglot->name);
04240    }
04241 
04242    return parkinglot;
04243 }
04244 
04245 /*! \brief Copy parkinglot and store it with new name */
04246 struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot) {
04247    struct ast_parkinglot *copylot;
04248 
04249    if (ast_strlen_zero(name)) { /* No name specified */
04250       return NULL;
04251    }
04252    if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
04253       if (copylot) {
04254          ao2_ref(copylot, -1);
04255       }
04256       return NULL;
04257    }
04258 
04259    copylot = create_parkinglot(name);
04260    ast_debug(1, "Building parking lot %s\n", name);
04261 
04262    memcpy(copylot, parkinglot, sizeof(struct ast_parkinglot));
04263    ast_copy_string(copylot->name, name, sizeof(copylot->name));
04264    AST_LIST_HEAD_INIT(&copylot->parkings);
04265 
04266    return copylot;
04267 }
04268 
04269 AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
04270    AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
04271    AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
04272    AST_APP_OPTION('s', AST_PARK_OPT_SILENCE),
04273 END_OPTIONS );
04274 
04275 /*! \brief Park a call */
04276 static int park_call_exec(struct ast_channel *chan, const char *data)
04277 {
04278    /* Cache the original channel name in case we get masqueraded in the middle
04279     * of a park--it is still theoretically possible for a transfer to happen before
04280     * we get here, but it is _really_ unlikely */
04281    char *orig_chan_name = ast_strdupa(chan->name);
04282    char orig_exten[AST_MAX_EXTENSION];
04283    int orig_priority = chan->priority;
04284 
04285    /* Data is unused at the moment but could contain a parking
04286       lot context eventually */
04287    int res = 0;
04288 
04289    char *parse = NULL;
04290    AST_DECLARE_APP_ARGS(app_args,
04291       AST_APP_ARG(timeout);
04292       AST_APP_ARG(return_con);
04293       AST_APP_ARG(return_ext);
04294       AST_APP_ARG(return_pri);
04295       AST_APP_ARG(options);
04296    );
04297 
04298    parse = ast_strdupa(data);
04299    AST_STANDARD_APP_ARGS(app_args, parse);
04300 
04301    ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
04302 
04303    /* Setup the exten/priority to be s/1 since we don't know
04304       where this call should return */
04305    strcpy(chan->exten, "s");
04306    chan->priority = 1;
04307 
04308    /* Answer if call is not up */
04309    if (chan->_state != AST_STATE_UP)
04310       res = ast_answer(chan);
04311 
04312    /* Sleep to allow VoIP streams to settle down */
04313    if (!res)
04314       res = ast_safe_sleep(chan, 1000);
04315 
04316    /* Park the call */
04317    if (!res) {
04318       struct ast_park_call_args args = {
04319          .orig_chan_name = orig_chan_name,
04320       };
04321       struct ast_flags flags = { 0 };
04322 
04323       if (parse) {
04324          if (!ast_strlen_zero(app_args.timeout)) {
04325             if (sscanf(app_args.timeout, "%30d", &args.timeout) != 1) {
04326                ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
04327                args.timeout = 0;
04328             }
04329          }
04330          if (!ast_strlen_zero(app_args.return_con)) {
04331             args.return_con = app_args.return_con;
04332          }
04333          if (!ast_strlen_zero(app_args.return_ext)) {
04334             args.return_ext = app_args.return_ext;
04335          }
04336          if (!ast_strlen_zero(app_args.return_pri)) {
04337             if (sscanf(app_args.return_pri, "%30d", &args.return_pri) != 1) {
04338                ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
04339                args.return_pri = 0;
04340             }
04341          }
04342       }
04343 
04344       ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
04345       args.flags = flags.flags;
04346 
04347       args.parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &orig_exten);
04348       res = masq_park_call_announce(chan, chan, &args);
04349       /* Continue on in the dialplan */
04350       if (res == 1) {
04351          ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
04352          chan->priority = orig_priority;
04353          res = 0;
04354       } else if (!res) {
04355          res = 1;
04356       }
04357    }
04358 
04359    return res;
04360 }
04361 
04362 /*! \brief Pickup parked call */
04363 static int park_exec_full(struct ast_channel *chan, const char *data)
04364 {
04365    int res = 0;
04366    struct ast_channel *peer=NULL;
04367    struct parkeduser *pu;
04368    struct ast_context *con;
04369    int park = 0;
04370    struct ast_bridge_config config;
04371    struct ast_parkinglot *parkinglot;
04372 
04373    if (data) {
04374       park = atoi((char *) data);
04375    }
04376 
04377    parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_position_cb, (void *) &park);
04378    if (!parkinglot)
04379       parkinglot = default_parkinglot;
04380 
04381    AST_LIST_LOCK(&parkinglot->parkings);
04382    AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
04383       if (!pu->notquiteyet && (!data || pu->parkingnum == park)) {
04384          if (pu->chan->pbx) { /* do not allow call to be picked up until the PBX thread is finished */
04385             AST_LIST_UNLOCK(&parkinglot->parkings);
04386             return -1;
04387          }
04388          AST_LIST_REMOVE_CURRENT(list);
04389          break;
04390       }
04391    }
04392    AST_LIST_TRAVERSE_SAFE_END;
04393    AST_LIST_UNLOCK(&parkinglot->parkings);
04394 
04395    if (pu) {
04396       peer = pu->chan;
04397       con = ast_context_find(parkinglot->parking_con);
04398       if (con) {
04399          if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
04400             ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
04401          else
04402             notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
04403       } else
04404          ast_log(LOG_WARNING, "Whoa, no parking context?\n");
04405 
04406       ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "UnParkedCall", chan);
04407       ast_manager_event(pu->chan, EVENT_FLAG_CALL, "UnParkedCall",
04408          "Exten: %s\r\n"
04409          "Channel: %s\r\n"
04410          "From: %s\r\n"
04411          "CallerIDNum: %s\r\n"
04412          "CallerIDName: %s\r\n",
04413          pu->parkingexten, pu->chan->name, chan->name,
04414          S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
04415          S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>")
04416          );
04417 
04418       ast_free(pu);
04419    }
04420    /* JK02: it helps to answer the channel if not already up */
04421    if (chan->_state != AST_STATE_UP)
04422       ast_answer(chan);
04423 
04424    //XXX Why do we unlock here ?
04425    // uncomment it for now, till my setup with debug_threads and detect_deadlocks starts to complain
04426    //ASTOBJ_UNLOCK(parkinglot);
04427 
04428    if (peer) {
04429       struct ast_datastore *features_datastore;
04430       struct ast_dial_features *dialfeatures = NULL;
04431 
04432       /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
04433 
04434       if (!ast_strlen_zero(courtesytone)) {
04435          int error = 0;
04436          ast_indicate(peer, AST_CONTROL_UNHOLD);
04437          if (parkedplay == 0) {
04438             error = ast_stream_and_wait(chan, courtesytone, "");
04439          } else if (parkedplay == 1) {
04440             error = ast_stream_and_wait(peer, courtesytone, "");
04441          } else if (parkedplay == 2) {
04442             if (!ast_streamfile(chan, courtesytone, chan->language) &&
04443                   !ast_streamfile(peer, courtesytone, chan->language)) {
04444                /*! \todo XXX we would like to wait on both! */
04445                res = ast_waitstream(chan, "");
04446                if (res >= 0)
04447                   res = ast_waitstream(peer, "");
04448                if (res < 0)
04449                   error = 1;
04450             }
04451          }
04452          if (error) {
04453             ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
04454             ast_hangup(peer);
04455             return -1;
04456          }
04457       } else
04458          ast_indicate(peer, AST_CONTROL_UNHOLD);
04459 
04460       res = ast_channel_make_compatible(chan, peer);
04461       if (res < 0) {
04462          ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
04463          ast_hangup(peer);
04464          return -1;
04465       }
04466       /* This runs sorta backwards, since we give the incoming channel control, as if it
04467          were the person called. */
04468       ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
04469 
04470       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
04471       ast_cdr_setdestchan(chan->cdr, peer->name);
04472       memset(&config, 0, sizeof(struct ast_bridge_config));
04473 
04474       /* Get datastore for peer and apply it's features to the callee side of the bridge config */
04475       ast_channel_lock(peer);
04476       if ((features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL))) {
04477          dialfeatures = features_datastore->data;
04478       }
04479       ast_channel_unlock(peer);
04480 
04481       /* When the datastores for both caller and callee are created, both the callee and caller channels
04482        * use the features_caller flag variable to represent themselves. With that said, the config.features_callee
04483        * flags should be copied from the datastore's caller feature flags regardless if peer was a callee
04484        * or caller. */
04485       if (dialfeatures) {
04486          ast_copy_flags(&(config.features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
04487       }
04488 
04489       if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
04490          ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
04491       }
04492       if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
04493          ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
04494       }
04495       if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
04496          ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
04497       }
04498       if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
04499          ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
04500       }
04501       if ((parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
04502          ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
04503       }
04504       if ((parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
04505          ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
04506       }
04507       if ((parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
04508          ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
04509       }
04510       if ((parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
04511          ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
04512       }
04513 
04514       parkinglot_unref(parkinglot);
04515       res = ast_bridge_call(chan, peer, &config);
04516 
04517       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
04518       ast_cdr_setdestchan(chan->cdr, peer->name);
04519 
04520       /* Simulate the PBX hanging up */
04521       ast_hangup(peer);
04522       return -1;
04523    } else {
04524       /*! \todo XXX Play a message XXX */
04525       if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
04526          ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
04527       ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
04528       res = -1;
04529    }
04530 
04531    return -1;
04532 }
04533 
04534 static int park_exec(struct ast_channel *chan, const char *data) 
04535 {
04536    return park_exec_full(chan, data);
04537 }
04538 
04539 /*! \brief Unreference parkinglot object. If no more references,
04540    then go ahead and delete it */
04541 static void parkinglot_unref(struct ast_parkinglot *parkinglot) 
04542 {
04543    int refcount = ao2_ref(parkinglot, -1);
04544    ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount - 1);
04545 }
04546 
04547 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
04548 {
04549    int refcount = ao2_ref(parkinglot, +1);
04550    ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
04551    return parkinglot;
04552 }
04553 
04554 /*! \brief Allocate parking lot structure */
04555 static struct ast_parkinglot *create_parkinglot(const char *name)
04556 {
04557    struct ast_parkinglot *newlot = (struct ast_parkinglot *) NULL;
04558 
04559    if (!name)
04560       return NULL;
04561 
04562    newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);
04563    if (!newlot)
04564       return NULL;
04565    
04566    ast_copy_string(newlot->name, name, sizeof(newlot->name));
04567    AST_LIST_HEAD_INIT(&newlot->parkings);
04568 
04569    return newlot;
04570 }
04571 
04572 /*! \brief Destroy a parking lot */
04573 static void parkinglot_destroy(void *obj)
04574 {
04575    struct ast_parkinglot *ruin = obj;
04576    struct ast_context *con;
04577    con = ast_context_find(ruin->parking_con);
04578    if (con)
04579       ast_context_destroy(con, registrar);
04580 }
04581 
04582 /*! 
04583  * \brief Add parking hints for all defined parking lots 
04584  * \param context
04585  * \param start starting parkinglot number
04586  * \param stop ending parkinglot number
04587 */
04588 static void park_add_hints(char *context, int start, int stop)
04589 {
04590    int numext;
04591    char device[AST_MAX_EXTENSION];
04592    char exten[10];
04593 
04594    for (numext = start; numext <= stop; numext++) {
04595       snprintf(exten, sizeof(exten), "%d", numext);
04596       snprintf(device, sizeof(device), "park:%s@%s", exten, context);
04597       ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
04598    }
04599 }
04600 
04601 /*! \brief Build parkinglot from configuration and chain it in if it doesn't already exist */
04602 static struct ast_parkinglot *build_parkinglot(char *name, struct ast_variable *var)
04603 {
04604    struct ast_parkinglot *parkinglot;
04605    struct ast_context *con = NULL;
04606 
04607    struct ast_variable *confvar = var;
04608    int error = 0;
04609    int start = 0, end = 0;
04610    int oldparkinglot = 0;
04611 
04612    parkinglot = find_parkinglot(name);
04613    if (parkinglot)
04614       oldparkinglot = 1;
04615    else
04616       parkinglot = create_parkinglot(name);
04617 
04618    if (!parkinglot)
04619       return NULL;
04620 
04621    ao2_lock(parkinglot);
04622 
04623    ast_debug(1, "Building parking lot %s\n", name);
04624 
04625    /* Do some config stuff */
04626    while(confvar) {
04627       if (!strcasecmp(confvar->name, "context")) {
04628          ast_copy_string(parkinglot->parking_con, confvar->value, sizeof(parkinglot->parking_con));
04629       } else if (!strcasecmp(confvar->name, "parkext")) {
04630          ast_copy_string(parkinglot->parkext, confvar->value, sizeof(parkinglot->parkext));
04631       } else if (!strcasecmp(confvar->name, "parkingtime")) {
04632          if ((sscanf(confvar->value, "%30d", &parkinglot->parkingtime) != 1) || (parkinglot->parkingtime < 1)) {
04633             ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", confvar->value);
04634             parkinglot->parkingtime = DEFAULT_PARK_TIME;
04635          } else
04636             parkinglot->parkingtime = parkinglot->parkingtime * 1000;
04637       } else if (!strcasecmp(confvar->name, "parkpos")) {
04638          if (sscanf(confvar->value, "%30d-%30d", &start, &end) != 2) {
04639             ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of parking.conf\n", confvar->lineno);
04640             error = 1;
04641          } else {
04642             parkinglot->parking_start = start;
04643             parkinglot->parking_stop = end;
04644          }
04645       } else if (!strcasecmp(confvar->name, "findslot")) {
04646          parkinglot->parkfindnext = (!strcasecmp(confvar->value, "next"));
04647       } else if (!strcasecmp(confvar->name, "parkedcalltransfers")) {
04648                         ast_log(LOG_DEBUG, "Setting parking lot %s %s to %s\n", name, confvar->name, confvar->value);
04649                         if (!strcasecmp(confvar->value, "both"))
04650                                 parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
04651                         else if (!strcasecmp(confvar->value, "caller"))
04652                                 parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
04653                         else if (!strcasecmp(confvar->value, "callee"))
04654                                 parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
04655                 } else if (!strcasecmp(confvar->name, "parkedcallreparking")) {
04656                         ast_log(LOG_DEBUG, "Setting parking lot %s %s to %s\n", name, confvar->name, confvar->value);
04657                         if (!strcasecmp(confvar->value, "both"))
04658                                 parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYBOTH;
04659                         else if (!strcasecmp(confvar->value, "caller"))
04660                                 parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLER;
04661                         else if (!strcasecmp(confvar->value, "callee"))
04662                                 parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLEE;
04663                 } else if (!strcasecmp(confvar->name, "parkedcallhangup")) {
04664                         ast_log(LOG_DEBUG, "Setting parking lot %s %s to %s\n", name, confvar->name, confvar->value);
04665                         if (!strcasecmp(confvar->value, "both"))
04666                                 parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYBOTH;
04667                         else if (!strcasecmp(confvar->value, "caller"))
04668                                 parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLER;
04669                         else if (!strcasecmp(confvar->value, "callee"))
04670                                 parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLEE;
04671                 } else if (!strcasecmp(confvar->name, "parkedcallrecording")) {
04672                         ast_log(LOG_DEBUG, "Setting parking lot %s %s to %s\n", name, confvar->name, confvar->value);
04673                         if (!strcasecmp(confvar->value, "both"))
04674                                 parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYBOTH;
04675                         else if (!strcasecmp(confvar->value, "caller"))
04676                                 parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
04677                         else if (!strcasecmp(confvar->value, "callee"))
04678                                 parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
04679                 }
04680       confvar = confvar->next;
04681    }
04682    /* make sure parkingtime is set if not specified */
04683    if (parkinglot->parkingtime == 0) {
04684       parkinglot->parkingtime = DEFAULT_PARK_TIME;
04685    }
04686    if (ast_strlen_zero(parkinglot->parkext)) {
04687       ast_debug(2, "no parkext specified for %s - setting it to %s\n", parkinglot->name, DEFAULT_PARK_EXTENSION);
04688       ast_copy_string(parkinglot->parkext, DEFAULT_PARK_EXTENSION, sizeof(parkinglot->parkext));
04689    }
04690 
04691    if (!var) { /* Default parking lot */
04692       ast_copy_string(parkinglot->parking_con, "parkedcalls", sizeof(parkinglot->parking_con));
04693       ast_copy_string(parkinglot->parking_con_dial, "park-dial", sizeof(parkinglot->parking_con_dial));
04694       ast_copy_string(parkinglot->mohclass, "default", sizeof(parkinglot->mohclass));
04695    }
04696 
04697    /* Check for errors */
04698    if (ast_strlen_zero(parkinglot->parking_con)) {
04699       ast_log(LOG_WARNING, "Parking lot %s lacks context\n", name);
04700       error = 1;
04701    }
04702 
04703    /* Create context */
04704    if (!error && !(con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar))) {
04705       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
04706       error = 1;
04707    }
04708 
04709    /* Add a parking extension into the context */
04710    if (!error && !oldparkinglot) {
04711       if (!ast_strlen_zero(parkinglot->parkext)) {
04712          if (ast_add_extension2(con, 1, parkinglot->parkext, 1, NULL, NULL, parkcall, strdup(""), ast_free_ptr, registrar) == -1)
04713             error = 1;
04714       }
04715    }
04716 
04717    /* Add parking hints */
04718    if (parkinglot->parkaddhints)
04719       park_add_hints(parkinglot->parking_con, parkinglot->parking_start, parkinglot->parking_stop);
04720 
04721    ao2_unlock(parkinglot);
04722 
04723    if (error) {
04724       ast_log(LOG_WARNING, "Parking %s not open for business. Configuration error.\n", name);
04725       parkinglot_destroy(parkinglot);
04726       parkinglot_unref(parkinglot);
04727       return NULL;
04728    }
04729    ast_debug(1, "Parking %s now open for business. (start exten %d end %d)\n", name, start, end);
04730    parkinglot->the_mark = 0;
04731 
04732    /* Move it into the list, if it wasn't already there */
04733    if (!oldparkinglot) {
04734       ao2_link(parkinglots, parkinglot);
04735    }
04736    parkinglot_unref(parkinglot);
04737 
04738    return parkinglot;
04739 }
04740 
04741 static int load_config(void) 
04742 {
04743    int start = 0, end = 0;
04744    int res;
04745    int i;
04746    struct ast_context *con = NULL;
04747    struct ast_config *cfg = NULL;
04748    struct ast_variable *var = NULL;
04749    struct feature_group *fg = NULL;
04750    struct ast_flags config_flags = { 0 };
04751    char *ctg; 
04752    static const char * const categories[] = { 
04753       /* Categories in features.conf that are not
04754        * to be parsed as group categories
04755        */
04756       "general",
04757       "featuremap",
04758       "applicationmap"
04759    };
04760 
04761    default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
04762    if (default_parkinglot) {
04763       ao2_lock(default_parkinglot);
04764       ast_copy_string(default_parkinglot->parkext, DEFAULT_PARK_EXTENSION, sizeof(default_parkinglot->parkext));
04765       default_parkinglot->parking_start = 701;
04766       default_parkinglot->parking_stop = 750;
04767       default_parkinglot->parking_offset = 0;
04768       default_parkinglot->parkfindnext = 0;
04769       default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
04770       ao2_unlock(default_parkinglot);
04771    }
04772    
04773    if (default_parkinglot) {
04774       ast_debug(1, "Configuration of default parkinglot done.\n");
04775    } else {
04776       ast_log(LOG_ERROR, "Configuration of default parkinglot failed.\n");
04777       return -1;
04778    }
04779 
04780    /* Reset to defaults */
04781    strcpy(default_parkinglot->parkext, DEFAULT_PARK_EXTENSION);
04782    strcpy(pickup_ext, "*8");
04783    courtesytone[0] = '\0';
04784    strcpy(xfersound, "beep");
04785    strcpy(xferfailsound, "pbx-invalid");
04786    pickupsound[0] = '\0';
04787    pickupfailsound[0] = '\0';
04788    adsipark = 0;
04789    comebacktoorigin = 1;
04790    parkeddynamic = 0;
04791 
04792    default_parkinglot->parkaddhints = 0;
04793    default_parkinglot->parkedcalltransfers = 0;
04794    default_parkinglot->parkedcallreparking = 0;
04795    default_parkinglot->parkedcallrecording = 0;
04796    default_parkinglot->parkedcallhangup = 0;
04797 
04798    transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
04799    featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
04800    atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
04801    atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
04802    atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
04803    atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
04804 
04805    cfg = ast_config_load2("features.conf", "features", config_flags);
04806    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
04807       ast_log(LOG_WARNING,"Could not load features.conf\n");
04808       return 0;
04809    }
04810    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
04811       if (!strcasecmp(var->name, "parkext")) {
04812          ast_copy_string(default_parkinglot->parkext, var->value, sizeof(default_parkinglot->parkext));
04813       } else if (!strcasecmp(var->name, "context")) {
04814          ast_copy_string(default_parkinglot->parking_con, var->value, sizeof(default_parkinglot->parking_con));
04815       } else if (!strcasecmp(var->name, "parkingtime")) {
04816          if ((sscanf(var->value, "%30d", &default_parkinglot->parkingtime) != 1) || (default_parkinglot->parkingtime < 1)) {
04817             ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
04818             default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
04819          } else
04820             default_parkinglot->parkingtime = default_parkinglot->parkingtime * 1000;
04821       } else if (!strcasecmp(var->name, "parkpos")) {
04822          if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
04823             ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of features.conf\n", var->lineno);
04824          } else if (default_parkinglot) {
04825             default_parkinglot->parking_start = start;
04826             default_parkinglot->parking_stop = end;
04827          } else {
04828             ast_log(LOG_WARNING, "No default parking lot!\n");
04829          }
04830       } else if (!strcasecmp(var->name, "findslot")) {
04831          default_parkinglot->parkfindnext = (!strcasecmp(var->value, "next"));
04832       } else if (!strcasecmp(var->name, "parkinghints")) {
04833          default_parkinglot->parkaddhints = ast_true(var->value);
04834       } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
04835          if (!strcasecmp(var->value, "both"))
04836             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
04837          else if (!strcasecmp(var->value, "caller"))
04838             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
04839          else if (!strcasecmp(var->value, "callee"))
04840             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
04841       } else if (!strcasecmp(var->name, "parkedcallreparking")) {
04842          if (!strcasecmp(var->value, "both"))
04843             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYBOTH;
04844          else if (!strcasecmp(var->value, "caller"))
04845             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLER;
04846          else if (!strcasecmp(var->value, "callee"))
04847             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLEE;
04848       } else if (!strcasecmp(var->name, "parkedcallhangup")) {
04849          if (!strcasecmp(var->value, "both"))
04850             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYBOTH;
04851          else if (!strcasecmp(var->value, "caller"))
04852             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLER;
04853          else if (!strcasecmp(var->value, "callee"))
04854             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLEE;
04855       } else if (!strcasecmp(var->name, "parkedcallrecording")) {
04856          if (!strcasecmp(var->value, "both"))
04857             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYBOTH;
04858          else if (!strcasecmp(var->value, "caller"))
04859             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
04860          else if (!strcasecmp(var->value, "callee"))
04861             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
04862       } else if (!strcasecmp(var->name, "parkeddynamic")) {
04863          parkeddynamic = ast_true(var->value);
04864       } else if (!strcasecmp(var->name, "adsipark")) {
04865          adsipark = ast_true(var->value);
04866       } else if (!strcasecmp(var->name, "transferdigittimeout")) {
04867          if ((sscanf(var->value, "%30d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
04868             ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
04869             transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
04870          } else
04871             transferdigittimeout = transferdigittimeout * 1000;
04872       } else if (!strcasecmp(var->name, "featuredigittimeout")) {
04873          if ((sscanf(var->value, "%30d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
04874             ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
04875             featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
04876          }
04877       } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
04878          if ((sscanf(var->value, "%30d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
04879             ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
04880             atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
04881          } else
04882             atxfernoanswertimeout = atxfernoanswertimeout * 1000;
04883       } else if (!strcasecmp(var->name, "atxferloopdelay")) {
04884          if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
04885             ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
04886             atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
04887          } else 
04888             atxferloopdelay *= 1000;
04889       } else if (!strcasecmp(var->name, "atxferdropcall")) {
04890          atxferdropcall = ast_true(var->value);
04891       } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
04892          if ((sscanf(var->value, "%30u", &atxfercallbackretries) != 1)) {
04893             ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
04894             atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
04895          }
04896       } else if (!strcasecmp(var->name, "courtesytone")) {
04897          ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
04898       }  else if (!strcasecmp(var->name, "parkedplay")) {
04899          if (!strcasecmp(var->value, "both"))
04900             parkedplay = 2;
04901          else if (!strcasecmp(var->value, "parked"))
04902             parkedplay = 1;
04903          else
04904             parkedplay = 0;
04905       } else if (!strcasecmp(var->name, "xfersound")) {
04906          ast_copy_string(xfersound, var->value, sizeof(xfersound));
04907       } else if (!strcasecmp(var->name, "xferfailsound")) {
04908          ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
04909       } else if (!strcasecmp(var->name, "pickupexten")) {
04910          ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
04911       } else if (!strcasecmp(var->name, "pickupsound")) {
04912          ast_copy_string(pickupsound, var->value, sizeof(pickupsound));
04913       } else if (!strcasecmp(var->name, "pickupfailsound")) {
04914          ast_copy_string(pickupfailsound, var->value, sizeof(pickupfailsound));
04915       } else if (!strcasecmp(var->name, "comebacktoorigin")) {
04916          comebacktoorigin = ast_true(var->value);
04917       } else if (!strcasecmp(var->name, "parkedmusicclass")) {
04918          ast_copy_string(default_parkinglot->mohclass, var->value, sizeof(default_parkinglot->mohclass));
04919       }
04920    }
04921 
04922    unmap_features();
04923    for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
04924       if (remap_feature(var->name, var->value))
04925          ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
04926    }
04927 
04928    /* Map a key combination to an application*/
04929    ast_unregister_features();
04930    for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
04931       char *tmp_val = ast_strdupa(var->value);
04932       char *activateon; 
04933       struct ast_call_feature *feature;
04934       AST_DECLARE_APP_ARGS(args,
04935          AST_APP_ARG(exten);
04936          AST_APP_ARG(activatedby);
04937          AST_APP_ARG(app);
04938          AST_APP_ARG(app_args);
04939          AST_APP_ARG(moh_class);
04940       );
04941 
04942       AST_STANDARD_APP_ARGS(args, tmp_val);
04943       if (strchr(args.app, '(')) {
04944          /* New syntax */
04945          args.moh_class = args.app_args;
04946          args.app_args = strchr(args.app, '(');
04947          *args.app_args++ = '\0';
04948          if (args.app_args[strlen(args.app_args) - 1] == ')') {
04949             args.app_args[strlen(args.app_args) - 1] = '\0';
04950          }
04951       }
04952 
04953       activateon = strsep(&args.activatedby, "/"); 
04954 
04955       /*! \todo XXX var_name or app_args ? */
04956       if (ast_strlen_zero(args.app) || ast_strlen_zero(args.exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
04957          ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
04958             args.app, args.exten, activateon, var->name);
04959          continue;
04960       }
04961 
04962       AST_RWLIST_RDLOCK(&feature_list);
04963       if ((feature = find_dynamic_feature(var->name))) {
04964          AST_RWLIST_UNLOCK(&feature_list);
04965          ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
04966          continue;
04967       }
04968       AST_RWLIST_UNLOCK(&feature_list);
04969             
04970       if (!(feature = ast_calloc(1, sizeof(*feature)))) {
04971          continue;
04972       }
04973 
04974       ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
04975       ast_copy_string(feature->app, args.app, FEATURE_APP_LEN);
04976       ast_copy_string(feature->exten, args.exten, FEATURE_EXTEN_LEN);
04977       
04978       if (args.app_args) {
04979          ast_copy_string(feature->app_args, args.app_args, FEATURE_APP_ARGS_LEN);
04980       }
04981 
04982       if (args.moh_class) {
04983          ast_copy_string(feature->moh_class, args.moh_class, FEATURE_MOH_LEN);
04984       }
04985 
04986       ast_copy_string(feature->exten, args.exten, sizeof(feature->exten));
04987       feature->operation = feature_exec_app;
04988       ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
04989 
04990       /* Allow caller and calle to be specified for backwards compatability */
04991       if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
04992          ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
04993       else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
04994          ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
04995       else {
04996          ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
04997             " must be 'self', or 'peer'\n", var->name);
04998          continue;
04999       }
05000 
05001       if (ast_strlen_zero(args.activatedby))
05002          ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
05003       else if (!strcasecmp(args.activatedby, "caller"))
05004          ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
05005       else if (!strcasecmp(args.activatedby, "callee"))
05006          ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
05007       else if (!strcasecmp(args.activatedby, "both"))
05008          ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
05009       else {
05010          ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
05011             " must be 'caller', or 'callee', or 'both'\n", var->name);
05012          continue;
05013       }
05014 
05015       ast_register_feature(feature);
05016 
05017       ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, args.app, args.app_args, args.exten);
05018    }
05019 
05020    ast_unregister_groups();
05021    AST_RWLIST_WRLOCK(&feature_groups);
05022 
05023    ctg = NULL;
05024    while ((ctg = ast_category_browse(cfg, ctg))) {
05025       /* Is this a parkinglot definition ? */
05026       if (!strncasecmp(ctg, "parkinglot_", strlen("parkinglot_"))) {
05027          ast_debug(2, "Found configuration section %s, assume parking context\n", ctg);
05028          if(!build_parkinglot(ctg, ast_variable_browse(cfg, ctg)))
05029             ast_log(LOG_ERROR, "Could not build parking lot %s. Configuration error.\n", ctg);
05030          else
05031             ast_debug(1, "Configured parking context %s\n", ctg);
05032          continue;   
05033       }
05034       /* No, check if it's a group */
05035       for (i = 0; i < ARRAY_LEN(categories); i++) {
05036          if (!strcasecmp(categories[i], ctg))
05037             break;
05038       }
05039 
05040       if (i < ARRAY_LEN(categories)) 
05041          continue;
05042 
05043       if (!(fg = register_group(ctg)))
05044          continue;
05045 
05046       for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
05047          struct ast_call_feature *feature;
05048 
05049          AST_RWLIST_RDLOCK(&feature_list);
05050          if (!(feature = find_dynamic_feature(var->name)) && 
05051              !(feature = ast_find_call_feature(var->name))) {
05052             AST_RWLIST_UNLOCK(&feature_list);
05053             ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
05054             continue;
05055          }
05056          AST_RWLIST_UNLOCK(&feature_list);
05057 
05058          register_group_feature(fg, var->value, feature);
05059       }
05060    }
05061 
05062    AST_RWLIST_UNLOCK(&feature_groups);
05063 
05064    ast_config_destroy(cfg);
05065 
05066    if (!(con = ast_context_find_or_create(NULL, NULL, default_parkinglot->parking_con, registrar))) {
05067       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", default_parkinglot->parking_con);
05068       return -1;
05069    }
05070    res = ast_add_extension2(con, 1, default_parkinglot->parkext, 1, NULL, NULL, parkcall, NULL, NULL, registrar);
05071    if (default_parkinglot->parkaddhints)
05072       park_add_hints(default_parkinglot->parking_con, default_parkinglot->parking_start, default_parkinglot->parking_stop);
05073    if (!res)
05074       notify_metermaids(default_parkinglot->parkext, default_parkinglot->parking_con, AST_DEVICE_INUSE); 
05075    return res;
05076 
05077 }
05078 
05079 /*!
05080  * \brief CLI command to list configured features
05081  * \param e
05082  * \param cmd
05083  * \param a
05084  *
05085  * \retval CLI_SUCCESS on success.
05086  * \retval NULL when tab completion is used.
05087  */
05088 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05089 {
05090    int i;
05091    struct ast_call_feature *feature;
05092    struct ao2_iterator iter;
05093    struct ast_parkinglot *curlot;
05094 #define HFS_FORMAT "%-25s %-7s %-7s\n"
05095 
05096    switch (cmd) {
05097    
05098    case CLI_INIT:
05099       e->command = "features show";
05100       e->usage =
05101          "Usage: features show\n"
05102          "       Lists configured features\n";
05103       return NULL;
05104    case CLI_GENERATE:
05105       return NULL;
05106    }
05107 
05108    ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
05109    ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
05110 
05111    ast_cli(a->fd, HFS_FORMAT, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
05112 
05113    ast_rwlock_rdlock(&features_lock);
05114    for (i = 0; i < FEATURES_COUNT; i++)
05115       ast_cli(a->fd, HFS_FORMAT, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
05116    ast_rwlock_unlock(&features_lock);
05117 
05118    ast_cli(a->fd, "\n");
05119    ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
05120    ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
05121    if (AST_RWLIST_EMPTY(&feature_list)) {
05122       ast_cli(a->fd, "(none)\n");
05123    } else {
05124       AST_RWLIST_RDLOCK(&feature_list);
05125       AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
05126          ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
05127       }
05128       AST_RWLIST_UNLOCK(&feature_list);
05129    }
05130 
05131    ast_cli(a->fd, "\nFeature Groups:\n");
05132    ast_cli(a->fd, "---------------\n");
05133    if (AST_RWLIST_EMPTY(&feature_groups)) {
05134       ast_cli(a->fd, "(none)\n");
05135    } else {
05136       struct feature_group *fg;
05137       struct feature_group_exten *fge;
05138 
05139       AST_RWLIST_RDLOCK(&feature_groups);
05140       AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
05141          ast_cli(a->fd, "===> Group: %s\n", fg->gname);
05142          AST_LIST_TRAVERSE(&fg->features, fge, entry) {
05143             ast_cli(a->fd, "===> --> %s (%s)\n", fge->feature->sname, fge->exten);
05144          }
05145       }
05146       AST_RWLIST_UNLOCK(&feature_groups);
05147    }
05148 
05149    iter = ao2_iterator_init(parkinglots, 0);
05150    while ((curlot = ao2_iterator_next(&iter))) {
05151       ast_cli(a->fd, "\nCall parking (Parking lot: %s)\n", curlot->name);
05152       ast_cli(a->fd, "------------\n");
05153       ast_cli(a->fd,"%-22s:      %s\n", "Parking extension", curlot->parkext);
05154       ast_cli(a->fd,"%-22s:      %s\n", "Parking context", curlot->parking_con);
05155       ast_cli(a->fd,"%-22s:      %d-%d\n", "Parked call extensions", curlot->parking_start, curlot->parking_stop);
05156       ast_cli(a->fd,"%-22s:      %d\n", "Parkingtime", curlot->parkingtime);
05157       ast_cli(a->fd,"%-22s:      %s\n", "MusicOnHold class", curlot->mohclass);
05158       ast_cli(a->fd,"\n");
05159       ao2_ref(curlot, -1);
05160    }
05161    ao2_iterator_destroy(&iter);
05162 
05163    return CLI_SUCCESS;
05164 }
05165 
05166 static int parkinglot_markall_cb(void *obj, void *arg, int flags)
05167 {
05168    struct ast_parkinglot *parkinglot = obj;
05169    parkinglot->the_mark = 1;
05170    return 0;
05171 }
05172 
05173 static int parkinglot_is_marked_cb(void *obj, void *arg, int flags)
05174 {
05175    struct ast_parkinglot *parkinglot = obj;
05176    return parkinglot->the_mark ? CMP_MATCH : 0;
05177 }
05178 
05179 int ast_features_reload(void)
05180 {
05181    int res;
05182 
05183    ao2_t_callback(parkinglots, OBJ_NODATA, parkinglot_markall_cb, NULL, "callback to mark all parkinglots");
05184    res = load_config(); /* Reload configuration */
05185    ao2_t_callback(parkinglots, OBJ_NODATA | OBJ_UNLINK, parkinglot_is_marked_cb, NULL, "callback to remove all marked parkinglots");
05186    
05187    return res;
05188 }
05189 
05190 static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05191 {
05192    switch (cmd) { 
05193    case CLI_INIT:
05194       e->command = "features reload";
05195       e->usage =
05196          "Usage: features reload\n"
05197          "       Reloads configured call features from features.conf\n";
05198       return NULL;
05199    case CLI_GENERATE:
05200       return NULL;
05201    }
05202    ast_features_reload();
05203 
05204    return CLI_SUCCESS;
05205 }
05206 
05207 /*!
05208  * \brief Actual bridge
05209  * \param chan
05210  * \param tmpchan
05211  * 
05212  * Stop hold music, lock both channels, masq channels,
05213  * after bridge return channel to next priority.
05214 */
05215 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
05216 {
05217    ast_moh_stop(chan);
05218    ast_channel_lock_both(chan, tmpchan);
05219    ast_setstate(tmpchan, chan->_state);
05220    tmpchan->readformat = chan->readformat;
05221    tmpchan->writeformat = chan->writeformat;
05222    ast_channel_masquerade(tmpchan, chan);
05223    ast_channel_unlock(chan);
05224    ast_channel_unlock(tmpchan);
05225 
05226    /* must be done without any channel locks held */
05227    ast_do_masquerade(tmpchan);
05228 
05229    /* when returning from bridge, the channel will continue at the next priority */
05230    ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
05231 }
05232 
05233 /*!
05234  * \brief Bridge channels together
05235  * \param s
05236  * \param m
05237  * 
05238  * Make sure valid channels were specified, 
05239  * send errors if any of the channels could not be found/locked, answer channels if needed,
05240  * create the placeholder channels and grab the other channels 
05241  * make the channels compatible, send error if we fail doing so 
05242  * setup the bridge thread object and start the bridge.
05243  * 
05244  * \retval 0 on success or on incorrect use.
05245  * \retval 1 on failure to bridge channels.
05246 */
05247 static int action_bridge(struct mansession *s, const struct message *m)
05248 {
05249    const char *channela = astman_get_header(m, "Channel1");
05250    const char *channelb = astman_get_header(m, "Channel2");
05251    const char *playtone = astman_get_header(m, "Tone");
05252    struct ast_channel *chana = NULL, *chanb = NULL, *chans[2];
05253    struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
05254    struct ast_bridge_thread_obj *tobj = NULL;
05255 
05256    /* make sure valid channels were specified */
05257    if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
05258       astman_send_error(s, m, "Missing channel parameter in request");
05259       return 0;
05260    }
05261 
05262    /* Start with chana */
05263    chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
05264 
05265    /* send errors if any of the channels could not be found/locked */
05266    if (!chana) {
05267       char buf[256];
05268       snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
05269       astman_send_error(s, m, buf);
05270       return 0;
05271    }
05272 
05273    /* Answer the channels if needed */
05274    if (chana->_state != AST_STATE_UP)
05275       ast_answer(chana);
05276 
05277    /* create the placeholder channels and grab the other channels */
05278    if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
05279       NULL, NULL, chana->linkedid, 0, "Bridge/%s", chana->name))) {
05280       astman_send_error(s, m, "Unable to create temporary channel!");
05281       chana = ast_channel_unref(chana);
05282       return 1;
05283    }
05284 
05285    do_bridge_masquerade(chana, tmpchana);
05286 
05287    chana = ast_channel_unref(chana);
05288 
05289    /* now do chanb */
05290    chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
05291    /* send errors if any of the channels could not be found/locked */
05292    if (!chanb) {
05293       char buf[256];
05294       snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
05295       ast_hangup(tmpchana);
05296       astman_send_error(s, m, buf);
05297       return 0;
05298    }
05299 
05300    /* Answer the channels if needed */
05301    if (chanb->_state != AST_STATE_UP)
05302       ast_answer(chanb);
05303 
05304    /* create the placeholder channels and grab the other channels */
05305    if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
05306       NULL, NULL, chanb->linkedid, 0, "Bridge/%s", chanb->name))) {
05307       astman_send_error(s, m, "Unable to create temporary channels!");
05308       ast_hangup(tmpchana);
05309       chanb = ast_channel_unref(chanb);
05310       return 1;
05311    }
05312 
05313    do_bridge_masquerade(chanb, tmpchanb);
05314 
05315    chanb = ast_channel_unref(chanb);
05316 
05317    /* make the channels compatible, send error if we fail doing so */
05318    if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
05319       ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
05320       astman_send_error(s, m, "Could not make channels compatible for manager bridge");
05321       ast_hangup(tmpchana);
05322       ast_hangup(tmpchanb);
05323       return 1;
05324    }
05325 
05326    /* setup the bridge thread object and start the bridge */
05327    if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
05328       ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
05329       astman_send_error(s, m, "Unable to spawn a new bridge thread");
05330       ast_hangup(tmpchana);
05331       ast_hangup(tmpchanb);
05332       return 1;
05333    }
05334 
05335    tobj->chan = tmpchana;
05336    tobj->peer = tmpchanb;
05337    tobj->return_to_pbx = 1;
05338 
05339    if (ast_true(playtone)) {
05340       if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
05341          if (ast_waitstream(tmpchanb, "") < 0)
05342             ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
05343       }
05344    }
05345 
05346    chans[0] = tmpchana;
05347    chans[1] = tmpchanb;
05348 
05349    ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeAction", 2, chans,
05350             "Response: Success\r\n"
05351             "Channel1: %s\r\n"
05352             "Channel2: %s\r\n", tmpchana->name, tmpchanb->name);
05353 
05354    bridge_call_thread_launch(tobj);
05355 
05356    astman_send_ack(s, m, "Launched bridge thread with success");
05357 
05358    return 0;
05359 }
05360 
05361 /*!
05362  * \brief CLI command to list parked calls
05363  * \param e 
05364  * \param cmd
05365  * \param a
05366  *  
05367  * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
05368  * \retval CLI_SUCCESS on success.
05369  * \retval CLI_SHOWUSAGE on incorrect number of arguments.
05370  * \retval NULL when tab completion is used.
05371 */
05372 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05373 {
05374    struct parkeduser *cur;
05375    int numparked = 0;
05376    struct ao2_iterator iter;
05377    struct ast_parkinglot *curlot;
05378 
05379    switch (cmd) {
05380    case CLI_INIT:
05381       e->command = "parkedcalls show";
05382       e->usage =
05383          "Usage: parkedcalls show\n"
05384          "       List currently parked calls\n";
05385       return NULL;
05386    case CLI_GENERATE:
05387       return NULL;
05388    }
05389 
05390    if (a->argc > e->args)
05391       return CLI_SHOWUSAGE;
05392 
05393    ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
05394       , "Context", "Extension", "Pri", "Timeout");
05395 
05396    iter = ao2_iterator_init(parkinglots, 0);
05397    while ((curlot = ao2_iterator_next(&iter))) {
05398       int lotparked = 0;
05399       /* subtract ref for iterator and for configured parking lot */
05400       ast_cli(a->fd, "*** Parking lot: %s (%d)\n", curlot->name, ao2_ref(curlot, 0) - 2);
05401 
05402       AST_LIST_LOCK(&curlot->parkings);
05403       AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
05404          ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
05405             ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
05406             ,cur->priority,
05407             (long)(cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL)) );
05408          numparked++;
05409          numparked += lotparked;
05410       }
05411       AST_LIST_UNLOCK(&curlot->parkings);
05412       if (lotparked)
05413          ast_cli(a->fd, "   %d parked call%s in parking lot %s\n", lotparked, ESS(lotparked), curlot->name);
05414 
05415       ao2_ref(curlot, -1);
05416    }
05417 
05418    ast_cli(a->fd, "---\n%d parked call%s in total.\n", numparked, ESS(numparked));
05419 
05420    return CLI_SUCCESS;
05421 }
05422 
05423 static struct ast_cli_entry cli_features[] = {
05424    AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
05425    AST_CLI_DEFINE(handle_features_reload, "Reloads configured features"),
05426    AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls"),
05427 };
05428 
05429 /*! 
05430  * \brief Dump parking lot status
05431  * \param s
05432  * \param m
05433  * 
05434  * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
05435  * \return Always RESULT_SUCCESS 
05436 */
05437 static int manager_parking_status(struct mansession *s, const struct message *m)
05438 {
05439    struct parkeduser *cur;
05440    const char *id = astman_get_header(m, "ActionID");
05441    char idText[256] = "";
05442    struct ao2_iterator iter;
05443    struct ast_parkinglot *curlot;
05444 
05445    if (!ast_strlen_zero(id))
05446       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
05447 
05448    astman_send_ack(s, m, "Parked calls will follow");
05449 
05450    iter = ao2_iterator_init(parkinglots, 0);
05451    while ((curlot = ao2_iterator_next(&iter))) {
05452 
05453       AST_LIST_LOCK(&curlot->parkings);
05454       AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
05455          astman_append(s, "Event: ParkedCall\r\n"
05456             "Exten: %d\r\n"
05457             "Channel: %s\r\n"
05458             "From: %s\r\n"
05459             "Timeout: %ld\r\n"
05460             "CallerIDNum: %s\r\n"
05461             "CallerIDName: %s\r\n"
05462             "%s"
05463             "\r\n",
05464             cur->parkingnum, cur->chan->name, cur->peername,
05465             (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
05466             S_COR(cur->chan->caller.id.number.valid, cur->chan->caller.id.number.str, ""),   /* XXX in other places it is <unknown> */
05467             S_COR(cur->chan->caller.id.name.valid, cur->chan->caller.id.name.str, ""),
05468             idText);
05469       }
05470       AST_LIST_UNLOCK(&curlot->parkings);
05471       ao2_ref(curlot, -1);
05472    }
05473 
05474    astman_append(s,
05475       "Event: ParkedCallsComplete\r\n"
05476       "%s"
05477       "\r\n",idText);
05478 
05479 
05480    return RESULT_SUCCESS;
05481 }
05482 
05483 /*!
05484  * \brief Create manager event for parked calls
05485  * \param s
05486  * \param m
05487  *
05488  * Get channels involved in park, create event.
05489  * \return Always 0
05490 */
05491 static int manager_park(struct mansession *s, const struct message *m)
05492 {
05493    const char *channel = astman_get_header(m, "Channel");
05494    const char *channel2 = astman_get_header(m, "Channel2");
05495    const char *timeout = astman_get_header(m, "Timeout");
05496    const char *parkinglotname = astman_get_header(m, "Parkinglot");
05497    char buf[BUFSIZ];
05498    int res = 0;
05499    struct ast_channel *ch1, *ch2;
05500    struct ast_park_call_args args = {0,};
05501 
05502    if (ast_strlen_zero(channel)) {
05503       astman_send_error(s, m, "Channel not specified");
05504       return 0;
05505    }
05506 
05507    if (ast_strlen_zero(channel2)) {
05508       astman_send_error(s, m, "Channel2 not specified");
05509       return 0;
05510    }
05511 
05512    if (!(ch1 = ast_channel_get_by_name(channel))) {
05513       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
05514       astman_send_error(s, m, buf);
05515       return 0;
05516    }
05517 
05518    if (!(ch2 = ast_channel_get_by_name(channel2))) {
05519       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
05520       astman_send_error(s, m, buf);
05521       ast_channel_unref(ch1);
05522       return 0;
05523    }
05524 
05525    if (!ast_strlen_zero(timeout)) {
05526       sscanf(timeout, "%30d", &args.timeout);
05527    }
05528    if (!ast_strlen_zero(parkinglotname)) {
05529       args.parkinglot = find_parkinglot(parkinglotname);
05530    }
05531 
05532    ast_channel_lock(ch1);
05533    while (ast_channel_trylock(ch2)) {
05534       CHANNEL_DEADLOCK_AVOIDANCE(ch1);
05535    }
05536 
05537    res = masq_park_call(ch1, ch2, 0, NULL, 0, &args);
05538    if (!res) {
05539       ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
05540       astman_send_ack(s, m, "Park successful");
05541    } else {
05542       astman_send_error(s, m, "Park failure");
05543    }
05544 
05545    ast_channel_unlock(ch1);
05546    ast_channel_unlock(ch2);
05547 
05548    ch1 = ast_channel_unref(ch1);
05549    ch2 = ast_channel_unref(ch2);
05550 
05551    return 0;
05552 }
05553 
05554 static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
05555 {
05556    struct ast_channel *c = data;
05557    struct ast_channel *chan = obj;
05558 
05559    int i = !chan->pbx &&
05560       /* Accessing 'chan' here is safe without locking, because there is no way for
05561          the channel do disappear from under us at this point.  pickupgroup *could*
05562          change while we're here, but that isn't a problem. */
05563       (c != chan) &&
05564       (chan->pickupgroup & c->callgroup) &&
05565       ((chan->_state == AST_STATE_RINGING) || (chan->_state == AST_STATE_RING));
05566 
05567    return i ? CMP_MATCH | CMP_STOP : 0;
05568 }
05569 
05570 /*!
05571  * \brief Pickup a call
05572  * \param chan channel that initiated pickup.
05573  *
05574  * Walk list of channels, checking it is not itself, channel is pbx one,
05575  * check that the callgroup for both channels are the same and the channel is ringing.
05576  * Answer calling channel, flag channel as answered on queue, masq channels together.
05577 */
05578 int ast_pickup_call(struct ast_channel *chan)
05579 {
05580    struct ast_channel *cur, *chans[2] = { chan, };
05581    struct ast_party_connected_line connected_caller;
05582    int res;
05583    const char *chan_name;
05584    const char *cur_name;
05585 
05586    if (!(cur = ast_channel_callback(find_channel_by_group, NULL, chan, 0))) {
05587       ast_debug(1, "No call pickup possible...\n");
05588       if (!ast_strlen_zero(pickupfailsound)) {
05589          ast_stream_and_wait(chan, pickupfailsound, "");
05590       }
05591       return -1;
05592    }
05593 
05594    chans[1] = cur;
05595 
05596    ast_channel_lock_both(cur, chan);
05597 
05598    cur_name = ast_strdupa(cur->name);
05599    chan_name = ast_strdupa(chan->name);
05600 
05601    ast_debug(1, "Call pickup on chan '%s' by '%s'\n", cur_name, chan_name);
05602 
05603    connected_caller = cur->connected;
05604    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
05605    if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
05606       ast_channel_update_connected_line(chan, &connected_caller, NULL);
05607    }
05608 
05609    ast_party_connected_line_collect_caller(&connected_caller, &chan->caller);
05610    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
05611    ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
05612 
05613    ast_channel_unlock(cur);
05614    ast_channel_unlock(chan);
05615 
05616    if (ast_answer(chan)) {
05617       ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
05618    }
05619 
05620    if (ast_queue_control(chan, AST_CONTROL_ANSWER)) {
05621       ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
05622    }
05623 
05624    if ((res = ast_channel_masquerade(cur, chan))) {
05625       ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan_name, cur_name);
05626    }
05627 
05628    if (!ast_strlen_zero(pickupsound)) {
05629       ast_stream_and_wait(cur, pickupsound, "");
05630    }
05631 
05632    /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
05633    ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
05634       "Channel: %s\r\nTargetChannel: %s\r\n", chan->name, cur->name);
05635 
05636    cur = ast_channel_unref(cur);
05637 
05638    return res;
05639 }
05640 
05641 static char *app_bridge = "Bridge";
05642 
05643 enum {
05644    BRIDGE_OPT_PLAYTONE = (1 << 0),
05645    OPT_CALLEE_HANGUP =  (1 << 1),
05646    OPT_CALLER_HANGUP =  (1 << 2),
05647    OPT_DURATION_LIMIT = (1 << 3),
05648    OPT_DURATION_STOP =  (1 << 4),
05649    OPT_CALLEE_TRANSFER = (1 << 5),
05650    OPT_CALLER_TRANSFER = (1 << 6),
05651    OPT_CALLEE_MONITOR = (1 << 7),
05652    OPT_CALLER_MONITOR = (1 << 8),
05653    OPT_CALLEE_PARK = (1 << 9),
05654    OPT_CALLER_PARK = (1 << 10),
05655    OPT_CALLEE_KILL = (1 << 11),
05656 };
05657  
05658 enum {
05659    OPT_ARG_DURATION_LIMIT = 0,
05660    OPT_ARG_DURATION_STOP,
05661    /* note: this entry _MUST_ be the last one in the enum */
05662    OPT_ARG_ARRAY_SIZE,
05663 };
05664 
05665 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
05666    AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE),
05667    AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
05668    AST_APP_OPTION('H', OPT_CALLER_HANGUP),
05669    AST_APP_OPTION('k', OPT_CALLEE_PARK),
05670    AST_APP_OPTION('K', OPT_CALLER_PARK),
05671    AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
05672    AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
05673    AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
05674    AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
05675    AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
05676    AST_APP_OPTION('W', OPT_CALLER_MONITOR),
05677    AST_APP_OPTION('x', OPT_CALLEE_KILL),
05678 END_OPTIONS );
05679 
05680 int ast_bridge_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
05681    char *parse, struct timeval *calldurationlimit)
05682 {
05683    char *stringp = ast_strdupa(parse);
05684    char *limit_str, *warning_str, *warnfreq_str;
05685    const char *var;
05686    int play_to_caller = 0, play_to_callee = 0;
05687    int delta;
05688 
05689    limit_str = strsep(&stringp, ":");
05690    warning_str = strsep(&stringp, ":");
05691    warnfreq_str = strsep(&stringp, ":");
05692 
05693    config->timelimit = atol(limit_str);
05694    if (warning_str)
05695       config->play_warning = atol(warning_str);
05696    if (warnfreq_str)
05697       config->warning_freq = atol(warnfreq_str);
05698 
05699    if (!config->timelimit) {
05700       ast_log(LOG_WARNING, "Bridge does not accept L(%s), hanging up.\n", limit_str);
05701       config->timelimit = config->play_warning = config->warning_freq = 0;
05702       config->warning_sound = NULL;
05703       return -1; /* error */
05704    } else if ( (delta = config->play_warning - config->timelimit) > 0) {
05705       int w = config->warning_freq;
05706 
05707       /* If the first warning is requested _after_ the entire call would end,
05708          and no warning frequency is requested, then turn off the warning. If
05709          a warning frequency is requested, reduce the 'first warning' time by
05710          that frequency until it falls within the call's total time limit.
05711          Graphically:
05712               timelim->|    delta        |<-playwarning
05713          0__________________|_________________|
05714                 | w  |    |    |    |
05715 
05716          so the number of intervals to cut is 1+(delta-1)/w
05717       */
05718 
05719       if (w == 0) {
05720          config->play_warning = 0;
05721       } else {
05722          config->play_warning -= w * ( 1 + (delta-1)/w );
05723          if (config->play_warning < 1)
05724             config->play_warning = config->warning_freq = 0;
05725       }
05726    }
05727    
05728    ast_channel_lock(chan);
05729 
05730    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
05731    play_to_caller = var ? ast_true(var) : 1;
05732 
05733    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
05734    play_to_callee = var ? ast_true(var) : 0;
05735 
05736    if (!play_to_caller && !play_to_callee)
05737       play_to_caller = 1;
05738 
05739    var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
05740    config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
05741 
05742    /* The code looking at config wants a NULL, not just "", to decide
05743     * that the message should not be played, so we replace "" with NULL.
05744     * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
05745     * not found.
05746     */
05747 
05748    var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
05749    config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
05750 
05751    var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
05752    config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
05753 
05754    ast_channel_unlock(chan);
05755 
05756    /* undo effect of S(x) in case they are both used */
05757    calldurationlimit->tv_sec = 0;
05758    calldurationlimit->tv_usec = 0;
05759 
05760    /* more efficient to do it like S(x) does since no advanced opts */
05761    if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
05762       calldurationlimit->tv_sec = config->timelimit / 1000;
05763       calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
05764       ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
05765          calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
05766       config->timelimit = play_to_caller = play_to_callee =
05767       config->play_warning = config->warning_freq = 0;
05768    } else {
05769       ast_verb(4, "Limit Data for this call:\n");
05770       ast_verb(4, "timelimit      = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0);
05771       ast_verb(4, "play_warning   = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0);
05772       ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
05773       ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
05774       ast_verb(4, "warning_freq   = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0);
05775       ast_verb(4, "start_sound    = %s\n", S_OR(config->start_sound, ""));
05776       ast_verb(4, "warning_sound  = %s\n", config->warning_sound);
05777       ast_verb(4, "end_sound      = %s\n", S_OR(config->end_sound, ""));
05778    }
05779    if (play_to_caller)
05780       ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
05781    if (play_to_callee)
05782       ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
05783    return 0;
05784 }
05785 
05786 
05787 /*!
05788  * \brief Bridge channels
05789  * \param chan
05790  * \param data channel to bridge with.
05791  * 
05792  * Split data, check we aren't bridging with ourself, check valid channel,
05793  * answer call if not already, check compatible channels, setup bridge config
05794  * now bridge call, if transfered party hangs up return to PBX extension.
05795 */
05796 static int bridge_exec(struct ast_channel *chan, const char *data)
05797 {
05798    struct ast_channel *current_dest_chan, *final_dest_chan, *chans[2];
05799    char *tmp_data  = NULL;
05800    struct ast_flags opts = { 0, };
05801    struct ast_bridge_config bconfig = { { 0, }, };
05802    char *opt_args[OPT_ARG_ARRAY_SIZE];
05803    struct timeval calldurationlimit = { 0, };
05804 
05805    AST_DECLARE_APP_ARGS(args,
05806       AST_APP_ARG(dest_chan);
05807       AST_APP_ARG(options);
05808    );
05809    
05810    if (ast_strlen_zero(data)) {
05811       ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
05812       return -1;
05813    }
05814 
05815    tmp_data = ast_strdupa(data);
05816    AST_STANDARD_APP_ARGS(args, tmp_data);
05817    if (!ast_strlen_zero(args.options))
05818       ast_app_parse_options(bridge_exec_options, &opts, opt_args, args.options);
05819 
05820    /* avoid bridge with ourselves */
05821    if (!strcmp(chan->name, args.dest_chan)) {
05822       ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
05823       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
05824                "Response: Failed\r\n"
05825                "Reason: Unable to bridge channel to itself\r\n"
05826                "Channel1: %s\r\n"
05827                "Channel2: %s\r\n",
05828                chan->name, args.dest_chan);
05829       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
05830       return 0;
05831    }
05832 
05833    /* make sure we have a valid end point */
05834    if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
05835          strlen(args.dest_chan)))) {
05836       ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
05837          "cannot get its lock\n", args.dest_chan);
05838       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
05839                "Response: Failed\r\n"
05840                "Reason: Cannot grab end point\r\n"
05841                "Channel1: %s\r\n"
05842                "Channel2: %s\r\n", chan->name, args.dest_chan);
05843       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
05844       return 0;
05845    }
05846 
05847    /* answer the channel if needed */
05848    if (current_dest_chan->_state != AST_STATE_UP) {
05849       ast_answer(current_dest_chan);
05850    }
05851 
05852    /* try to allocate a place holder where current_dest_chan will be placed */
05853    if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
05854       NULL, NULL, current_dest_chan->linkedid, 0, "Bridge/%s", current_dest_chan->name))) {
05855       ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
05856       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
05857                "Response: Failed\r\n"
05858                "Reason: cannot create placeholder\r\n"
05859                "Channel1: %s\r\n"
05860                "Channel2: %s\r\n", chan->name, args.dest_chan);
05861    }
05862 
05863    ast_channel_unlock(current_dest_chan);
05864 
05865    do_bridge_masquerade(current_dest_chan, final_dest_chan);
05866 
05867    chans[0] = current_dest_chan;
05868    chans[1] = final_dest_chan;
05869 
05870    /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
05871    /* try to make compatible, send error if we fail */
05872    if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
05873       ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
05874       ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
05875                "Response: Failed\r\n"
05876                "Reason: Could not make channels compatible for bridge\r\n"
05877                "Channel1: %s\r\n"
05878                "Channel2: %s\r\n", chan->name, final_dest_chan->name);
05879       ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
05880       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
05881       current_dest_chan = ast_channel_unref(current_dest_chan);
05882       return 0;
05883    }
05884 
05885    /* Report that the bridge will be successfull */
05886    ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
05887             "Response: Success\r\n"
05888             "Channel1: %s\r\n"
05889             "Channel2: %s\r\n", chan->name, final_dest_chan->name);
05890 
05891    /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */  
05892    if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
05893       if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
05894          if (ast_waitstream(final_dest_chan, "") < 0)
05895             ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
05896       }
05897    }
05898    
05899    current_dest_chan = ast_channel_unref(current_dest_chan);
05900    
05901    if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
05902       if (ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
05903          goto done;
05904    }
05905 
05906    if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER))
05907       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_REDIRECT);
05908    if (ast_test_flag(&opts, OPT_CALLER_TRANSFER))
05909       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_REDIRECT);
05910    if (ast_test_flag(&opts, OPT_CALLEE_HANGUP))
05911       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
05912    if (ast_test_flag(&opts, OPT_CALLER_HANGUP))
05913       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
05914    if (ast_test_flag(&opts, OPT_CALLEE_MONITOR))
05915       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_AUTOMON);
05916    if (ast_test_flag(&opts, OPT_CALLER_MONITOR)) 
05917       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_AUTOMON);
05918    if (ast_test_flag(&opts, OPT_CALLEE_PARK))
05919       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_PARKCALL);
05920    if (ast_test_flag(&opts, OPT_CALLER_PARK))
05921       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_PARKCALL);
05922 
05923    ast_bridge_call(chan, final_dest_chan, &bconfig);
05924 
05925    /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
05926    pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
05927    if (!ast_check_hangup(final_dest_chan) && !ast_test_flag(&opts, OPT_CALLEE_KILL)) {
05928       ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n", 
05929          final_dest_chan->context, final_dest_chan->exten, 
05930          final_dest_chan->priority, final_dest_chan->name);
05931 
05932       if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
05933          ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
05934          ast_hangup(final_dest_chan);
05935       } else
05936          ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
05937    } else {
05938       ast_debug(1, "hangup chan %s since the other endpoint has hung up or the x flag was passed\n", final_dest_chan->name);
05939       ast_hangup(final_dest_chan);
05940    }
05941 done:
05942    if (bconfig.warning_sound) {
05943       ast_free((char *)bconfig.warning_sound);
05944    }
05945    if (bconfig.end_sound) {
05946       ast_free((char *)bconfig.end_sound);
05947    }
05948    if (bconfig.start_sound) {
05949       ast_free((char *)bconfig.start_sound);
05950    }
05951 
05952    return 0;
05953 }
05954 
05955 int ast_features_init(void)
05956 {
05957    int res;
05958 
05959    ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
05960 
05961    parkinglots = ao2_container_alloc(7, parkinglot_hash_cb, parkinglot_cmp_cb);
05962 
05963    if ((res = load_config()))
05964       return res;
05965    ast_cli_register_multiple(cli_features, ARRAY_LEN(cli_features));
05966    ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
05967    res = ast_register_application2(parkedcall, park_exec, NULL, NULL, NULL);
05968    if (!res)
05969       res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
05970    if (!res) {
05971       ast_manager_register_xml("ParkedCalls", 0, manager_parking_status);
05972       ast_manager_register_xml("Park", EVENT_FLAG_CALL, manager_park);
05973       ast_manager_register_xml("Bridge", EVENT_FLAG_CALL, action_bridge);
05974    }
05975 
05976    res |= ast_devstate_prov_add("Park", metermaidstate);
05977 #ifdef TEST_FRAMEWORK
05978    res |= AST_TEST_REGISTER(features_test);
05979 #endif
05980 
05981    return res;
05982 }

Generated on Wed Apr 6 11:29:44 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7