Mon Jun 27 16:50:53 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: 324704 $")
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    ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
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, format_t 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 or error, (would be 0 for invalid and 1 for valid) */
01876       finishup(transferee);
01877       return -1;
01878    }
01879    if (res == 0) {
01880       if (xferto[0]) {
01881          ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
01882             xferto, transferer_real_context);
01883       } else {
01884          /* Does anyone care about this case? */
01885          ast_log(LOG_WARNING, "No digits dialed.\n");
01886       }
01887       ast_stream_and_wait(transferer, "pbx-invalid", "");
01888       finishup(transferee);
01889       return AST_FEATURE_RETURN_SUCCESS;
01890    }
01891 
01892    found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
01893    if (found_lot) {
01894       struct ast_park_call_args args = {
01895          .parkinglot = found_lot,
01896       };
01897       res = finishup(transferee);
01898       if (res) {
01899       } else if (!(parkstatus = masq_park_call_announce(transferee, transferer, &args))) {   /* success */
01900          /* We return non-zero, but tell the PBX not to hang the channel when
01901             the thread dies -- We have to be careful now though.  We are responsible for 
01902             hanging up the channel, else it will never be hung up! */
01903 
01904          return 0;
01905       } else {
01906          ast_log(LOG_WARNING, "Unable to park call %s, parkstatus = %d\n", transferee->name, parkstatus);
01907       }
01908       ast_autoservice_start(transferee);
01909    } else {
01910       ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
01911       pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
01912       pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
01913       res=finishup(transferee);
01914       if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
01915          transferer->cdr=ast_cdr_alloc();
01916          if (transferer->cdr) {
01917             ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
01918             ast_cdr_start(transferer->cdr);
01919          }
01920       }
01921       if (transferer->cdr) {
01922          struct ast_cdr *swap = transferer->cdr;
01923          ast_log(LOG_DEBUG,"transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
01924                transferer->name, transferee->name, transferer->cdr->lastapp, transferer->cdr->lastdata, 
01925                transferer->cdr->channel, transferer->cdr->dstchannel);
01926          ast_log(LOG_DEBUG,"TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
01927                transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel, transferee->cdr->dstchannel);
01928          ast_log(LOG_DEBUG,"transferer_real_context=%s; xferto=%s\n", transferer_real_context, xferto);
01929          /* swap cdrs-- it will save us some time & work */
01930          transferer->cdr = transferee->cdr;
01931          transferee->cdr = swap;
01932       }
01933       if (!transferee->pbx) {
01934          /* Doh!  Use our handy async_goto functions */
01935          ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
01936                         ,transferee->name, xferto, transferer_real_context);
01937          if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
01938             ast_log(LOG_WARNING, "Async goto failed :-(\n");
01939       } else {
01940          /* Set the channel's new extension, since it exists, using transferer context */
01941          ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
01942          ast_log(LOG_DEBUG,"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
01943          if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
01944             ast_channel_update_connected_line(transferer, &transferer->connected, NULL);
01945          }
01946          set_c_e_p(transferee, transferer_real_context, xferto, 0);
01947       }
01948       check_goto_on_transfer(transferer);
01949       return res;
01950    }
01951    if (parkstatus != AST_FEATURE_RETURN_PARKFAILED
01952       && ast_stream_and_wait(transferer, xferfailsound, "")) {
01953       finishup(transferee);
01954       return -1;
01955    }
01956    ast_stopstream(transferer);
01957    res = finishup(transferee);
01958    if (res) {
01959       ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
01960       return res;
01961    }
01962    return AST_FEATURE_RETURN_SUCCESS;
01963 }
01964 
01965 /*!
01966  * \brief make channels compatible
01967  * \param c
01968  * \param newchan
01969  * \retval 0 on success.
01970  * \retval -1 on failure.
01971 */
01972 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
01973 {
01974    if (ast_channel_make_compatible(c, newchan) < 0) {
01975       ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
01976          c->name, newchan->name);
01977       ast_hangup(newchan);
01978       return -1;
01979    }
01980    return 0;
01981 }
01982 
01983 /*!
01984  * \internal
01985  * \brief Builtin attended transfer failed cleanup.
01986  * \since 1.10
01987  *
01988  * \param transferee Party A in the transfer.
01989  * \param transferer Party B in the transfer.
01990  * \param connected_line Saved connected line info about party A.
01991  *
01992  * \note The connected_line data is freed.
01993  *
01994  * \return Nothing
01995  */
01996 static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
01997 {
01998    finishup(transferee);
01999 
02000    /*
02001     * Restore party B connected line info about party A.
02002     *
02003     * Party B was the caller to party C and is the last known mode
02004     * for party B.
02005     */
02006    if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
02007       ast_channel_update_connected_line(transferer, connected_line, NULL);
02008    }
02009    ast_party_connected_line_free(connected_line);
02010 }
02011 
02012 /*!
02013  * \brief Attended transfer
02014  * \param chan transfered user
02015  * \param peer person transfering call
02016  * \param config
02017  * \param code
02018  * \param sense feature options
02019  *
02020  * \param data
02021  * Get extension to transfer to, if you cannot generate channel (or find extension)
02022  * return to host channel. After called channel answered wait for hangup of transferer,
02023  * bridge call between transfer peer (taking them off hold) to attended transfer channel.
02024  *
02025  * \return -1 on failure
02026 */
02027 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
02028 {
02029    struct ast_channel *transferer;/* Party B */
02030    struct ast_channel *transferee;/* Party A */
02031    const char *transferer_real_context;
02032    char xferto[256] = "";
02033    int res;
02034    int outstate=0;
02035    struct ast_channel *newchan;
02036    struct ast_channel *xferchan;
02037    struct ast_bridge_thread_obj *tobj;
02038    struct ast_bridge_config bconfig;
02039    int l;
02040    struct ast_party_connected_line connected_line;
02041    struct ast_datastore *features_datastore;
02042    struct ast_dial_features *dialfeatures = NULL;
02043    struct ast_parkinglot *parkinglot;
02044    char *transferer_tech;
02045    char *transferer_name;
02046    char *transferer_name_orig;
02047    char *dash;
02048 
02049    ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
02050    set_peers(&transferer, &transferee, peer, chan, sense);
02051    transferer_real_context = real_ctx(transferer, transferee);
02052 
02053    /* Start autoservice on transferee while we talk to the transferer */
02054    ast_autoservice_start(transferee);
02055    ast_indicate(transferee, AST_CONTROL_HOLD);
02056 
02057    /* Transfer */
02058    res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
02059    if (res < 0) {
02060       finishup(transferee);
02061       return -1;
02062    }
02063    if (res > 0) /* If they've typed a digit already, handle it */
02064       xferto[0] = (char) res;
02065 
02066    /* this is specific of atxfer */
02067    res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
02068    if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
02069       finishup(transferee);
02070       return -1;
02071    }
02072    l = strlen(xferto);
02073    if (res == 0) {
02074       if (l) {
02075          ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
02076             xferto, transferer_real_context);
02077       } else {
02078          /* Does anyone care about this case? */
02079          ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
02080       }
02081       ast_stream_and_wait(transferer, "pbx-invalid", "");
02082       finishup(transferee);
02083       return AST_FEATURE_RETURN_SUCCESS;
02084    }
02085 
02086    /* If we are attended transfering to parking, just use parkcall_helper instead of trying to track all of
02087     * the different variables for handling this properly with a builtin_atxfer */
02088    parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
02089    if (parkinglot) {
02090       struct ast_park_call_args args = {
02091          .parkinglot = parkinglot,
02092       };
02093       finishup(transferee);
02094       return parkcall_helper(chan, peer, config, code, sense, &args);
02095    }
02096 
02097    /* Append context to dialed transfer number. */
02098    snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
02099 
02100    /* If we are performing an attended transfer and we have two channels involved then
02101       copy sound file information to play upon attended transfer completion */
02102    if (transferee) {
02103       const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
02104       const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
02105 
02106       if (!ast_strlen_zero(chan1_attended_sound)) {
02107          pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
02108       }
02109       if (!ast_strlen_zero(chan2_attended_sound)) {
02110          pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
02111       }
02112    }
02113 
02114    /* Extract redial transferer information from the channel name. */
02115    transferer_name_orig = ast_strdupa(transferer->name);
02116    transferer_name = ast_strdupa(transferer_name_orig);
02117    transferer_tech = strsep(&transferer_name, "/");
02118    dash = strrchr(transferer_name, '-');
02119    if (dash) {
02120       /* Trim off channel name sequence/serial number. */
02121       *dash = '\0';
02122    }
02123 
02124    /* Stop autoservice so we can monitor all parties involved in the transfer. */
02125    if (ast_autoservice_stop(transferee) < 0) {
02126       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02127       return -1;
02128    }
02129 
02130    /* Save connected line info for party B about party A in case transfer fails. */
02131    ast_party_connected_line_init(&connected_line);
02132    ast_channel_lock(transferer);
02133    ast_party_connected_line_copy(&connected_line, &transferer->connected);
02134    ast_channel_unlock(transferer);
02135    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02136 
02137    /* Dial party C */
02138    newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
02139       transferee, "Local", ast_best_codec(transferer->nativeformats), xferto,
02140       atxfernoanswertimeout, &outstate, transferer->language);
02141    ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
02142 
02143    if (!ast_check_hangup(transferer)) {
02144       int hangup_dont = 0;
02145 
02146       /* Transferer (party B) is up */
02147       ast_debug(1, "Actually doing an attended transfer.\n");
02148 
02149       /* Start autoservice on transferee while the transferer deals with party C. */
02150       ast_autoservice_start(transferee);
02151 
02152       ast_indicate(transferer, -1);
02153       if (!newchan) {
02154          /* any reason besides user requested cancel and busy triggers the failed sound */
02155          switch (outstate) {
02156          case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
02157          case AST_CONTROL_BUSY:
02158          case AST_CONTROL_CONGESTION:
02159             if (ast_stream_and_wait(transferer, xfersound, "")) {
02160                ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02161             }
02162             break;
02163          default:
02164             if (ast_stream_and_wait(transferer, xferfailsound, "")) {
02165                ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
02166             }
02167             break;
02168          }
02169          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02170          return AST_FEATURE_RETURN_SUCCESS;
02171       }
02172 
02173       if (check_compat(transferer, newchan)) {
02174          if (ast_stream_and_wait(transferer, xferfailsound, "")) {
02175             ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
02176          }
02177          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02178          return AST_FEATURE_RETURN_SUCCESS;
02179       }
02180       memset(&bconfig,0,sizeof(struct ast_bridge_config));
02181       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
02182       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
02183 
02184       /* ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we don't
02185          want that to happen here because we're also in another bridge already
02186        */
02187       if (ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)) {
02188          hangup_dont = 1;
02189       }
02190       /* Let party B and party C talk as long as they want. */
02191       ast_bridge_call(transferer, newchan, &bconfig);
02192       if (hangup_dont) {
02193          ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
02194       }
02195 
02196       if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
02197          ast_hangup(newchan);
02198          if (ast_stream_and_wait(transferer, xfersound, "")) {
02199             ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02200          }
02201          atxfer_fail_cleanup(transferee, transferer, &connected_line);
02202          return AST_FEATURE_RETURN_SUCCESS;
02203       }
02204 
02205       /* Transferer (party B) is confirmed hung up at this point. */
02206       if (check_compat(transferee, newchan)) {
02207          finishup(transferee);
02208          ast_party_connected_line_free(&connected_line);
02209          return -1;
02210       }
02211 
02212       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02213       if ((ast_autoservice_stop(transferee) < 0)
02214          || (ast_waitfordigit(transferee, 100) < 0)
02215          || (ast_waitfordigit(newchan, 100) < 0)
02216          || ast_check_hangup(transferee)
02217          || ast_check_hangup(newchan)) {
02218          ast_hangup(newchan);
02219          ast_party_connected_line_free(&connected_line);
02220          return -1;
02221       }
02222    } else if (!ast_check_hangup(transferee)) {
02223       /* Transferer (party B) has hung up at this point.  Doing blonde transfer. */
02224       ast_debug(1, "Actually doing a blonde transfer.\n");
02225 
02226       if (!newchan && !atxferdropcall) {
02227          /* Party C is not available, try to call party B back. */
02228          unsigned int tries = 0;
02229 
02230          if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
02231             ast_log(LOG_WARNING,
02232                "Transferer channel name: '%s' cannot be used for callback.\n",
02233                transferer_name_orig);
02234             ast_indicate(transferee, AST_CONTROL_UNHOLD);
02235             ast_party_connected_line_free(&connected_line);
02236             return -1;
02237          }
02238 
02239          tries = 0;
02240          for (;;) {
02241             /* Try to get party B back. */
02242             ast_debug(1, "We're trying to callback %s/%s\n",
02243                transferer_tech, transferer_name);
02244             newchan = feature_request_and_dial(transferer, transferer_name_orig,
02245                transferee, transferee, transferer_tech,
02246                ast_best_codec(transferee->nativeformats), transferer_name,
02247                atxfernoanswertimeout, &outstate, transferer->language);
02248             ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
02249                !!newchan, outstate);
02250             if (newchan || ast_check_hangup(transferee)) {
02251                break;
02252             }
02253 
02254             ++tries;
02255             if (atxfercallbackretries <= tries) {
02256                /* No more callback tries remaining. */
02257                break;
02258             }
02259 
02260             if (atxferloopdelay) {
02261                /* Transfer failed, sleeping */
02262                ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
02263                   atxferloopdelay);
02264                ast_safe_sleep(transferee, atxferloopdelay);
02265                if (ast_check_hangup(transferee)) {
02266                   ast_party_connected_line_free(&connected_line);
02267                   return -1;
02268                }
02269             }
02270 
02271             /* Retry dialing party C. */
02272             ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
02273             newchan = feature_request_and_dial(transferer, transferer_name_orig,
02274                transferer, transferee, "Local",
02275                ast_best_codec(transferee->nativeformats), xferto,
02276                atxfernoanswertimeout, &outstate, transferer->language);
02277             ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
02278                !!newchan, outstate);
02279             if (newchan || ast_check_hangup(transferee)) {
02280                break;
02281             }
02282          }
02283       }
02284       ast_indicate(transferee, AST_CONTROL_UNHOLD);
02285       if (!newchan) {
02286          /* No party C or could not callback party B. */
02287          ast_party_connected_line_free(&connected_line);
02288          return -1;
02289       }
02290 
02291       /* newchan is up, we should prepare transferee and bridge them */
02292       if (ast_check_hangup(newchan)) {
02293          ast_hangup(newchan);
02294          ast_party_connected_line_free(&connected_line);
02295          return -1;
02296       }
02297       if (check_compat(transferee, newchan)) {
02298          ast_party_connected_line_free(&connected_line);
02299          return -1;
02300       }
02301    } else {
02302       /*
02303        * Both the transferer and transferee have hungup.  If newchan
02304        * is up, hang it up as it has no one to talk to.
02305        */
02306       ast_debug(1, "Everyone is hungup.\n");
02307       if (newchan) {
02308          ast_hangup(newchan);
02309       }
02310       ast_party_connected_line_free(&connected_line);
02311       return -1;
02312    }
02313 
02314    /* Initiate the channel transfer of party A to party C (or recalled party B). */
02315    ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
02316 
02317    xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", transferee->linkedid, 0, "Transfered/%s", transferee->name);
02318    if (!xferchan) {
02319       ast_hangup(newchan);
02320       ast_party_connected_line_free(&connected_line);
02321       return -1;
02322    }
02323 
02324    /* Give party A a momentary ringback tone during transfer. */
02325    xferchan->visible_indication = AST_CONTROL_RINGING;
02326 
02327    /* Make formats okay */
02328    xferchan->readformat = transferee->readformat;
02329    xferchan->writeformat = transferee->writeformat;
02330 
02331    ast_channel_masquerade(xferchan, transferee);
02332    ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
02333    xferchan->_state = AST_STATE_UP;
02334    ast_clear_flag(xferchan, AST_FLAGS_ALL);
02335 
02336    /* Do the masquerade manually to make sure that is is completed. */
02337    ast_do_masquerade(xferchan);
02338 
02339    newchan->_state = AST_STATE_UP;
02340    ast_clear_flag(newchan, AST_FLAGS_ALL);
02341    tobj = ast_calloc(1, sizeof(*tobj));
02342    if (!tobj) {
02343       ast_hangup(xferchan);
02344       ast_hangup(newchan);
02345       ast_party_connected_line_free(&connected_line);
02346       return -1;
02347    }
02348 
02349    ast_channel_lock(newchan);
02350    if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
02351       dialfeatures = features_datastore->data;
02352    }
02353    ast_channel_unlock(newchan);
02354 
02355    if (dialfeatures) {
02356       /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
02357          I don't currently understand, the abilities of newchan seem to be stored on the caller side */
02358       ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
02359       dialfeatures = NULL;
02360    }
02361 
02362    ast_channel_lock(xferchan);
02363    if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
02364       dialfeatures = features_datastore->data;
02365    }
02366    ast_channel_unlock(xferchan);
02367 
02368    if (dialfeatures) {
02369       ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
02370    }
02371 
02372    tobj->chan = newchan;
02373    tobj->peer = xferchan;
02374    tobj->bconfig = *config;
02375 
02376    if (tobj->bconfig.end_bridge_callback_data_fixup) {
02377       tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
02378    }
02379 
02380    /*
02381     * xferchan is transferee, and newchan is the transfer target
02382     * So...in a transfer, who is the caller and who is the callee?
02383     *
02384     * When the call is originally made, it is clear who is caller and callee.
02385     * When a transfer occurs, it is my humble opinion that the transferee becomes
02386     * the caller, and the transfer target is the callee.
02387     *
02388     * The problem is that these macros were set with the intention of the original
02389     * caller and callee taking those roles.  A transfer can totally mess things up,
02390     * to be technical.  What sucks even more is that you can't effectively change
02391     * the macros in the dialplan during the call from the transferer to the transfer
02392     * target because the transferee is stuck with whatever role he originally had.
02393     *
02394     * I think the answer here is just to make sure that it is well documented that
02395     * during a transfer, the transferee is the "caller" and the transfer target
02396     * is the "callee."
02397     *
02398     * This means that if party B calls party A, and party B transfers party A to
02399     * party C, then A has switched roles for the call.  Now party A will have the
02400     * caller macro called on his channel instead of the callee macro.
02401     *
02402     * Luckily, the method by which the party B to party C bridge is
02403     * launched above ensures that the transferee is the "chan" on
02404     * the bridge and the transfer target is the "peer," so my idea
02405     * for the roles post-transfer does not require extensive code
02406     * changes.
02407     */
02408 
02409    /* Transfer party C connected line to party A */
02410    ast_channel_lock(transferer);
02411    /*
02412     * Due to a limitation regarding when callerID is set on a Local channel,
02413     * we use the transferer's connected line information here.
02414     */
02415    ast_party_connected_line_copy(&connected_line, &transferer->connected);
02416    ast_channel_unlock(transferer);
02417    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02418    if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
02419       ast_channel_update_connected_line(xferchan, &connected_line, NULL);
02420    }
02421 
02422    /* Transfer party A connected line to party C */
02423    ast_channel_lock(xferchan);
02424    ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
02425    ast_channel_unlock(xferchan);
02426    connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
02427    if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
02428       ast_channel_update_connected_line(newchan, &connected_line, NULL);
02429    }
02430 
02431    if (ast_stream_and_wait(newchan, xfersound, ""))
02432       ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
02433    bridge_call_thread_launch(tobj);
02434 
02435    ast_party_connected_line_free(&connected_line);
02436    return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
02437 }
02438 
02439 /* add atxfer and automon as undefined so you can only use em if you configure them */
02440 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
02441 
02442 AST_RWLOCK_DEFINE_STATIC(features_lock);
02443 
02444 static struct ast_call_feature builtin_features[] = {
02445    { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02446    { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02447    { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02448    { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02449    { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02450    { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
02451 };
02452 
02453 
02454 static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
02455 
02456 /*! \brief register new feature into feature_list*/
02457 void ast_register_feature(struct ast_call_feature *feature)
02458 {
02459    if (!feature) {
02460       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
02461       return;
02462    }
02463   
02464    AST_RWLIST_WRLOCK(&feature_list);
02465    AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
02466    AST_RWLIST_UNLOCK(&feature_list);
02467 
02468    ast_verb(2, "Registered Feature '%s'\n",feature->sname);
02469 }
02470 
02471 /*! 
02472  * \brief Add new feature group
02473  * \param fgname feature group name.
02474  *
02475  * Add new feature group to the feature group list insert at head of list.
02476  * \note This function MUST be called while feature_groups is locked.
02477 */
02478 static struct feature_group *register_group(const char *fgname)
02479 {
02480    struct feature_group *fg;
02481 
02482    if (!fgname) {
02483       ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
02484       return NULL;
02485    }
02486 
02487    if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
02488       return NULL;
02489    }
02490 
02491    ast_string_field_set(fg, gname, fgname);
02492 
02493    AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
02494 
02495    ast_verb(2, "Registered group '%s'\n", fg->gname);
02496 
02497    return fg;
02498 }
02499 
02500 /*! 
02501  * \brief Add feature to group
02502  * \param fg feature group
02503  * \param exten
02504  * \param feature feature to add.
02505  *
02506  * Check fg and feature specified, add feature to list
02507  * \note This function MUST be called while feature_groups is locked. 
02508 */
02509 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
02510 {
02511    struct feature_group_exten *fge;
02512 
02513    if (!fg) {
02514       ast_log(LOG_NOTICE, "You didn't pass a group!\n");
02515       return;
02516    }
02517 
02518    if (!feature) {
02519       ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
02520       return;
02521    }
02522 
02523    if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
02524       return;
02525    }
02526 
02527    ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
02528 
02529    fge->feature = feature;
02530 
02531    AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
02532 
02533    ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
02534                feature->sname, fg->gname, fge->exten);
02535 }
02536 
02537 void ast_unregister_feature(struct ast_call_feature *feature)
02538 {
02539    if (!feature) {
02540       return;
02541    }
02542 
02543    AST_RWLIST_WRLOCK(&feature_list);
02544    AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
02545    AST_RWLIST_UNLOCK(&feature_list);
02546 
02547    ast_free(feature);
02548 }
02549 
02550 /*! \brief Remove all features in the list */
02551 static void ast_unregister_features(void)
02552 {
02553    struct ast_call_feature *feature;
02554 
02555    AST_RWLIST_WRLOCK(&feature_list);
02556    while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
02557       ast_free(feature);
02558    }
02559    AST_RWLIST_UNLOCK(&feature_list);
02560 }
02561 
02562 /*! \brief find a call feature by name */
02563 static struct ast_call_feature *find_dynamic_feature(const char *name)
02564 {
02565    struct ast_call_feature *tmp;
02566 
02567    AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
02568       if (!strcasecmp(tmp->sname, name)) {
02569          break;
02570       }
02571    }
02572 
02573    return tmp;
02574 }
02575 
02576 /*! \brief Remove all feature groups in the list */
02577 static void ast_unregister_groups(void)
02578 {
02579    struct feature_group *fg;
02580    struct feature_group_exten *fge;
02581 
02582    AST_RWLIST_WRLOCK(&feature_groups);
02583    while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
02584       while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
02585          ast_string_field_free_memory(fge);
02586          ast_free(fge);
02587       }
02588 
02589       ast_string_field_free_memory(fg);
02590       ast_free(fg);
02591    }
02592    AST_RWLIST_UNLOCK(&feature_groups);
02593 }
02594 
02595 /*! 
02596  * \brief Find a group by name 
02597  * \param name feature name
02598  * \retval feature group on success.
02599  * \retval NULL on failure.
02600 */
02601 static struct feature_group *find_group(const char *name)
02602 {
02603    struct feature_group *fg = NULL;
02604 
02605    AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
02606       if (!strcasecmp(fg->gname, name))
02607          break;
02608    }
02609 
02610    return fg;
02611 }
02612 
02613 void ast_rdlock_call_features(void)
02614 {
02615    ast_rwlock_rdlock(&features_lock);
02616 }
02617 
02618 void ast_unlock_call_features(void)
02619 {
02620    ast_rwlock_unlock(&features_lock);
02621 }
02622 
02623 struct ast_call_feature *ast_find_call_feature(const char *name)
02624 {
02625    int x;
02626    for (x = 0; x < FEATURES_COUNT; x++) {
02627       if (!strcasecmp(name, builtin_features[x].sname))
02628          return &builtin_features[x];
02629    }
02630    return NULL;
02631 }
02632 
02633 /*!
02634  * \brief exec an app by feature 
02635  * \param chan,peer,config,code,sense,data
02636  *
02637  * Find a feature, determine which channel activated
02638  * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
02639  * \retval -1 error.
02640  * \retval -2 when an application cannot be found.
02641 */
02642 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)
02643 {
02644    struct ast_app *app;
02645    struct ast_call_feature *feature = data;
02646    struct ast_channel *work, *idle;
02647    int res;
02648 
02649    if (!feature) { /* shouldn't ever happen! */
02650       ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
02651       return -1; 
02652    }
02653 
02654    if (sense == FEATURE_SENSE_CHAN) {
02655       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
02656          return AST_FEATURE_RETURN_KEEPTRYING;
02657       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
02658          work = chan;
02659          idle = peer;
02660       } else {
02661          work = peer;
02662          idle = chan;
02663       }
02664    } else {
02665       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
02666          return AST_FEATURE_RETURN_KEEPTRYING;
02667       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
02668          work = peer;
02669          idle = chan;
02670       } else {
02671          work = chan;
02672          idle = peer;
02673       }
02674    }
02675 
02676    if (!(app = pbx_findapp(feature->app))) {
02677       ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
02678       return -2;
02679    }
02680 
02681    ast_autoservice_start(idle);
02682    ast_autoservice_ignore(idle, AST_FRAME_DTMF_END);
02683    
02684    if(work && idle) {
02685       pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", idle->name);
02686       pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", work->name);
02687       pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
02688       pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
02689    }
02690 
02691    if (!ast_strlen_zero(feature->moh_class))
02692       ast_moh_start(idle, feature->moh_class, NULL);
02693 
02694    res = pbx_exec(work, app, feature->app_args);
02695 
02696    if (!ast_strlen_zero(feature->moh_class))
02697       ast_moh_stop(idle);
02698 
02699    ast_autoservice_stop(idle);
02700 
02701    if (res) {
02702       return AST_FEATURE_RETURN_SUCCESSBREAK;
02703    }
02704    return AST_FEATURE_RETURN_SUCCESS;  /*! \todo XXX should probably return res */
02705 }
02706 
02707 static void unmap_features(void)
02708 {
02709    int x;
02710 
02711    ast_rwlock_wrlock(&features_lock);
02712    for (x = 0; x < FEATURES_COUNT; x++)
02713       strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
02714    ast_rwlock_unlock(&features_lock);
02715 }
02716 
02717 static int remap_feature(const char *name, const char *value)
02718 {
02719    int x, res = -1;
02720 
02721    ast_rwlock_wrlock(&features_lock);
02722    for (x = 0; x < FEATURES_COUNT; x++) {
02723       if (strcasecmp(builtin_features[x].sname, name))
02724          continue;
02725 
02726       ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
02727       res = 0;
02728       break;
02729    }
02730    ast_rwlock_unlock(&features_lock);
02731 
02732    return res;
02733 }
02734 
02735 /*!
02736  * \brief Helper function for feature_interpret and ast_feature_detect
02737  * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
02738  *
02739  * Lock features list, browse for code, unlock list
02740  * If a feature is found and the operation variable is set, that feature's
02741  * operation is executed.  The first feature found is copied to the feature parameter.
02742  * \retval res on success.
02743  * \retval -1 on failure.
02744 */
02745 static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
02746    struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
02747    struct ast_flags *features, int operation, struct ast_call_feature *feature)
02748 {
02749    int x;
02750    struct feature_group *fg = NULL;
02751    struct feature_group_exten *fge;
02752    struct ast_call_feature *tmpfeature;
02753    char *tmp, *tok;
02754    int res = AST_FEATURE_RETURN_PASSDIGITS;
02755    int feature_detected = 0;
02756 
02757    if (!(peer && chan && config) && operation) {
02758       return -1; /* can not run feature operation */
02759    }
02760 
02761    ast_rwlock_rdlock(&features_lock);
02762    for (x = 0; x < FEATURES_COUNT; x++) {
02763       if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
02764           !ast_strlen_zero(builtin_features[x].exten)) {
02765          /* Feature is up for consideration */
02766          if (!strcmp(builtin_features[x].exten, code)) {
02767             ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
02768             if (operation) {
02769                res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
02770             }
02771             memcpy(feature, &builtin_features[x], sizeof(feature));
02772             feature_detected = 1;
02773             break;
02774          } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
02775             if (res == AST_FEATURE_RETURN_PASSDIGITS)
02776                res = AST_FEATURE_RETURN_STOREDIGITS;
02777          }
02778       }
02779    }
02780    ast_rwlock_unlock(&features_lock);
02781 
02782    if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
02783       return res;
02784    }
02785 
02786    tmp = dynamic_features_buf;
02787 
02788    while ((tok = strsep(&tmp, "#"))) {
02789       AST_RWLIST_RDLOCK(&feature_groups);
02790 
02791       fg = find_group(tok);
02792 
02793       if (fg) {
02794          AST_LIST_TRAVERSE(&fg->features, fge, entry) {
02795             if (!strcmp(fge->exten, code)) {
02796                if (operation) {
02797                   res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
02798                }
02799                memcpy(feature, fge->feature, sizeof(feature));
02800                if (res != AST_FEATURE_RETURN_KEEPTRYING) {
02801                   AST_RWLIST_UNLOCK(&feature_groups);
02802                   break;
02803                }
02804                res = AST_FEATURE_RETURN_PASSDIGITS;
02805             } else if (!strncmp(fge->exten, code, strlen(code))) {
02806                res = AST_FEATURE_RETURN_STOREDIGITS;
02807             }
02808          }
02809          if (fge) {
02810             break;
02811          }
02812       }
02813 
02814       AST_RWLIST_UNLOCK(&feature_groups);
02815 
02816       AST_RWLIST_RDLOCK(&feature_list);
02817 
02818       if (!(tmpfeature = find_dynamic_feature(tok))) {
02819          AST_RWLIST_UNLOCK(&feature_list);
02820          continue;
02821       }
02822 
02823       /* Feature is up for consideration */
02824       if (!strcmp(tmpfeature->exten, code)) {
02825          ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
02826          if (operation) {
02827             res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
02828          }
02829          memcpy(feature, tmpfeature, sizeof(feature));
02830          if (res != AST_FEATURE_RETURN_KEEPTRYING) {
02831             AST_RWLIST_UNLOCK(&feature_list);
02832             break;
02833          }
02834          res = AST_FEATURE_RETURN_PASSDIGITS;
02835       } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
02836          res = AST_FEATURE_RETURN_STOREDIGITS;
02837 
02838       AST_RWLIST_UNLOCK(&feature_list);
02839    }
02840 
02841    return res;
02842 }
02843 
02844 /*!
02845  * \brief Check the dynamic features
02846  * \param chan,peer,config,code,sense
02847  *
02848  * \retval res on success.
02849  * \retval -1 on failure.
02850 */
02851 
02852 static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense) {
02853 
02854    char dynamic_features_buf[128];
02855    const char *peer_dynamic_features, *chan_dynamic_features;
02856    struct ast_flags features;
02857    struct ast_call_feature feature;
02858    if (sense == FEATURE_SENSE_CHAN) {
02859       ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
02860    }
02861    else {
02862       ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
02863    }
02864 
02865    ast_channel_lock(peer);
02866    peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
02867    ast_channel_unlock(peer);
02868 
02869    ast_channel_lock(chan);
02870    chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
02871    ast_channel_unlock(chan);
02872 
02873    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,""));
02874 
02875    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);
02876 
02877    return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, 1, &feature);
02878 }
02879 
02880 
02881 int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
02882 
02883    return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature);
02884 }
02885 
02886 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
02887 {
02888    int x;
02889 
02890    ast_clear_flag(config, AST_FLAGS_ALL);
02891 
02892    ast_rwlock_rdlock(&features_lock);
02893    for (x = 0; x < FEATURES_COUNT; x++) {
02894       if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
02895          continue;
02896 
02897       if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
02898          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
02899 
02900       if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
02901          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
02902    }
02903    ast_rwlock_unlock(&features_lock);
02904 
02905    if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
02906       const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
02907 
02908       if (dynamic_features) {
02909          char *tmp = ast_strdupa(dynamic_features);
02910          char *tok;
02911          struct ast_call_feature *feature;
02912 
02913          /* while we have a feature */
02914          while ((tok = strsep(&tmp, "#"))) {
02915             struct feature_group *fg;
02916 
02917             AST_RWLIST_RDLOCK(&feature_groups);
02918             AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
02919                struct feature_group_exten *fge;
02920 
02921                AST_LIST_TRAVERSE(&fg->features, fge, entry) {
02922                   if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLER)) {
02923                      ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
02924                   }
02925                   if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLEE)) {
02926                      ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
02927                   }
02928                }
02929             }
02930             AST_RWLIST_UNLOCK(&feature_groups);
02931 
02932             AST_RWLIST_RDLOCK(&feature_list);
02933             if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
02934                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
02935                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
02936                }
02937                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE)) {
02938                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
02939                }
02940             }
02941             AST_RWLIST_UNLOCK(&feature_list);
02942          }
02943       }
02944    }
02945 }
02946 
02947 /*!
02948  * \internal
02949  * \brief Get feature and dial.
02950  *
02951  * \param caller Channel to represent as the calling channel for the dialed channel.
02952  * \param caller_name Original caller channel name.
02953  * \param requestor Channel to say is requesting the dial (usually the caller).
02954  * \param transferee Channel that the dialed channel will be transferred to.
02955  * \param type Channel technology type to dial.
02956  * \param format Codec formats for dialed channel.
02957  * \param data Dialed channel extra parameters for ast_request() and ast_call().
02958  * \param timeout Time limit for dialed channel to answer in ms. Must be greater than zero.
02959  * \param outstate Status of dialed channel if unsuccessful.
02960  * \param language Language of the caller.
02961  *
02962  * \note
02963  * outstate can be:
02964  * 0, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION,
02965  * AST_CONTROL_ANSWER, or AST_CONTROL_UNHOLD.  If
02966  * AST_CONTROL_UNHOLD then the caller channel cancelled the
02967  * transfer or the dialed channel did not answer before the
02968  * timeout.
02969  *
02970  * \details
02971  * Request channel, set channel variables, initiate call,
02972  * check if they want to disconnect, go into loop, check if timeout has elapsed,
02973  * check if person to be transfered hung up, check for answer break loop,
02974  * set cdr return channel.
02975  *
02976  * \retval Channel Connected channel for transfer.
02977  * \retval NULL on failure to get third party connected.
02978  *
02979  * \note This is similar to __ast_request_and_dial() in channel.c
02980  */
02981 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
02982    const char *caller_name, struct ast_channel *requestor,
02983    struct ast_channel *transferee, const char *type, format_t format, void *data,
02984    int timeout, int *outstate, const char *language)
02985 {
02986    int state = 0;
02987    int cause = 0;
02988    int to;
02989    int caller_hungup;
02990    int transferee_hungup;
02991    struct ast_channel *chan;
02992    struct ast_channel *monitor_chans[3];
02993    struct ast_channel *active_channel;
02994    int res;
02995    int ready = 0;
02996    struct timeval started;
02997    int x, len = 0;
02998    char *disconnect_code = NULL, *dialed_code = NULL;
02999    struct ast_frame *f;
03000    AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
03001 
03002    caller_hungup = ast_check_hangup(caller);
03003 
03004    if (!(chan = ast_request(type, format, requestor, data, &cause))) {
03005       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
03006       switch (cause) {
03007       case AST_CAUSE_BUSY:
03008          state = AST_CONTROL_BUSY;
03009          break;
03010       case AST_CAUSE_CONGESTION:
03011          state = AST_CONTROL_CONGESTION;
03012          break;
03013       default:
03014          state = 0;
03015          break;
03016       }
03017       goto done;
03018    }
03019 
03020    ast_string_field_set(chan, language, language);
03021    ast_channel_inherit_variables(caller, chan);
03022    pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
03023 
03024    ast_channel_lock(chan);
03025    ast_connected_line_copy_from_caller(&chan->connected, &requestor->caller);
03026    ast_channel_unlock(chan);
03027 
03028    if (ast_call(chan, data, timeout)) {
03029       ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
03030       switch (chan->hangupcause) {
03031       case AST_CAUSE_BUSY:
03032          state = AST_CONTROL_BUSY;
03033          break;
03034       case AST_CAUSE_CONGESTION:
03035          state = AST_CONTROL_CONGESTION;
03036          break;
03037       default:
03038          state = 0;
03039          break;
03040       }
03041       goto done;
03042    }
03043 
03044    /* support dialing of the featuremap disconnect code while performing an attended tranfer */
03045    ast_rwlock_rdlock(&features_lock);
03046    for (x = 0; x < FEATURES_COUNT; x++) {
03047       if (strcasecmp(builtin_features[x].sname, "disconnect"))
03048          continue;
03049 
03050       disconnect_code = builtin_features[x].exten;
03051       len = strlen(disconnect_code) + 1;
03052       dialed_code = alloca(len);
03053       memset(dialed_code, 0, len);
03054       break;
03055    }
03056    ast_rwlock_unlock(&features_lock);
03057    x = 0;
03058    started = ast_tvnow();
03059    to = timeout;
03060    AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
03061 
03062    ast_poll_channel_add(caller, chan);
03063 
03064    transferee_hungup = 0;
03065    while (!ast_check_hangup(transferee) && (chan->_state != AST_STATE_UP)) {
03066       int num_chans = 0;
03067 
03068       monitor_chans[num_chans++] = transferee;
03069       monitor_chans[num_chans++] = chan;
03070       if (!caller_hungup) {
03071          if (ast_check_hangup(caller)) {
03072             caller_hungup = 1;
03073 
03074 #if defined(ATXFER_NULL_TECH)
03075             /* Change caller's name to ensure that it will remain unique. */
03076             set_new_chan_name(caller);
03077 
03078             /*
03079              * Get rid of caller's physical technology so it is free for
03080              * other calls.
03081              */
03082             set_null_chan_tech(caller);
03083 #endif   /* defined(ATXFER_NULL_TECH) */
03084          } else {
03085             /* caller is not hungup so monitor it. */
03086             monitor_chans[num_chans++] = caller;
03087          }
03088       }
03089 
03090       /* see if the timeout has been violated */
03091       if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
03092          state = AST_CONTROL_UNHOLD;
03093          ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", chan->name);
03094          break; /*doh! timeout*/
03095       }
03096 
03097       active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
03098       if (!active_channel)
03099          continue;
03100 
03101       f = NULL;
03102       if (transferee == active_channel) {
03103          struct ast_frame *dup_f;
03104 
03105          f = ast_read(transferee);
03106          if (f == NULL) { /*doh! where'd he go?*/
03107             transferee_hungup = 1;
03108             state = 0;
03109             break;
03110          }
03111          if (ast_is_deferrable_frame(f)) {
03112             dup_f = ast_frisolate(f);
03113             if (dup_f) {
03114                if (dup_f == f) {
03115                   f = NULL;
03116                }
03117                AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
03118             }
03119          }
03120       } else if (chan == active_channel) {
03121          if (!ast_strlen_zero(chan->call_forward)) {
03122             state = 0;
03123             chan = ast_call_forward(caller, chan, NULL, format, NULL, &state);
03124             if (!chan) {
03125                break;
03126             }
03127             continue;
03128          }
03129          f = ast_read(chan);
03130          if (f == NULL) { /*doh! where'd he go?*/
03131             switch (chan->hangupcause) {
03132             case AST_CAUSE_BUSY:
03133                state = AST_CONTROL_BUSY;
03134                break;
03135             case AST_CAUSE_CONGESTION:
03136                state = AST_CONTROL_CONGESTION;
03137                break;
03138             default:
03139                state = 0;
03140                break;
03141             }
03142             break;
03143          }
03144 
03145          if (f->frametype == AST_FRAME_CONTROL) {
03146             if (f->subclass.integer == AST_CONTROL_RINGING) {
03147                ast_verb(3, "%s is ringing\n", chan->name);
03148                ast_indicate(caller, AST_CONTROL_RINGING);
03149             } else if (f->subclass.integer == AST_CONTROL_BUSY) {
03150                state = f->subclass.integer;
03151                ast_verb(3, "%s is busy\n", chan->name);
03152                ast_indicate(caller, AST_CONTROL_BUSY);
03153                ast_frfree(f);
03154                break;
03155             } else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
03156                state = f->subclass.integer;
03157                ast_verb(3, "%s is congested\n", chan->name);
03158                ast_indicate(caller, AST_CONTROL_CONGESTION);
03159                ast_frfree(f);
03160                break;
03161             } else if (f->subclass.integer == AST_CONTROL_ANSWER) {
03162                /* This is what we are hoping for */
03163                state = f->subclass.integer;
03164                ast_frfree(f);
03165                ready=1;
03166                break;
03167             } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
03168                if (caller_hungup) {
03169                   struct ast_party_connected_line connected;
03170 
03171                   /* Just save it for the transfer. */
03172                   ast_party_connected_line_set_init(&connected, &caller->connected);
03173                   res = ast_connected_line_parse_data(f->data.ptr, f->datalen,
03174                      &connected);
03175                   if (!res) {
03176                      ast_channel_set_connected_line(caller, &connected, NULL);
03177                   }
03178                   ast_party_connected_line_free(&connected);
03179                } else {
03180                   ast_autoservice_start(transferee);
03181                   if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
03182                      ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE,
03183                         f->data.ptr, f->datalen);
03184                   }
03185                   ast_autoservice_stop(transferee);
03186                }
03187             } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
03188                if (!caller_hungup) {
03189                   ast_autoservice_start(transferee);
03190                   if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
03191                      ast_indicate_data(caller, AST_CONTROL_REDIRECTING,
03192                         f->data.ptr, f->datalen);
03193                   }
03194                   ast_autoservice_stop(transferee);
03195                }
03196             } else if (f->subclass.integer != -1 && f->subclass.integer != AST_CONTROL_PROGRESS) {
03197                ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
03198             }
03199             /* else who cares */
03200          } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
03201             ast_write(caller, f);
03202          }
03203       } else if (caller == active_channel) {
03204          f = ast_read(caller);
03205          if (f) {
03206             if (f->frametype == AST_FRAME_DTMF) {
03207                dialed_code[x++] = f->subclass.integer;
03208                dialed_code[x] = '\0';
03209                if (strlen(dialed_code) == len) {
03210                   x = 0;
03211                } else if (x && strncmp(dialed_code, disconnect_code, x)) {
03212                   x = 0;
03213                   dialed_code[x] = '\0';
03214                }
03215                if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
03216                   /* Caller Canceled the call */
03217                   state = AST_CONTROL_UNHOLD;
03218                   ast_frfree(f);
03219                   break;
03220                }
03221             } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
03222                ast_write(chan, f);
03223             }
03224          }
03225       }
03226       if (f)
03227          ast_frfree(f);
03228    } /* end while */
03229 
03230    ast_poll_channel_del(caller, chan);
03231 
03232    /*
03233     * We need to free all the deferred frames, but we only need to
03234     * queue the deferred frames if no hangup was received.
03235     */
03236    ast_channel_lock(transferee);
03237    transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
03238    while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
03239       if (!transferee_hungup) {
03240          ast_queue_frame_head(transferee, f);
03241       }
03242       ast_frfree(f);
03243    }
03244    ast_channel_unlock(transferee);
03245 
03246 done:
03247    ast_indicate(caller, -1);
03248    if (chan && (ready || chan->_state == AST_STATE_UP)) {
03249       state = AST_CONTROL_ANSWER;
03250    } else if (chan) {
03251       ast_hangup(chan);
03252       chan = NULL;
03253    }
03254 
03255    if (outstate)
03256       *outstate = state;
03257 
03258    return chan;
03259 }
03260 
03261 void ast_channel_log(char *title, struct ast_channel *chan);
03262 
03263 void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */
03264 {
03265        ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long)chan);
03266        ast_log(LOG_NOTICE, "CHAN: name: %s;  appl: %s; data: %s; contxt: %s;  exten: %s; pri: %d;\n",
03267                        chan->name, chan->appl, chan->data, chan->context, chan->exten, chan->priority);
03268        ast_log(LOG_NOTICE, "CHAN: acctcode: %s;  dialcontext: %s; amaflags: %x; maccontxt: %s;  macexten: %s; macpri: %d;\n",
03269                        chan->accountcode, chan->dialcontext, chan->amaflags, chan->macrocontext, chan->macroexten, chan->macropriority);
03270        ast_log(LOG_NOTICE, "CHAN: masq: %p;  masqr: %p; _bridge: %p; uniqueID: %s; linkedID:%s\n",
03271                        chan->masq, chan->masqr,
03272                        chan->_bridge, chan->uniqueid, chan->linkedid);
03273        if (chan->masqr)
03274                ast_log(LOG_NOTICE, "CHAN: masquerading as: %s;  cdr: %p;\n",
03275                                chan->masqr->name, chan->masqr->cdr);
03276        if (chan->_bridge)
03277                ast_log(LOG_NOTICE, "CHAN: Bridged to %s\n", chan->_bridge->name);
03278 
03279    ast_log(LOG_NOTICE, "===== done ====\n");
03280 }
03281 
03282 /*!
03283  * \brief return the first unlocked cdr in a possible chain
03284 */
03285 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
03286 {
03287    struct ast_cdr *cdr_orig = cdr;
03288    while (cdr) {
03289       if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
03290          return cdr;
03291       cdr = cdr->next;
03292    }
03293    return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
03294 }
03295 
03296 static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
03297 {
03298    const char *feature;
03299 
03300    if (ast_strlen_zero(features)) {
03301       return;
03302    }
03303 
03304    for (feature = features; *feature; feature++) {
03305       switch (*feature) {
03306       case 'T' :
03307       case 't' :
03308          ast_set_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
03309          break;
03310       case 'K' :
03311       case 'k' :
03312          ast_set_flag(&(config->features_caller), AST_FEATURE_PARKCALL);
03313          break;
03314       case 'H' :
03315       case 'h' :
03316          ast_set_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
03317          break;
03318       case 'W' :
03319       case 'w' :
03320          ast_set_flag(&(config->features_caller), AST_FEATURE_AUTOMON);
03321          break;
03322       default :
03323          ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
03324       }
03325    }
03326 }
03327 
03328 static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
03329 {
03330    struct ast_datastore *ds_callee_features = NULL, *ds_caller_features = NULL;
03331    struct ast_dial_features *callee_features = NULL, *caller_features = NULL;
03332 
03333    ast_channel_lock(caller);
03334    ds_caller_features = ast_channel_datastore_find(caller, &dial_features_info, NULL);
03335    ast_channel_unlock(caller);
03336    if (!ds_caller_features) {
03337       if (!(ds_caller_features = ast_datastore_alloc(&dial_features_info, NULL))) {
03338          ast_log(LOG_WARNING, "Unable to create channel datastore for caller features. Aborting!\n");
03339          return;
03340       }
03341       if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
03342          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
03343          ast_datastore_free(ds_caller_features);
03344          return;
03345       }
03346       ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
03347       caller_features->is_caller = 1;
03348       ast_copy_flags(&(caller_features->features_callee), &(config->features_callee), AST_FLAGS_ALL);
03349       ast_copy_flags(&(caller_features->features_caller), &(config->features_caller), AST_FLAGS_ALL);
03350       ds_caller_features->data = caller_features;
03351       ast_channel_lock(caller);
03352       ast_channel_datastore_add(caller, ds_caller_features);
03353       ast_channel_unlock(caller);
03354    } else {
03355       /* If we don't return here, then when we do a builtin_atxfer we will copy the disconnect
03356        * flags over from the atxfer to the caller */
03357       return;
03358    }
03359 
03360    ast_channel_lock(callee);
03361    ds_callee_features = ast_channel_datastore_find(callee, &dial_features_info, NULL);
03362    ast_channel_unlock(callee);
03363    if (!ds_callee_features) {
03364       if (!(ds_callee_features = ast_datastore_alloc(&dial_features_info, NULL))) {
03365          ast_log(LOG_WARNING, "Unable to create channel datastore for callee features. Aborting!\n");
03366          return;
03367       }
03368       if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
03369          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
03370          ast_datastore_free(ds_callee_features);
03371          return;
03372       }
03373       ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
03374       callee_features->is_caller = 0;
03375       ast_copy_flags(&(callee_features->features_callee), &(config->features_caller), AST_FLAGS_ALL);
03376       ast_copy_flags(&(callee_features->features_caller), &(config->features_callee), AST_FLAGS_ALL);
03377       ds_callee_features->data = callee_features;
03378       ast_channel_lock(callee);
03379       ast_channel_datastore_add(callee, ds_callee_features);
03380       ast_channel_unlock(callee);
03381    }
03382 
03383    return;
03384 }
03385 
03386 /*!
03387  * \brief bridge the call and set CDR
03388  * \param chan,peer,config
03389  * 
03390  * Set start time, check for two channels,check if monitor on
03391  * check for feature activation, create new CDR
03392  * \retval res on success.
03393  * \retval -1 on failure to bridge.
03394 */
03395 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
03396 {
03397    /* Copy voice back and forth between the two channels.  Give the peer
03398       the ability to transfer calls with '#<extension' syntax. */
03399    struct ast_frame *f;
03400    struct ast_channel *who;
03401    char chan_featurecode[FEATURE_MAX_LEN + 1]="";
03402    char peer_featurecode[FEATURE_MAX_LEN + 1]="";
03403    char orig_channame[AST_MAX_EXTENSION];
03404    char orig_peername[AST_MAX_EXTENSION];
03405    int res;
03406    int diff;
03407    int hasfeatures=0;
03408    int hadfeatures=0;
03409    int autoloopflag;
03410    int we_disabled_peer_cdr = 0;
03411    struct ast_option_header *aoh;
03412    struct ast_cdr *bridge_cdr = NULL;
03413    struct ast_cdr *orig_peer_cdr = NULL;
03414    struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */
03415    struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
03416    struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
03417    struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
03418 
03419    if (chan && peer) {
03420       pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
03421       pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
03422    } else if (chan) {
03423       pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
03424    }
03425 
03426    set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
03427    add_features_datastores(chan, peer, config);
03428 
03429    /* This is an interesting case.  One example is if a ringing channel gets redirected to
03430     * an extension that picks up a parked call.  This will make sure that the call taken
03431     * out of parking gets told that the channel it just got bridged to is still ringing. */
03432    if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
03433       ast_indicate(peer, AST_CONTROL_RINGING);
03434    }
03435 
03436    if (monitor_ok) {
03437       const char *monitor_exec;
03438       struct ast_channel *src = NULL;
03439       if (!monitor_app) {
03440          if (!(monitor_app = pbx_findapp("Monitor")))
03441             monitor_ok=0;
03442       }
03443       if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
03444          src = chan;
03445       else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
03446          src = peer;
03447       if (monitor_app && src) {
03448          char *tmp = ast_strdupa(monitor_exec);
03449          pbx_exec(src, monitor_app, tmp);
03450       }
03451    }
03452 
03453    set_config_flags(chan, peer, config);
03454 
03455    /* Answer if need be */
03456    if (chan->_state != AST_STATE_UP) {
03457       if (ast_raw_answer(chan, 1)) {
03458          return -1;
03459       }
03460    }
03461 
03462 #ifdef FOR_DEBUG
03463    /* show the two channels and cdrs involved in the bridge for debug & devel purposes */
03464    ast_channel_log("Pre-bridge CHAN Channel info", chan);
03465    ast_channel_log("Pre-bridge PEER Channel info", peer);
03466 #endif
03467    /* two channels are being marked as linked here */
03468    ast_channel_set_linkgroup(chan,peer);
03469 
03470    /* copy the userfield from the B-leg to A-leg if applicable */
03471    if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
03472       char tmp[256];
03473       if (!ast_strlen_zero(chan->cdr->userfield)) {
03474          snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
03475          ast_cdr_appenduserfield(chan, tmp);
03476       } else
03477          ast_cdr_setuserfield(chan, peer->cdr->userfield);
03478       /* Don't delete the CDR; just disable it. */
03479       ast_set_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED);
03480       we_disabled_peer_cdr = 1;
03481    }
03482    ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
03483    ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
03484    orig_peer_cdr = peer_cdr;
03485    
03486    if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
03487       
03488       if (chan_cdr) {
03489          ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
03490          ast_cdr_update(chan);
03491          bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr);
03492          /* rip any forked CDR's off of the chan_cdr and attach
03493           * them to the bridge_cdr instead */
03494          bridge_cdr->next = chan_cdr->next;
03495          chan_cdr->next = NULL;
03496          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
03497          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
03498          if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) {
03499             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
03500          }
03501          ast_cdr_setaccount(peer, chan->accountcode);
03502 
03503       } else {
03504          /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
03505          bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
03506          ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
03507          ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
03508          ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
03509          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
03510          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
03511          ast_cdr_setcid(bridge_cdr, chan);
03512          bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
03513          bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
03514          ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
03515          /* Destination information */
03516          ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
03517          ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
03518          if (peer_cdr) {
03519             bridge_cdr->start = peer_cdr->start;
03520             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
03521          } else {
03522             ast_cdr_start(bridge_cdr);
03523          }
03524       }
03525       ast_debug(4,"bridge answer set, chan answer set\n");
03526       /* peer_cdr->answer will be set when a macro runs on the peer;
03527          in that case, the bridge answer will be delayed while the
03528          macro plays on the peer channel. The peer answered the call
03529          before the macro started playing. To the phone system,
03530          this is billable time for the call, even tho the caller
03531          hears nothing but ringing while the macro does its thing. */
03532 
03533       /* Another case where the peer cdr's time will be set, is when
03534          A self-parks by pickup up phone and dialing 700, then B
03535          picks up A by dialing its parking slot; there may be more 
03536          practical paths that get the same result, tho... in which
03537          case you get the previous answer time from the Park... which
03538          is before the bridge's start time, so I added in the 
03539          tvcmp check to the if below */
03540 
03541       if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) {
03542          ast_cdr_setanswer(bridge_cdr, peer_cdr->answer);
03543          ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition);
03544          if (chan_cdr) {
03545             ast_cdr_setanswer(chan_cdr, peer_cdr->answer);
03546             ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition);
03547          }
03548       } else {
03549          ast_cdr_answer(bridge_cdr);
03550          if (chan_cdr) {
03551             ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
03552          }
03553       }
03554       if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
03555          if (chan_cdr) {
03556             ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
03557          }
03558          if (peer_cdr) {
03559             ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
03560          }
03561       }
03562       /* the DIALED flag may be set if a dialed channel is transfered
03563        * and then bridged to another channel.  In order for the
03564        * bridge CDR to be written, the DIALED flag must not be
03565        * present. */
03566       ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED);
03567    }
03568    ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, NULL);
03569    for (;;) {
03570       struct ast_channel *other; /* used later */
03571    
03572       res = ast_channel_bridge(chan, peer, config, &f, &who);
03573       
03574       /* When frame is not set, we are probably involved in a situation
03575          where we've timed out.
03576          When frame is set, we'll come this code twice; once for DTMF_BEGIN
03577          and also for DTMF_END. If we flow into the following 'if' for both, then 
03578          our wait times are cut in half, as both will subtract from the
03579          feature_timer. Not good!
03580       */
03581       if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
03582          /* Update feature timer for next pass */
03583          diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time);
03584          if (res == AST_BRIDGE_RETRY) {
03585             /* The feature fully timed out but has not been updated. Skip
03586              * the potential round error from the diff calculation and
03587              * explicitly set to expired. */
03588             config->feature_timer = -1;
03589          } else {
03590             config->feature_timer -= diff;
03591          }
03592 
03593          if (hasfeatures) {
03594             if (config->feature_timer <= 0) {
03595                /* Not *really* out of time, just out of time for
03596                   digits to come in for features. */
03597                ast_debug(1, "Timed out for feature!\n");
03598                if (!ast_strlen_zero(peer_featurecode)) {
03599                   ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
03600                   memset(peer_featurecode, 0, sizeof(peer_featurecode));
03601                }
03602                if (!ast_strlen_zero(chan_featurecode)) {
03603                   ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
03604                   memset(chan_featurecode, 0, sizeof(chan_featurecode));
03605                }
03606                if (f)
03607                   ast_frfree(f);
03608                hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
03609                if (!hasfeatures) {
03610                   /* No more digits expected - reset the timer */
03611                   config->feature_timer = 0;
03612                }
03613                hadfeatures = hasfeatures;
03614                /* Continue as we were */
03615                continue;
03616             } else if (!f) {
03617                /* The bridge returned without a frame and there is a feature in progress.
03618                 * However, we don't think the feature has quite yet timed out, so just
03619                 * go back into the bridge. */
03620                continue;
03621             }
03622          } else {
03623             if (config->feature_timer <=0) {
03624                /* We ran out of time */
03625                config->feature_timer = 0;
03626                who = chan;
03627                if (f)
03628                   ast_frfree(f);
03629                f = NULL;
03630                res = 0;
03631             }
03632          }
03633       }
03634       if (res < 0) {
03635          if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) {
03636             ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
03637          }
03638          goto before_you_go;
03639       }
03640       
03641       if (!f || (f->frametype == AST_FRAME_CONTROL &&
03642             (f->subclass.integer == AST_CONTROL_HANGUP || f->subclass.integer == AST_CONTROL_BUSY ||
03643                f->subclass.integer == AST_CONTROL_CONGESTION))) {
03644          res = -1;
03645          break;
03646       }
03647       /* many things should be sent to the 'other' channel */
03648       other = (who == chan) ? peer : chan;
03649       if (f->frametype == AST_FRAME_CONTROL) {
03650          switch (f->subclass.integer) {
03651          case AST_CONTROL_RINGING:
03652          case AST_CONTROL_FLASH:
03653          case -1:
03654             ast_indicate(other, f->subclass.integer);
03655             break;
03656          case AST_CONTROL_CONNECTED_LINE:
03657             if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
03658                break;
03659             }
03660             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
03661             break;
03662          case AST_CONTROL_REDIRECTING:
03663             if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
03664                break;
03665             }
03666             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
03667             break;
03668          case AST_CONTROL_AOC:
03669          case AST_CONTROL_HOLD:
03670          case AST_CONTROL_UNHOLD:
03671             ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
03672             break;
03673          case AST_CONTROL_OPTION:
03674             aoh = f->data.ptr;
03675             /* Forward option Requests, but only ones we know are safe
03676              * These are ONLY sent by chan_iax2 and I'm not convinced that
03677              * they are useful. I haven't deleted them entirely because I
03678              * just am not sure of the ramifications of removing them. */
03679             if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
03680                   switch (ntohs(aoh->option)) {
03681                case AST_OPTION_TONE_VERIFY:
03682                case AST_OPTION_TDD:
03683                case AST_OPTION_RELAXDTMF:
03684                case AST_OPTION_AUDIO_MODE:
03685                case AST_OPTION_DIGIT_DETECT:
03686                case AST_OPTION_FAX_DETECT:
03687                   ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 
03688                      f->datalen - sizeof(struct ast_option_header), 0);
03689                }
03690             }
03691             break;
03692          }
03693       } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
03694          /* eat it */
03695       } else if (f->frametype == AST_FRAME_DTMF) {
03696          char *featurecode;
03697          int sense;
03698 
03699          hadfeatures = hasfeatures;
03700          /* This cannot overrun because the longest feature is one shorter than our buffer */
03701          if (who == chan) {
03702             sense = FEATURE_SENSE_CHAN;
03703             featurecode = chan_featurecode;
03704          } else  {
03705             sense = FEATURE_SENSE_PEER;
03706             featurecode = peer_featurecode;
03707          }
03708          /*! append the event to featurecode. we rely on the string being zero-filled, and
03709           * not overflowing it. 
03710           * \todo XXX how do we guarantee the latter ?
03711           */
03712          featurecode[strlen(featurecode)] = f->subclass.integer;
03713          /* Get rid of the frame before we start doing "stuff" with the channels */
03714          ast_frfree(f);
03715          f = NULL;
03716          config->feature_timer = 0;
03717          res = feature_interpret(chan, peer, config, featurecode, sense);
03718          switch(res) {
03719          case AST_FEATURE_RETURN_PASSDIGITS:
03720             ast_dtmf_stream(other, who, featurecode, 0, 0);
03721             /* Fall through */
03722          case AST_FEATURE_RETURN_SUCCESS:
03723             memset(featurecode, 0, sizeof(chan_featurecode));
03724             break;
03725          }
03726          if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
03727             res = 0;
03728          } else {
03729             break;
03730          }
03731          hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
03732          if (hadfeatures && !hasfeatures) {
03733             /* Feature completed or timed out */
03734             config->feature_timer = 0;
03735          } else if (hasfeatures) {
03736             if (config->timelimit) {
03737                /* No warning next time - we are waiting for future */
03738                ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
03739             }
03740             config->feature_start_time = ast_tvnow();
03741             config->feature_timer = featuredigittimeout;
03742             ast_debug(1, "Set feature timer to %ld ms\n", config->feature_timer);
03743          }
03744       }
03745       if (f)
03746          ast_frfree(f);
03747 
03748    }
03749    ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, NULL);
03750    before_you_go:
03751 
03752    if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) {
03753       ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
03754       if (bridge_cdr) {
03755          ast_cdr_discard(bridge_cdr);
03756          /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */
03757       }
03758       return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */
03759    }
03760 
03761    if (config->end_bridge_callback) {
03762       config->end_bridge_callback(config->end_bridge_callback_data);
03763    }
03764 
03765    /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation 
03766     * if it were, then chan belongs to a different thread now, and might have been hung up long
03767      * ago.
03768     */
03769    if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN)
03770       && ast_exists_extension(chan, chan->context, "h", 1,
03771          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
03772       struct ast_cdr *swapper = NULL;
03773       char savelastapp[AST_MAX_EXTENSION];
03774       char savelastdata[AST_MAX_EXTENSION];
03775       char save_exten[AST_MAX_EXTENSION];
03776       int  save_prio;
03777       int  found = 0;   /* set if we find at least one match */
03778       int  spawn_error = 0;
03779       
03780       autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
03781       ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
03782       if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
03783          ast_cdr_end(bridge_cdr);
03784       }
03785       /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
03786          dialplan code operate on it */
03787       ast_channel_lock(chan);
03788       if (bridge_cdr) {
03789          swapper = chan->cdr;
03790          ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
03791          ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
03792          chan->cdr = bridge_cdr;
03793       }
03794       ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
03795       save_prio = chan->priority;
03796       ast_copy_string(chan->exten, "h", sizeof(chan->exten));
03797       chan->priority = 1;
03798       ast_channel_unlock(chan);
03799       while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten,
03800          chan->priority,
03801          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
03802          &found, 1)) == 0) {
03803          chan->priority++;
03804       }
03805       if (spawn_error
03806          && (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
03807             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
03808             || ast_check_hangup(chan))) {
03809          /* if the extension doesn't exist or a hangup occurred, this isn't really a spawn error */
03810          spawn_error = 0;
03811       }
03812       if (found && spawn_error) {
03813          /* Something bad happened, or a hangup has been requested. */
03814          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
03815          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
03816       }
03817       /* swap it back */
03818       ast_channel_lock(chan);
03819       ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
03820       chan->priority = save_prio;
03821       if (bridge_cdr) {
03822          if (chan->cdr == bridge_cdr) {
03823             chan->cdr = swapper;
03824          } else {
03825             bridge_cdr = NULL;
03826          }
03827       }
03828       if (!spawn_error) {
03829          ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
03830       }
03831       ast_channel_unlock(chan);
03832       /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
03833       if (bridge_cdr) {
03834          ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
03835          ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
03836       }
03837       ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
03838    }
03839    
03840    /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
03841    new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
03842    if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))
03843       ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
03844 
03845    /* we can post the bridge CDR at this point */
03846    if (bridge_cdr) {
03847       ast_cdr_end(bridge_cdr);
03848       ast_cdr_detach(bridge_cdr);
03849    }
03850    
03851    /* do a specialized reset on the beginning channel
03852       CDR's, if they still exist, so as not to mess up
03853       issues in future bridges;
03854       
03855       Here are the rules of the game:
03856       1. The chan and peer channel pointers will not change
03857          during the life of the bridge.
03858       2. But, in transfers, the channel names will change.
03859          between the time the bridge is started, and the
03860          time the channel ends. 
03861          Usually, when a channel changes names, it will
03862          also change CDR pointers.
03863       3. Usually, only one of the two channels (chan or peer)
03864          will change names.
03865       4. Usually, if a channel changes names during a bridge,
03866          it is because of a transfer. Usually, in these situations,
03867          it is normal to see 2 bridges running simultaneously, and
03868          it is not unusual to see the two channels that change
03869          swapped between bridges.
03870       5. After a bridge occurs, we have 2 or 3 channels' CDRs
03871          to attend to; if the chan or peer changed names,
03872          we have the before and after attached CDR's.
03873    */
03874 
03875    if (new_chan_cdr) {
03876       struct ast_channel *chan_ptr = NULL;
03877 
03878       if (strcasecmp(orig_channame, chan->name) != 0) { 
03879          /* old channel */
03880          if ((chan_ptr = ast_channel_get_by_name(orig_channame))) {
03881             ast_channel_lock(chan_ptr);
03882             if (!ast_bridged_channel(chan_ptr)) {
03883                struct ast_cdr *cur;
03884                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
03885                   if (cur == chan_cdr) {
03886                      break;
03887                   }
03888                }
03889                if (cur) {
03890                   ast_cdr_specialized_reset(chan_cdr, 0);
03891                }
03892             }
03893             ast_channel_unlock(chan_ptr);
03894             chan_ptr = ast_channel_unref(chan_ptr);
03895          }
03896          /* new channel */
03897          ast_cdr_specialized_reset(new_chan_cdr, 0);
03898       } else {
03899          ast_cdr_specialized_reset(chan->cdr, 0); /* nothing changed, reset the chan cdr  */
03900       }
03901    }
03902 
03903    {
03904       struct ast_channel *chan_ptr = NULL;
03905       new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
03906       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))
03907          ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
03908       if (strcasecmp(orig_peername, peer->name) != 0) { 
03909          /* old channel */
03910          if ((chan_ptr = ast_channel_get_by_name(orig_peername))) {
03911             ast_channel_lock(chan_ptr);
03912             if (!ast_bridged_channel(chan_ptr)) {
03913                struct ast_cdr *cur;
03914                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
03915                   if (cur == peer_cdr) {
03916                      break;
03917                   }
03918                }
03919                if (cur) {
03920                   ast_cdr_specialized_reset(peer_cdr, 0);
03921                }
03922             }
03923             ast_channel_unlock(chan_ptr);
03924             chan_ptr = ast_channel_unref(chan_ptr);
03925          }
03926          /* new channel */
03927          if (new_peer_cdr) {
03928             ast_cdr_specialized_reset(new_peer_cdr, 0);
03929          }
03930       } else {
03931          if (we_disabled_peer_cdr) {
03932             ast_clear_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED);
03933          }
03934          ast_cdr_specialized_reset(peer->cdr, 0); /* nothing changed, reset the peer cdr  */
03935       }
03936    }
03937    
03938    return res;
03939 }
03940 
03941 /*! \brief Output parking event to manager */
03942 static void post_manager_event(const char *s, struct parkeduser *pu)
03943 {
03944    manager_event(EVENT_FLAG_CALL, s,
03945       "Exten: %s\r\n"
03946       "Channel: %s\r\n"
03947       "Parkinglot: %s\r\n"
03948       "CallerIDNum: %s\r\n"
03949       "CallerIDName: %s\r\n"
03950       "UniqueID: %s\r\n",
03951       pu->parkingexten, 
03952       pu->chan->name,
03953       pu->parkinglot->name,
03954       S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
03955       S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
03956       pu->chan->uniqueid
03957       );
03958 }
03959 
03960 static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
03961 {
03962    int i = 0;
03963    enum {
03964       OPT_CALLEE_REDIRECT   = 't',
03965       OPT_CALLER_REDIRECT   = 'T',
03966       OPT_CALLEE_AUTOMON    = 'w',
03967       OPT_CALLER_AUTOMON    = 'W',
03968       OPT_CALLEE_DISCONNECT = 'h',
03969       OPT_CALLER_DISCONNECT = 'H',
03970       OPT_CALLEE_PARKCALL   = 'k',
03971       OPT_CALLER_PARKCALL   = 'K',
03972    };
03973 
03974    memset(options, 0, len);
03975    if (ast_test_flag(features_caller, AST_FEATURE_REDIRECT) && i < len) {
03976       options[i++] = OPT_CALLER_REDIRECT;
03977    }
03978    if (ast_test_flag(features_caller, AST_FEATURE_AUTOMON) && i < len) {
03979       options[i++] = OPT_CALLER_AUTOMON;
03980    }
03981    if (ast_test_flag(features_caller, AST_FEATURE_DISCONNECT) && i < len) {
03982       options[i++] = OPT_CALLER_DISCONNECT;
03983    }
03984    if (ast_test_flag(features_caller, AST_FEATURE_PARKCALL) && i < len) {
03985       options[i++] = OPT_CALLER_PARKCALL;
03986    }
03987 
03988    if (ast_test_flag(features_callee, AST_FEATURE_REDIRECT) && i < len) {
03989       options[i++] = OPT_CALLEE_REDIRECT;
03990    }
03991    if (ast_test_flag(features_callee, AST_FEATURE_AUTOMON) && i < len) {
03992       options[i++] = OPT_CALLEE_AUTOMON;
03993    }
03994    if (ast_test_flag(features_callee, AST_FEATURE_DISCONNECT) && i < len) {
03995       options[i++] = OPT_CALLEE_DISCONNECT;
03996    }
03997    if (ast_test_flag(features_callee, AST_FEATURE_PARKCALL) && i < len) {
03998       options[i++] = OPT_CALLEE_PARKCALL;
03999    }
04000 
04001    return options;
04002 }
04003 
04004 /*! \brief Run management on parkinglots, called once per parkinglot */
04005 int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
04006 {
04007    struct parkeduser *pu;
04008    int res = 0;
04009    char parkingslot[AST_MAX_EXTENSION];
04010 
04011    /* Lock parking list */
04012    AST_LIST_LOCK(&curlot->parkings);
04013    AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
04014       struct ast_channel *chan = pu->chan;   /* shorthand */
04015       int tms;        /* timeout for this item */
04016       int x;          /* fd index in channel */
04017       struct ast_context *con;
04018 
04019       if (pu->notquiteyet) { /* Pretend this one isn't here yet */
04020          continue;
04021       }
04022       tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
04023       if (tms > pu->parkingtime) {
04024          /* Stop music on hold */
04025          ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
04026          /* Get chan, exten from derived kludge */
04027          if (pu->peername[0]) {
04028             char *peername = ast_strdupa(pu->peername);
04029             char *dash = strrchr(peername, '-');
04030             char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
04031             int i;
04032 
04033             if (dash) {
04034                *dash = '\0';
04035             }
04036 
04037             peername_flat = ast_strdupa(peername);
04038             for (i = 0; peername_flat[i]; i++) {
04039                if (peername_flat[i] == '/') {
04040                   peername_flat[i]= '_';
04041                }
04042             }
04043 
04044             con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
04045             if (!con) {
04046                ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
04047             } else {
04048                char returnexten[AST_MAX_EXTENSION];
04049                struct ast_datastore *features_datastore;
04050                struct ast_dial_features *dialfeatures = NULL;
04051 
04052                ast_channel_lock(chan);
04053 
04054                if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
04055                   dialfeatures = features_datastore->data;
04056 
04057                ast_channel_unlock(chan);
04058 
04059                if (!strncmp(peername, "Parked/", 7)) {
04060                   peername += 7;
04061                }
04062 
04063                if (dialfeatures) {
04064                   char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
04065                   snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername, callback_dialoptions(&(dialfeatures->features_callee), &(dialfeatures->features_caller), buf, sizeof(buf)));
04066                } else { /* Existing default */
04067                   ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n", chan->name);
04068                   snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
04069                }
04070 
04071                ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
04072             }
04073             if (pu->options_specified == 1) {
04074                /* Park() was called with overriding return arguments, respect those arguments */
04075                set_c_e_p(chan, pu->context, pu->exten, pu->priority);
04076             } else {
04077                if (comebacktoorigin) {
04078                   set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername_flat, 1);
04079                } else {
04080                   snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
04081                   pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
04082                   set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
04083                }
04084             }
04085          } else {
04086             /* They've been waiting too long, send them back to where they came.  Theoretically they
04087                should have their original extensions and such, but we copy to be on the safe side */
04088             set_c_e_p(chan, pu->context, pu->exten, pu->priority);
04089          }
04090          post_manager_event("ParkedCallTimeOut", pu);
04091          ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
04092 
04093          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);
04094          /* Start up the PBX, or hang them up */
04095          if (ast_pbx_start(chan))  {
04096             ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
04097             ast_hangup(chan);
04098          }
04099          /* And take them out of the parking lot */
04100          con = ast_context_find(pu->parkinglot->parking_con);
04101          if (con) {
04102             if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
04103                ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
04104             else
04105                notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
04106          } else
04107             ast_log(LOG_WARNING, "Whoa, no parking context?\n");
04108          AST_LIST_REMOVE_CURRENT(list);
04109          free(pu);
04110       } else { /* still within parking time, process descriptors */
04111          for (x = 0; x < AST_MAX_FDS; x++) {
04112             struct ast_frame *f;
04113             int y;
04114 
04115             if (chan->fds[x] == -1) {
04116                continue;   /* nothing on this descriptor */
04117             }
04118 
04119             for (y = 0; y < nfds; y++) {
04120                if (pfds[y].fd == chan->fds[x]) {
04121                   /* Found poll record! */
04122                   break;
04123                }
04124             }
04125             if (y == nfds) {
04126                /* Not found */
04127                continue;
04128             }
04129 
04130             if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
04131                /* Next x */
04132                continue;
04133             }
04134 
04135             if (pfds[y].revents & POLLPRI) {
04136                ast_set_flag(chan, AST_FLAG_EXCEPTION);
04137             } else {
04138                ast_clear_flag(chan, AST_FLAG_EXCEPTION);
04139             }
04140             chan->fdno = x;
04141 
04142             /* See if they need servicing */
04143             f = ast_read(pu->chan);
04144             /* Hangup? */
04145             if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer ==  AST_CONTROL_HANGUP))) {
04146                if (f)
04147                   ast_frfree(f);
04148                post_manager_event("ParkedCallGiveUp", pu);
04149                ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp", NULL);
04150 
04151                /* There's a problem, hang them up*/
04152                ast_verb(2, "%s got tired of being parked\n", chan->name);
04153                ast_hangup(chan);
04154                /* And take them out of the parking lot */
04155                con = ast_context_find(curlot->parking_con);
04156                if (con) {
04157                   if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
04158                      ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
04159                   else
04160                      notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
04161                } else
04162                   ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
04163                AST_LIST_REMOVE_CURRENT(list);
04164                parkinglot_unref(pu->parkinglot);
04165                free(pu);
04166                break;
04167             } else {
04168                /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
04169                ast_frfree(f);
04170                if (pu->moh_trys < 3 && !chan->generatordata) {
04171                   ast_debug(1, "MOH on parked call stopped by outside source.  Restarting on channel %s.\n", chan->name);
04172                   ast_indicate_data(chan, AST_CONTROL_HOLD, 
04173                      S_OR(curlot->mohclass, NULL),
04174                      (!ast_strlen_zero(curlot->mohclass) ? strlen(curlot->mohclass) + 1 : 0));
04175                   pu->moh_trys++;
04176                }
04177                goto std;   /* XXX Ick: jumping into an else statement??? XXX */
04178             }
04179          } /* End for */
04180          if (x >= AST_MAX_FDS) {
04181 std:        for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
04182                if (chan->fds[x] > -1) {
04183                   void *tmp = ast_realloc(*new_pfds, (*new_nfds + 1) * sizeof(struct pollfd));
04184                   if (!tmp) {
04185                      continue;
04186                   }
04187                   *new_pfds = tmp;
04188                   (*new_pfds)[*new_nfds].fd = chan->fds[x];
04189                   (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
04190                   (*new_pfds)[*new_nfds].revents = 0;
04191                   (*new_nfds)++;
04192                }
04193             }
04194             /* Keep track of our shortest wait */
04195             if (tms < *ms || *ms < 0) {
04196                *ms = tms;
04197             }
04198          }
04199       }
04200    }
04201    AST_LIST_TRAVERSE_SAFE_END;
04202    AST_LIST_UNLOCK(&curlot->parkings);
04203 
04204    return res;
04205 }
04206 
04207 /*! 
04208  * \brief Take care of parked calls and unpark them if needed 
04209  * \param ignore unused var.
04210  * 
04211  * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
04212  * if so, remove channel from parking lot and return it to the extension that parked it.
04213  * Check if parked channel decided to hangup, wait until next FD via select().
04214 */
04215 static void *do_parking_thread(void *ignore)
04216 {
04217    struct pollfd *pfds = NULL, *new_pfds = NULL;
04218    int nfds = 0, new_nfds = 0;
04219 
04220    for (;;) {
04221       struct ao2_iterator iter;
04222       struct ast_parkinglot *curlot;
04223       int ms = -1;   /* poll2 timeout, uninitialized */
04224       iter = ao2_iterator_init(parkinglots, 0);
04225 
04226       while ((curlot = ao2_iterator_next(&iter))) {
04227          manage_parkinglot(curlot, pfds, nfds, &new_pfds, &new_nfds, &ms);
04228          ao2_ref(curlot, -1);
04229       }
04230       ao2_iterator_destroy(&iter);
04231 
04232       /* Recycle */
04233       ast_free(pfds);
04234       pfds = new_pfds;
04235       nfds = new_nfds;
04236       new_pfds = NULL;
04237       new_nfds = 0;
04238 
04239       /* Wait for something to happen */
04240       ast_poll(pfds, nfds, ms);
04241       pthread_testcancel();
04242    }
04243    /* If this WERE reached, we'd need to free(pfds) */
04244    return NULL;   /* Never reached */
04245 }
04246 
04247 /*! \brief Find parkinglot by name */
04248 struct ast_parkinglot *find_parkinglot(const char *name)
04249 {
04250    struct ast_parkinglot *parkinglot;
04251 
04252    if (ast_strlen_zero(name)) {
04253       return NULL;
04254    }
04255 
04256    parkinglot = ao2_find(parkinglots, (void *) name, 0);
04257    if (parkinglot) {
04258       ast_debug(1, "Found Parkinglot: %s\n", parkinglot->name);
04259    }
04260 
04261    return parkinglot;
04262 }
04263 
04264 /*! \brief Copy parkinglot and store it with new name */
04265 struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot) {
04266    struct ast_parkinglot *copylot;
04267 
04268    if (ast_strlen_zero(name)) { /* No name specified */
04269       return NULL;
04270    }
04271    if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
04272       if (copylot) {
04273          ao2_ref(copylot, -1);
04274       }
04275       return NULL;
04276    }
04277 
04278    copylot = create_parkinglot(name);
04279    ast_debug(1, "Building parking lot %s\n", name);
04280 
04281    memcpy(copylot, parkinglot, sizeof(struct ast_parkinglot));
04282    ast_copy_string(copylot->name, name, sizeof(copylot->name));
04283    AST_LIST_HEAD_INIT(&copylot->parkings);
04284 
04285    return copylot;
04286 }
04287 
04288 AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
04289    AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
04290    AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
04291    AST_APP_OPTION('s', AST_PARK_OPT_SILENCE),
04292 END_OPTIONS );
04293 
04294 /*! \brief Park a call */
04295 static int park_call_exec(struct ast_channel *chan, const char *data)
04296 {
04297    /* Cache the original channel name in case we get masqueraded in the middle
04298     * of a park--it is still theoretically possible for a transfer to happen before
04299     * we get here, but it is _really_ unlikely */
04300    char *orig_chan_name = ast_strdupa(chan->name);
04301    char orig_exten[AST_MAX_EXTENSION];
04302    int orig_priority = chan->priority;
04303 
04304    /* Data is unused at the moment but could contain a parking
04305       lot context eventually */
04306    int res = 0;
04307 
04308    char *parse = NULL;
04309    AST_DECLARE_APP_ARGS(app_args,
04310       AST_APP_ARG(timeout);
04311       AST_APP_ARG(return_con);
04312       AST_APP_ARG(return_ext);
04313       AST_APP_ARG(return_pri);
04314       AST_APP_ARG(options);
04315    );
04316 
04317    parse = ast_strdupa(data);
04318    AST_STANDARD_APP_ARGS(app_args, parse);
04319 
04320    ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
04321 
04322    /* Setup the exten/priority to be s/1 since we don't know
04323       where this call should return */
04324    strcpy(chan->exten, "s");
04325    chan->priority = 1;
04326 
04327    /* Answer if call is not up */
04328    if (chan->_state != AST_STATE_UP)
04329       res = ast_answer(chan);
04330 
04331    /* Sleep to allow VoIP streams to settle down */
04332    if (!res)
04333       res = ast_safe_sleep(chan, 1000);
04334 
04335    /* Park the call */
04336    if (!res) {
04337       struct ast_park_call_args args = {
04338          .orig_chan_name = orig_chan_name,
04339       };
04340       struct ast_flags flags = { 0 };
04341 
04342       if (parse) {
04343          if (!ast_strlen_zero(app_args.timeout)) {
04344             if (sscanf(app_args.timeout, "%30d", &args.timeout) != 1) {
04345                ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
04346                args.timeout = 0;
04347             }
04348          }
04349          if (!ast_strlen_zero(app_args.return_con)) {
04350             args.return_con = app_args.return_con;
04351          }
04352          if (!ast_strlen_zero(app_args.return_ext)) {
04353             args.return_ext = app_args.return_ext;
04354          }
04355          if (!ast_strlen_zero(app_args.return_pri)) {
04356             if (sscanf(app_args.return_pri, "%30d", &args.return_pri) != 1) {
04357                ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
04358                args.return_pri = 0;
04359             }
04360          }
04361       }
04362 
04363       ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
04364       args.flags = flags.flags;
04365 
04366       args.parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &orig_exten);
04367       res = masq_park_call_announce(chan, chan, &args);
04368       /* Continue on in the dialplan */
04369       if (res == 1) {
04370          ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
04371          chan->priority = orig_priority;
04372          res = 0;
04373       } else if (!res) {
04374          res = 1;
04375       }
04376    }
04377 
04378    return res;
04379 }
04380 
04381 /*! \brief Pickup parked call */
04382 static int park_exec_full(struct ast_channel *chan, const char *data)
04383 {
04384    int res = 0;
04385    struct ast_channel *peer=NULL;
04386    struct parkeduser *pu;
04387    struct ast_context *con;
04388    int park = 0;
04389    struct ast_bridge_config config;
04390    struct ast_parkinglot *parkinglot;
04391 
04392    if (data) {
04393       park = atoi((char *) data);
04394    }
04395 
04396    parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_position_cb, (void *) &park);
04397    if (!parkinglot)
04398       parkinglot = default_parkinglot;
04399 
04400    AST_LIST_LOCK(&parkinglot->parkings);
04401    AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
04402       if (!pu->notquiteyet && (!data || pu->parkingnum == park)) {
04403          if (pu->chan->pbx) { /* do not allow call to be picked up until the PBX thread is finished */
04404             AST_LIST_UNLOCK(&parkinglot->parkings);
04405             return -1;
04406          }
04407          AST_LIST_REMOVE_CURRENT(list);
04408          break;
04409       }
04410    }
04411    AST_LIST_TRAVERSE_SAFE_END;
04412    AST_LIST_UNLOCK(&parkinglot->parkings);
04413 
04414    if (pu) {
04415       peer = pu->chan;
04416       con = ast_context_find(parkinglot->parking_con);
04417       if (con) {
04418          if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
04419             ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
04420          else
04421             notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
04422       } else
04423          ast_log(LOG_WARNING, "Whoa, no parking context?\n");
04424 
04425       ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "UnParkedCall", chan);
04426       ast_manager_event(pu->chan, EVENT_FLAG_CALL, "UnParkedCall",
04427          "Exten: %s\r\n"
04428          "Channel: %s\r\n"
04429          "From: %s\r\n"
04430          "CallerIDNum: %s\r\n"
04431          "CallerIDName: %s\r\n",
04432          pu->parkingexten, pu->chan->name, chan->name,
04433          S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
04434          S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>")
04435          );
04436 
04437       ast_free(pu);
04438    }
04439    /* JK02: it helps to answer the channel if not already up */
04440    if (chan->_state != AST_STATE_UP)
04441       ast_answer(chan);
04442 
04443    //XXX Why do we unlock here ?
04444    // uncomment it for now, till my setup with debug_threads and detect_deadlocks starts to complain
04445    //ASTOBJ_UNLOCK(parkinglot);
04446 
04447    if (peer) {
04448       struct ast_datastore *features_datastore;
04449       struct ast_dial_features *dialfeatures = NULL;
04450 
04451       /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
04452 
04453       if (!ast_strlen_zero(courtesytone)) {
04454          int error = 0;
04455          ast_indicate(peer, AST_CONTROL_UNHOLD);
04456          if (parkedplay == 0) {
04457             error = ast_stream_and_wait(chan, courtesytone, "");
04458          } else if (parkedplay == 1) {
04459             error = ast_stream_and_wait(peer, courtesytone, "");
04460          } else if (parkedplay == 2) {
04461             if (!ast_streamfile(chan, courtesytone, chan->language) &&
04462                   !ast_streamfile(peer, courtesytone, chan->language)) {
04463                /*! \todo XXX we would like to wait on both! */
04464                res = ast_waitstream(chan, "");
04465                if (res >= 0)
04466                   res = ast_waitstream(peer, "");
04467                if (res < 0)
04468                   error = 1;
04469             }
04470          }
04471          if (error) {
04472             ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
04473             ast_hangup(peer);
04474             return -1;
04475          }
04476       } else
04477          ast_indicate(peer, AST_CONTROL_UNHOLD);
04478 
04479       res = ast_channel_make_compatible(chan, peer);
04480       if (res < 0) {
04481          ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
04482          ast_hangup(peer);
04483          return -1;
04484       }
04485       /* This runs sorta backwards, since we give the incoming channel control, as if it
04486          were the person called. */
04487       ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
04488 
04489       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
04490       ast_cdr_setdestchan(chan->cdr, peer->name);
04491       memset(&config, 0, sizeof(struct ast_bridge_config));
04492 
04493       /* Get datastore for peer and apply it's features to the callee side of the bridge config */
04494       ast_channel_lock(peer);
04495       if ((features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL))) {
04496          dialfeatures = features_datastore->data;
04497       }
04498       ast_channel_unlock(peer);
04499 
04500       /* When the datastores for both caller and callee are created, both the callee and caller channels
04501        * use the features_caller flag variable to represent themselves. With that said, the config.features_callee
04502        * flags should be copied from the datastore's caller feature flags regardless if peer was a callee
04503        * or caller. */
04504       if (dialfeatures) {
04505          ast_copy_flags(&(config.features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
04506       }
04507 
04508       if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
04509          ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
04510       }
04511       if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
04512          ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
04513       }
04514       if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
04515          ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
04516       }
04517       if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
04518          ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
04519       }
04520       if ((parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
04521          ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
04522       }
04523       if ((parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
04524          ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
04525       }
04526       if ((parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
04527          ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
04528       }
04529       if ((parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
04530          ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
04531       }
04532 
04533       parkinglot_unref(parkinglot);
04534       res = ast_bridge_call(chan, peer, &config);
04535 
04536       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
04537       ast_cdr_setdestchan(chan->cdr, peer->name);
04538 
04539       /* Simulate the PBX hanging up */
04540       ast_hangup(peer);
04541       return -1;
04542    } else {
04543       /*! \todo XXX Play a message XXX */
04544       if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
04545          ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
04546       ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
04547       res = -1;
04548    }
04549 
04550    return -1;
04551 }
04552 
04553 static int park_exec(struct ast_channel *chan, const char *data) 
04554 {
04555    return park_exec_full(chan, data);
04556 }
04557 
04558 /*! \brief Unreference parkinglot object. If no more references,
04559    then go ahead and delete it */
04560 static void parkinglot_unref(struct ast_parkinglot *parkinglot) 
04561 {
04562    int refcount = ao2_ref(parkinglot, -1);
04563    ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount - 1);
04564 }
04565 
04566 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
04567 {
04568    int refcount = ao2_ref(parkinglot, +1);
04569    ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
04570    return parkinglot;
04571 }
04572 
04573 /*! \brief Allocate parking lot structure */
04574 static struct ast_parkinglot *create_parkinglot(const char *name)
04575 {
04576    struct ast_parkinglot *newlot = (struct ast_parkinglot *) NULL;
04577 
04578    if (!name)
04579       return NULL;
04580 
04581    newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);
04582    if (!newlot)
04583       return NULL;
04584    
04585    ast_copy_string(newlot->name, name, sizeof(newlot->name));
04586    AST_LIST_HEAD_INIT(&newlot->parkings);
04587 
04588    return newlot;
04589 }
04590 
04591 /*! \brief Destroy a parking lot */
04592 static void parkinglot_destroy(void *obj)
04593 {
04594    struct ast_parkinglot *ruin = obj;
04595    struct ast_context *con;
04596    con = ast_context_find(ruin->parking_con);
04597    if (con)
04598       ast_context_destroy(con, registrar);
04599 }
04600 
04601 /*! 
04602  * \brief Add parking hints for all defined parking lots 
04603  * \param context
04604  * \param start starting parkinglot number
04605  * \param stop ending parkinglot number
04606 */
04607 static void park_add_hints(char *context, int start, int stop)
04608 {
04609    int numext;
04610    char device[AST_MAX_EXTENSION];
04611    char exten[10];
04612 
04613    for (numext = start; numext <= stop; numext++) {
04614       snprintf(exten, sizeof(exten), "%d", numext);
04615       snprintf(device, sizeof(device), "park:%s@%s", exten, context);
04616       ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
04617    }
04618 }
04619 
04620 /*! \brief Build parkinglot from configuration and chain it in if it doesn't already exist */
04621 static struct ast_parkinglot *build_parkinglot(char *name, struct ast_variable *var)
04622 {
04623    struct ast_parkinglot *parkinglot;
04624    struct ast_context *con = NULL;
04625 
04626    struct ast_variable *confvar = var;
04627    int error = 0;
04628    int start = 0, end = 0;
04629    int oldparkinglot = 0;
04630 
04631    parkinglot = find_parkinglot(name);
04632    if (parkinglot)
04633       oldparkinglot = 1;
04634    else
04635       parkinglot = create_parkinglot(name);
04636 
04637    if (!parkinglot)
04638       return NULL;
04639 
04640    ao2_lock(parkinglot);
04641 
04642    ast_debug(1, "Building parking lot %s\n", name);
04643 
04644    /* Do some config stuff */
04645    while(confvar) {
04646       if (!strcasecmp(confvar->name, "context")) {
04647          ast_copy_string(parkinglot->parking_con, confvar->value, sizeof(parkinglot->parking_con));
04648       } else if (!strcasecmp(confvar->name, "parkext")) {
04649          ast_copy_string(parkinglot->parkext, confvar->value, sizeof(parkinglot->parkext));
04650       } else if (!strcasecmp(confvar->name, "parkingtime")) {
04651          if ((sscanf(confvar->value, "%30d", &parkinglot->parkingtime) != 1) || (parkinglot->parkingtime < 1)) {
04652             ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", confvar->value);
04653             parkinglot->parkingtime = DEFAULT_PARK_TIME;
04654          } else
04655             parkinglot->parkingtime = parkinglot->parkingtime * 1000;
04656       } else if (!strcasecmp(confvar->name, "parkpos")) {
04657          if (sscanf(confvar->value, "%30d-%30d", &start, &end) != 2) {
04658             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);
04659             error = 1;
04660          } else {
04661             parkinglot->parking_start = start;
04662             parkinglot->parking_stop = end;
04663          }
04664       } else if (!strcasecmp(confvar->name, "findslot")) {
04665          parkinglot->parkfindnext = (!strcasecmp(confvar->value, "next"));
04666       } else if (!strcasecmp(confvar->name, "parkedcalltransfers")) {
04667                         ast_log(LOG_DEBUG, "Setting parking lot %s %s to %s\n", name, confvar->name, confvar->value);
04668                         if (!strcasecmp(confvar->value, "both"))
04669                                 parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
04670                         else if (!strcasecmp(confvar->value, "caller"))
04671                                 parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
04672                         else if (!strcasecmp(confvar->value, "callee"))
04673                                 parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
04674                 } else if (!strcasecmp(confvar->name, "parkedcallreparking")) {
04675                         ast_log(LOG_DEBUG, "Setting parking lot %s %s to %s\n", name, confvar->name, confvar->value);
04676                         if (!strcasecmp(confvar->value, "both"))
04677                                 parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYBOTH;
04678                         else if (!strcasecmp(confvar->value, "caller"))
04679                                 parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLER;
04680                         else if (!strcasecmp(confvar->value, "callee"))
04681                                 parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLEE;
04682                 } else if (!strcasecmp(confvar->name, "parkedcallhangup")) {
04683                         ast_log(LOG_DEBUG, "Setting parking lot %s %s to %s\n", name, confvar->name, confvar->value);
04684                         if (!strcasecmp(confvar->value, "both"))
04685                                 parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYBOTH;
04686                         else if (!strcasecmp(confvar->value, "caller"))
04687                                 parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLER;
04688                         else if (!strcasecmp(confvar->value, "callee"))
04689                                 parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLEE;
04690                 } else if (!strcasecmp(confvar->name, "parkedcallrecording")) {
04691                         ast_log(LOG_DEBUG, "Setting parking lot %s %s to %s\n", name, confvar->name, confvar->value);
04692                         if (!strcasecmp(confvar->value, "both"))
04693                                 parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYBOTH;
04694                         else if (!strcasecmp(confvar->value, "caller"))
04695                                 parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
04696                         else if (!strcasecmp(confvar->value, "callee"))
04697                                 parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
04698                 }
04699       confvar = confvar->next;
04700    }
04701    /* make sure parkingtime is set if not specified */
04702    if (parkinglot->parkingtime == 0) {
04703       parkinglot->parkingtime = DEFAULT_PARK_TIME;
04704    }
04705    if (ast_strlen_zero(parkinglot->parkext)) {
04706       ast_debug(2, "no parkext specified for %s - setting it to %s\n", parkinglot->name, DEFAULT_PARK_EXTENSION);
04707       ast_copy_string(parkinglot->parkext, DEFAULT_PARK_EXTENSION, sizeof(parkinglot->parkext));
04708    }
04709 
04710    if (!var) { /* Default parking lot */
04711       ast_copy_string(parkinglot->parking_con, "parkedcalls", sizeof(parkinglot->parking_con));
04712       ast_copy_string(parkinglot->mohclass, "default", sizeof(parkinglot->mohclass));
04713    }
04714    ast_copy_string(parkinglot->parking_con_dial, "park-dial", sizeof(parkinglot->parking_con_dial));
04715 
04716    /* Check for errors */
04717    if (ast_strlen_zero(parkinglot->parking_con)) {
04718       ast_log(LOG_WARNING, "Parking lot %s lacks context\n", name);
04719       error = 1;
04720    }
04721 
04722    /* Create context */
04723    if (!error && !(con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar))) {
04724       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
04725       error = 1;
04726    }
04727 
04728    /* Add a parking extension into the context */
04729    if (!error && !oldparkinglot) {
04730       if (!ast_strlen_zero(parkinglot->parkext)) {
04731          if (ast_add_extension2(con, 1, parkinglot->parkext, 1, NULL, NULL, parkcall, strdup(""), ast_free_ptr, registrar) == -1)
04732             error = 1;
04733       }
04734    }
04735 
04736    /* Add parking hints */
04737    if (parkinglot->parkaddhints)
04738       park_add_hints(parkinglot->parking_con, parkinglot->parking_start, parkinglot->parking_stop);
04739 
04740    ao2_unlock(parkinglot);
04741 
04742    if (error) {
04743       ast_log(LOG_WARNING, "Parking %s not open for business. Configuration error.\n", name);
04744       parkinglot_destroy(parkinglot);
04745       parkinglot_unref(parkinglot);
04746       return NULL;
04747    }
04748    ast_debug(1, "Parking %s now open for business. (start exten %d end %d)\n", name, start, end);
04749    parkinglot->the_mark = 0;
04750 
04751    /* Move it into the list, if it wasn't already there */
04752    if (!oldparkinglot) {
04753       ao2_link(parkinglots, parkinglot);
04754    }
04755    parkinglot_unref(parkinglot);
04756 
04757    return parkinglot;
04758 }
04759 
04760 static int load_config(void) 
04761 {
04762    int start = 0, end = 0;
04763    int res;
04764    int i;
04765    struct ast_context *con = NULL;
04766    struct ast_config *cfg = NULL;
04767    struct ast_variable *var = NULL;
04768    struct feature_group *fg = NULL;
04769    struct ast_flags config_flags = { 0 };
04770    char *ctg; 
04771    static const char * const categories[] = { 
04772       /* Categories in features.conf that are not
04773        * to be parsed as group categories
04774        */
04775       "general",
04776       "featuremap",
04777       "applicationmap"
04778    };
04779 
04780    default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
04781    if (default_parkinglot) {
04782       ao2_lock(default_parkinglot);
04783       ast_copy_string(default_parkinglot->parkext, DEFAULT_PARK_EXTENSION, sizeof(default_parkinglot->parkext));
04784       default_parkinglot->parking_start = 701;
04785       default_parkinglot->parking_stop = 750;
04786       default_parkinglot->parking_offset = 0;
04787       default_parkinglot->parkfindnext = 0;
04788       default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
04789       ao2_unlock(default_parkinglot);
04790    }
04791    
04792    if (default_parkinglot) {
04793       ast_debug(1, "Configuration of default parkinglot done.\n");
04794    } else {
04795       ast_log(LOG_ERROR, "Configuration of default parkinglot failed.\n");
04796       return -1;
04797    }
04798 
04799    /* Reset to defaults */
04800    strcpy(default_parkinglot->parkext, DEFAULT_PARK_EXTENSION);
04801    strcpy(pickup_ext, "*8");
04802    courtesytone[0] = '\0';
04803    strcpy(xfersound, "beep");
04804    strcpy(xferfailsound, "beeperr");
04805    pickupsound[0] = '\0';
04806    pickupfailsound[0] = '\0';
04807    adsipark = 0;
04808    comebacktoorigin = 1;
04809    parkeddynamic = 0;
04810 
04811    default_parkinglot->parkaddhints = 0;
04812    default_parkinglot->parkedcalltransfers = 0;
04813    default_parkinglot->parkedcallreparking = 0;
04814    default_parkinglot->parkedcallrecording = 0;
04815    default_parkinglot->parkedcallhangup = 0;
04816 
04817    transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
04818    featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
04819    atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
04820    atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
04821    atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
04822    atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
04823 
04824    cfg = ast_config_load2("features.conf", "features", config_flags);
04825    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
04826       ast_log(LOG_WARNING,"Could not load features.conf\n");
04827       return 0;
04828    }
04829    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
04830       if (!strcasecmp(var->name, "parkext")) {
04831          ast_copy_string(default_parkinglot->parkext, var->value, sizeof(default_parkinglot->parkext));
04832       } else if (!strcasecmp(var->name, "context")) {
04833          ast_copy_string(default_parkinglot->parking_con, var->value, sizeof(default_parkinglot->parking_con));
04834       } else if (!strcasecmp(var->name, "parkingtime")) {
04835          if ((sscanf(var->value, "%30d", &default_parkinglot->parkingtime) != 1) || (default_parkinglot->parkingtime < 1)) {
04836             ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
04837             default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
04838          } else
04839             default_parkinglot->parkingtime = default_parkinglot->parkingtime * 1000;
04840       } else if (!strcasecmp(var->name, "parkpos")) {
04841          if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
04842             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);
04843          } else if (default_parkinglot) {
04844             default_parkinglot->parking_start = start;
04845             default_parkinglot->parking_stop = end;
04846          } else {
04847             ast_log(LOG_WARNING, "No default parking lot!\n");
04848          }
04849       } else if (!strcasecmp(var->name, "findslot")) {
04850          default_parkinglot->parkfindnext = (!strcasecmp(var->value, "next"));
04851       } else if (!strcasecmp(var->name, "parkinghints")) {
04852          default_parkinglot->parkaddhints = ast_true(var->value);
04853       } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
04854          if (!strcasecmp(var->value, "both"))
04855             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
04856          else if (!strcasecmp(var->value, "caller"))
04857             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
04858          else if (!strcasecmp(var->value, "callee"))
04859             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
04860       } else if (!strcasecmp(var->name, "parkedcallreparking")) {
04861          if (!strcasecmp(var->value, "both"))
04862             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYBOTH;
04863          else if (!strcasecmp(var->value, "caller"))
04864             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLER;
04865          else if (!strcasecmp(var->value, "callee"))
04866             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLEE;
04867       } else if (!strcasecmp(var->name, "parkedcallhangup")) {
04868          if (!strcasecmp(var->value, "both"))
04869             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYBOTH;
04870          else if (!strcasecmp(var->value, "caller"))
04871             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLER;
04872          else if (!strcasecmp(var->value, "callee"))
04873             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLEE;
04874       } else if (!strcasecmp(var->name, "parkedcallrecording")) {
04875          if (!strcasecmp(var->value, "both"))
04876             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYBOTH;
04877          else if (!strcasecmp(var->value, "caller"))
04878             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
04879          else if (!strcasecmp(var->value, "callee"))
04880             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
04881       } else if (!strcasecmp(var->name, "parkeddynamic")) {
04882          parkeddynamic = ast_true(var->value);
04883       } else if (!strcasecmp(var->name, "adsipark")) {
04884          adsipark = ast_true(var->value);
04885       } else if (!strcasecmp(var->name, "transferdigittimeout")) {
04886          if ((sscanf(var->value, "%30d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
04887             ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
04888             transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
04889          } else
04890             transferdigittimeout = transferdigittimeout * 1000;
04891       } else if (!strcasecmp(var->name, "featuredigittimeout")) {
04892          if ((sscanf(var->value, "%30d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
04893             ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
04894             featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
04895          }
04896       } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
04897          if ((sscanf(var->value, "%30d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
04898             ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
04899             atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
04900          } else
04901             atxfernoanswertimeout = atxfernoanswertimeout * 1000;
04902       } else if (!strcasecmp(var->name, "atxferloopdelay")) {
04903          if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
04904             ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
04905             atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
04906          } else 
04907             atxferloopdelay *= 1000;
04908       } else if (!strcasecmp(var->name, "atxferdropcall")) {
04909          atxferdropcall = ast_true(var->value);
04910       } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
04911          if ((sscanf(var->value, "%30u", &atxfercallbackretries) != 1)) {
04912             ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
04913             atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
04914          }
04915       } else if (!strcasecmp(var->name, "courtesytone")) {
04916          ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
04917       }  else if (!strcasecmp(var->name, "parkedplay")) {
04918          if (!strcasecmp(var->value, "both"))
04919             parkedplay = 2;
04920          else if (!strcasecmp(var->value, "parked"))
04921             parkedplay = 1;
04922          else
04923             parkedplay = 0;
04924       } else if (!strcasecmp(var->name, "xfersound")) {
04925          ast_copy_string(xfersound, var->value, sizeof(xfersound));
04926       } else if (!strcasecmp(var->name, "xferfailsound")) {
04927          ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
04928       } else if (!strcasecmp(var->name, "pickupexten")) {
04929          ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
04930       } else if (!strcasecmp(var->name, "pickupsound")) {
04931          ast_copy_string(pickupsound, var->value, sizeof(pickupsound));
04932       } else if (!strcasecmp(var->name, "pickupfailsound")) {
04933          ast_copy_string(pickupfailsound, var->value, sizeof(pickupfailsound));
04934       } else if (!strcasecmp(var->name, "comebacktoorigin")) {
04935          comebacktoorigin = ast_true(var->value);
04936       } else if (!strcasecmp(var->name, "parkedmusicclass")) {
04937          ast_copy_string(default_parkinglot->mohclass, var->value, sizeof(default_parkinglot->mohclass));
04938       }
04939    }
04940 
04941    unmap_features();
04942    for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
04943       if (remap_feature(var->name, var->value))
04944          ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
04945    }
04946 
04947    /* Map a key combination to an application*/
04948    ast_unregister_features();
04949    for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
04950       char *tmp_val = ast_strdupa(var->value);
04951       char *activateon; 
04952       struct ast_call_feature *feature;
04953       AST_DECLARE_APP_ARGS(args,
04954          AST_APP_ARG(exten);
04955          AST_APP_ARG(activatedby);
04956          AST_APP_ARG(app);
04957          AST_APP_ARG(app_args);
04958          AST_APP_ARG(moh_class);
04959       );
04960 
04961       AST_STANDARD_APP_ARGS(args, tmp_val);
04962       if (strchr(args.app, '(')) {
04963          /* New syntax */
04964          args.moh_class = args.app_args;
04965          args.app_args = strchr(args.app, '(');
04966          *args.app_args++ = '\0';
04967          if (args.app_args[strlen(args.app_args) - 1] == ')') {
04968             args.app_args[strlen(args.app_args) - 1] = '\0';
04969          }
04970       }
04971 
04972       activateon = strsep(&args.activatedby, "/"); 
04973 
04974       /*! \todo XXX var_name or app_args ? */
04975       if (ast_strlen_zero(args.app) || ast_strlen_zero(args.exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
04976          ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
04977             args.app, args.exten, activateon, var->name);
04978          continue;
04979       }
04980 
04981       AST_RWLIST_RDLOCK(&feature_list);
04982       if ((feature = find_dynamic_feature(var->name))) {
04983          AST_RWLIST_UNLOCK(&feature_list);
04984          ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
04985          continue;
04986       }
04987       AST_RWLIST_UNLOCK(&feature_list);
04988             
04989       if (!(feature = ast_calloc(1, sizeof(*feature)))) {
04990          continue;
04991       }
04992 
04993       ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
04994       ast_copy_string(feature->app, args.app, FEATURE_APP_LEN);
04995       ast_copy_string(feature->exten, args.exten, FEATURE_EXTEN_LEN);
04996       
04997       if (args.app_args) {
04998          ast_copy_string(feature->app_args, args.app_args, FEATURE_APP_ARGS_LEN);
04999       }
05000 
05001       if (args.moh_class) {
05002          ast_copy_string(feature->moh_class, args.moh_class, FEATURE_MOH_LEN);
05003       }
05004 
05005       ast_copy_string(feature->exten, args.exten, sizeof(feature->exten));
05006       feature->operation = feature_exec_app;
05007       ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
05008 
05009       /* Allow caller and calle to be specified for backwards compatability */
05010       if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
05011          ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
05012       else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
05013          ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
05014       else {
05015          ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
05016             " must be 'self', or 'peer'\n", var->name);
05017          continue;
05018       }
05019 
05020       if (ast_strlen_zero(args.activatedby))
05021          ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
05022       else if (!strcasecmp(args.activatedby, "caller"))
05023          ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
05024       else if (!strcasecmp(args.activatedby, "callee"))
05025          ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
05026       else if (!strcasecmp(args.activatedby, "both"))
05027          ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
05028       else {
05029          ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
05030             " must be 'caller', or 'callee', or 'both'\n", var->name);
05031          continue;
05032       }
05033 
05034       ast_register_feature(feature);
05035 
05036       ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, args.app, args.app_args, args.exten);
05037    }
05038 
05039    ast_unregister_groups();
05040    AST_RWLIST_WRLOCK(&feature_groups);
05041 
05042    ctg = NULL;
05043    while ((ctg = ast_category_browse(cfg, ctg))) {
05044       /* Is this a parkinglot definition ? */
05045       if (!strncasecmp(ctg, "parkinglot_", strlen("parkinglot_"))) {
05046          ast_debug(2, "Found configuration section %s, assume parking context\n", ctg);
05047          if(!build_parkinglot(ctg, ast_variable_browse(cfg, ctg)))
05048             ast_log(LOG_ERROR, "Could not build parking lot %s. Configuration error.\n", ctg);
05049          else
05050             ast_debug(1, "Configured parking context %s\n", ctg);
05051          continue;   
05052       }
05053       /* No, check if it's a group */
05054       for (i = 0; i < ARRAY_LEN(categories); i++) {
05055          if (!strcasecmp(categories[i], ctg))
05056             break;
05057       }
05058 
05059       if (i < ARRAY_LEN(categories)) 
05060          continue;
05061 
05062       if (!(fg = register_group(ctg)))
05063          continue;
05064 
05065       for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
05066          struct ast_call_feature *feature;
05067 
05068          AST_RWLIST_RDLOCK(&feature_list);
05069          if (!(feature = find_dynamic_feature(var->name)) && 
05070              !(feature = ast_find_call_feature(var->name))) {
05071             AST_RWLIST_UNLOCK(&feature_list);
05072             ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
05073             continue;
05074          }
05075          AST_RWLIST_UNLOCK(&feature_list);
05076 
05077          register_group_feature(fg, var->value, feature);
05078       }
05079    }
05080 
05081    AST_RWLIST_UNLOCK(&feature_groups);
05082 
05083    ast_config_destroy(cfg);
05084 
05085    if (!(con = ast_context_find_or_create(NULL, NULL, default_parkinglot->parking_con, registrar))) {
05086       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", default_parkinglot->parking_con);
05087       return -1;
05088    }
05089    res = ast_add_extension2(con, 1, default_parkinglot->parkext, 1, NULL, NULL, parkcall, NULL, NULL, registrar);
05090    if (default_parkinglot->parkaddhints)
05091       park_add_hints(default_parkinglot->parking_con, default_parkinglot->parking_start, default_parkinglot->parking_stop);
05092    if (!res)
05093       notify_metermaids(default_parkinglot->parkext, default_parkinglot->parking_con, AST_DEVICE_INUSE); 
05094    return res;
05095 
05096 }
05097 
05098 /*!
05099  * \brief CLI command to list configured features
05100  * \param e
05101  * \param cmd
05102  * \param a
05103  *
05104  * \retval CLI_SUCCESS on success.
05105  * \retval NULL when tab completion is used.
05106  */
05107 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05108 {
05109    int i;
05110    struct ast_call_feature *feature;
05111    struct ao2_iterator iter;
05112    struct ast_parkinglot *curlot;
05113 #define HFS_FORMAT "%-25s %-7s %-7s\n"
05114 
05115    switch (cmd) {
05116    
05117    case CLI_INIT:
05118       e->command = "features show";
05119       e->usage =
05120          "Usage: features show\n"
05121          "       Lists configured features\n";
05122       return NULL;
05123    case CLI_GENERATE:
05124       return NULL;
05125    }
05126 
05127    ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
05128    ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
05129 
05130    ast_cli(a->fd, HFS_FORMAT, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
05131 
05132    ast_rwlock_rdlock(&features_lock);
05133    for (i = 0; i < FEATURES_COUNT; i++)
05134       ast_cli(a->fd, HFS_FORMAT, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
05135    ast_rwlock_unlock(&features_lock);
05136 
05137    ast_cli(a->fd, "\n");
05138    ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
05139    ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
05140    if (AST_RWLIST_EMPTY(&feature_list)) {
05141       ast_cli(a->fd, "(none)\n");
05142    } else {
05143       AST_RWLIST_RDLOCK(&feature_list);
05144       AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
05145          ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
05146       }
05147       AST_RWLIST_UNLOCK(&feature_list);
05148    }
05149 
05150    ast_cli(a->fd, "\nFeature Groups:\n");
05151    ast_cli(a->fd, "---------------\n");
05152    if (AST_RWLIST_EMPTY(&feature_groups)) {
05153       ast_cli(a->fd, "(none)\n");
05154    } else {
05155       struct feature_group *fg;
05156       struct feature_group_exten *fge;
05157 
05158       AST_RWLIST_RDLOCK(&feature_groups);
05159       AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
05160          ast_cli(a->fd, "===> Group: %s\n", fg->gname);
05161          AST_LIST_TRAVERSE(&fg->features, fge, entry) {
05162             ast_cli(a->fd, "===> --> %s (%s)\n", fge->feature->sname, fge->exten);
05163          }
05164       }
05165       AST_RWLIST_UNLOCK(&feature_groups);
05166    }
05167 
05168    iter = ao2_iterator_init(parkinglots, 0);
05169    while ((curlot = ao2_iterator_next(&iter))) {
05170       ast_cli(a->fd, "\nCall parking (Parking lot: %s)\n", curlot->name);
05171       ast_cli(a->fd, "------------\n");
05172       ast_cli(a->fd,"%-22s:      %s\n", "Parking extension", curlot->parkext);
05173       ast_cli(a->fd,"%-22s:      %s\n", "Parking context", curlot->parking_con);
05174       ast_cli(a->fd,"%-22s:      %d-%d\n", "Parked call extensions", curlot->parking_start, curlot->parking_stop);
05175       ast_cli(a->fd,"%-22s:      %d\n", "Parkingtime", curlot->parkingtime);
05176       ast_cli(a->fd,"%-22s:      %s\n", "MusicOnHold class", curlot->mohclass);
05177       ast_cli(a->fd,"\n");
05178       ao2_ref(curlot, -1);
05179    }
05180    ao2_iterator_destroy(&iter);
05181 
05182    return CLI_SUCCESS;
05183 }
05184 
05185 static int parkinglot_markall_cb(void *obj, void *arg, int flags)
05186 {
05187    struct ast_parkinglot *parkinglot = obj;
05188    parkinglot->the_mark = 1;
05189    return 0;
05190 }
05191 
05192 static int parkinglot_is_marked_cb(void *obj, void *arg, int flags)
05193 {
05194    struct ast_parkinglot *parkinglot = obj;
05195    return parkinglot->the_mark ? CMP_MATCH : 0;
05196 }
05197 
05198 int ast_features_reload(void)
05199 {
05200    int res;
05201 
05202    ao2_t_callback(parkinglots, OBJ_NODATA, parkinglot_markall_cb, NULL, "callback to mark all parkinglots");
05203    res = load_config(); /* Reload configuration */
05204    ao2_t_callback(parkinglots, OBJ_NODATA | OBJ_UNLINK, parkinglot_is_marked_cb, NULL, "callback to remove all marked parkinglots");
05205    
05206    return res;
05207 }
05208 
05209 static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05210 {
05211    switch (cmd) { 
05212    case CLI_INIT:
05213       e->command = "features reload";
05214       e->usage =
05215          "Usage: features reload\n"
05216          "       Reloads configured call features from features.conf\n";
05217       return NULL;
05218    case CLI_GENERATE:
05219       return NULL;
05220    }
05221    ast_features_reload();
05222 
05223    return CLI_SUCCESS;
05224 }
05225 
05226 /*!
05227  * \brief Actual bridge
05228  * \param chan
05229  * \param tmpchan
05230  * 
05231  * Stop hold music, lock both channels, masq channels,
05232  * after bridge return channel to next priority.
05233 */
05234 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
05235 {
05236    ast_moh_stop(chan);
05237    ast_channel_lock_both(chan, tmpchan);
05238    ast_setstate(tmpchan, chan->_state);
05239    tmpchan->readformat = chan->readformat;
05240    tmpchan->writeformat = chan->writeformat;
05241    ast_channel_masquerade(tmpchan, chan);
05242    ast_channel_unlock(chan);
05243    ast_channel_unlock(tmpchan);
05244 
05245    /* must be done without any channel locks held */
05246    ast_do_masquerade(tmpchan);
05247 
05248    /* when returning from bridge, the channel will continue at the next priority */
05249    ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
05250 }
05251 
05252 /*!
05253  * \brief Bridge channels together
05254  * \param s
05255  * \param m
05256  * 
05257  * Make sure valid channels were specified, 
05258  * send errors if any of the channels could not be found/locked, answer channels if needed,
05259  * create the placeholder channels and grab the other channels 
05260  * make the channels compatible, send error if we fail doing so 
05261  * setup the bridge thread object and start the bridge.
05262  * 
05263  * \retval 0 on success or on incorrect use.
05264  * \retval 1 on failure to bridge channels.
05265 */
05266 static int action_bridge(struct mansession *s, const struct message *m)
05267 {
05268    const char *channela = astman_get_header(m, "Channel1");
05269    const char *channelb = astman_get_header(m, "Channel2");
05270    const char *playtone = astman_get_header(m, "Tone");
05271    struct ast_channel *chana = NULL, *chanb = NULL, *chans[2];
05272    struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
05273    struct ast_bridge_thread_obj *tobj = NULL;
05274 
05275    /* make sure valid channels were specified */
05276    if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
05277       astman_send_error(s, m, "Missing channel parameter in request");
05278       return 0;
05279    }
05280 
05281    /* Start with chana */
05282    chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
05283 
05284    /* send errors if any of the channels could not be found/locked */
05285    if (!chana) {
05286       char buf[256];
05287       snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
05288       astman_send_error(s, m, buf);
05289       return 0;
05290    }
05291 
05292    /* Answer the channels if needed */
05293    if (chana->_state != AST_STATE_UP)
05294       ast_answer(chana);
05295 
05296    /* create the placeholder channels and grab the other channels */
05297    if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
05298       NULL, NULL, chana->linkedid, 0, "Bridge/%s", chana->name))) {
05299       astman_send_error(s, m, "Unable to create temporary channel!");
05300       chana = ast_channel_unref(chana);
05301       return 1;
05302    }
05303 
05304    do_bridge_masquerade(chana, tmpchana);
05305 
05306    chana = ast_channel_unref(chana);
05307 
05308    /* now do chanb */
05309    chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
05310    /* send errors if any of the channels could not be found/locked */
05311    if (!chanb) {
05312       char buf[256];
05313       snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
05314       ast_hangup(tmpchana);
05315       astman_send_error(s, m, buf);
05316       return 0;
05317    }
05318 
05319    /* Answer the channels if needed */
05320    if (chanb->_state != AST_STATE_UP)
05321       ast_answer(chanb);
05322 
05323    /* create the placeholder channels and grab the other channels */
05324    if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
05325       NULL, NULL, chanb->linkedid, 0, "Bridge/%s", chanb->name))) {
05326       astman_send_error(s, m, "Unable to create temporary channels!");
05327       ast_hangup(tmpchana);
05328       chanb = ast_channel_unref(chanb);
05329       return 1;
05330    }
05331 
05332    do_bridge_masquerade(chanb, tmpchanb);
05333 
05334    chanb = ast_channel_unref(chanb);
05335 
05336    /* make the channels compatible, send error if we fail doing so */
05337    if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
05338       ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
05339       astman_send_error(s, m, "Could not make channels compatible for manager bridge");
05340       ast_hangup(tmpchana);
05341       ast_hangup(tmpchanb);
05342       return 1;
05343    }
05344 
05345    /* setup the bridge thread object and start the bridge */
05346    if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
05347       ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
05348       astman_send_error(s, m, "Unable to spawn a new bridge thread");
05349       ast_hangup(tmpchana);
05350       ast_hangup(tmpchanb);
05351       return 1;
05352    }
05353 
05354    tobj->chan = tmpchana;
05355    tobj->peer = tmpchanb;
05356    tobj->return_to_pbx = 1;
05357 
05358    if (ast_true(playtone)) {
05359       if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
05360          if (ast_waitstream(tmpchanb, "") < 0)
05361             ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
05362       }
05363    }
05364 
05365    chans[0] = tmpchana;
05366    chans[1] = tmpchanb;
05367 
05368    ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeAction", 2, chans,
05369             "Response: Success\r\n"
05370             "Channel1: %s\r\n"
05371             "Channel2: %s\r\n", tmpchana->name, tmpchanb->name);
05372 
05373    bridge_call_thread_launch(tobj);
05374 
05375    astman_send_ack(s, m, "Launched bridge thread with success");
05376 
05377    return 0;
05378 }
05379 
05380 /*!
05381  * \brief CLI command to list parked calls
05382  * \param e 
05383  * \param cmd
05384  * \param a
05385  *  
05386  * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
05387  * \retval CLI_SUCCESS on success.
05388  * \retval CLI_SHOWUSAGE on incorrect number of arguments.
05389  * \retval NULL when tab completion is used.
05390 */
05391 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05392 {
05393    struct parkeduser *cur;
05394    int numparked = 0;
05395    struct ao2_iterator iter;
05396    struct ast_parkinglot *curlot;
05397 
05398    switch (cmd) {
05399    case CLI_INIT:
05400       e->command = "parkedcalls show";
05401       e->usage =
05402          "Usage: parkedcalls show\n"
05403          "       List currently parked calls\n";
05404       return NULL;
05405    case CLI_GENERATE:
05406       return NULL;
05407    }
05408 
05409    if (a->argc > e->args)
05410       return CLI_SHOWUSAGE;
05411 
05412    ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
05413       , "Context", "Extension", "Pri", "Timeout");
05414 
05415    iter = ao2_iterator_init(parkinglots, 0);
05416    while ((curlot = ao2_iterator_next(&iter))) {
05417       int lotparked = 0;
05418       /* subtract ref for iterator and for configured parking lot */
05419       ast_cli(a->fd, "*** Parking lot: %s (%d)\n", curlot->name, ao2_ref(curlot, 0) - 2);
05420 
05421       AST_LIST_LOCK(&curlot->parkings);
05422       AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
05423          ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
05424             ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
05425             ,cur->priority,
05426             (long)(cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL)) );
05427          numparked++;
05428          numparked += lotparked;
05429       }
05430       AST_LIST_UNLOCK(&curlot->parkings);
05431       if (lotparked)
05432          ast_cli(a->fd, "   %d parked call%s in parking lot %s\n", lotparked, ESS(lotparked), curlot->name);
05433 
05434       ao2_ref(curlot, -1);
05435    }
05436 
05437    ast_cli(a->fd, "---\n%d parked call%s in total.\n", numparked, ESS(numparked));
05438 
05439    return CLI_SUCCESS;
05440 }
05441 
05442 static struct ast_cli_entry cli_features[] = {
05443    AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
05444    AST_CLI_DEFINE(handle_features_reload, "Reloads configured features"),
05445    AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls"),
05446 };
05447 
05448 /*! 
05449  * \brief Dump parking lot status
05450  * \param s
05451  * \param m
05452  * 
05453  * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
05454  * \return Always RESULT_SUCCESS 
05455 */
05456 static int manager_parking_status(struct mansession *s, const struct message *m)
05457 {
05458    struct parkeduser *cur;
05459    const char *id = astman_get_header(m, "ActionID");
05460    char idText[256] = "";
05461    struct ao2_iterator iter;
05462    struct ast_parkinglot *curlot;
05463 
05464    if (!ast_strlen_zero(id))
05465       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
05466 
05467    astman_send_ack(s, m, "Parked calls will follow");
05468 
05469    iter = ao2_iterator_init(parkinglots, 0);
05470    while ((curlot = ao2_iterator_next(&iter))) {
05471 
05472       AST_LIST_LOCK(&curlot->parkings);
05473       AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
05474          astman_append(s, "Event: ParkedCall\r\n"
05475             "Exten: %d\r\n"
05476             "Channel: %s\r\n"
05477             "From: %s\r\n"
05478             "Timeout: %ld\r\n"
05479             "CallerIDNum: %s\r\n"
05480             "CallerIDName: %s\r\n"
05481             "%s"
05482             "\r\n",
05483             cur->parkingnum, cur->chan->name, cur->peername,
05484             (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
05485             S_COR(cur->chan->caller.id.number.valid, cur->chan->caller.id.number.str, ""),   /* XXX in other places it is <unknown> */
05486             S_COR(cur->chan->caller.id.name.valid, cur->chan->caller.id.name.str, ""),
05487             idText);
05488       }
05489       AST_LIST_UNLOCK(&curlot->parkings);
05490       ao2_ref(curlot, -1);
05491    }
05492 
05493    astman_append(s,
05494       "Event: ParkedCallsComplete\r\n"
05495       "%s"
05496       "\r\n",idText);
05497 
05498 
05499    return RESULT_SUCCESS;
05500 }
05501 
05502 /*!
05503  * \brief Create manager event for parked calls
05504  * \param s
05505  * \param m
05506  *
05507  * Get channels involved in park, create event.
05508  * \return Always 0
05509 */
05510 static int manager_park(struct mansession *s, const struct message *m)
05511 {
05512    const char *channel = astman_get_header(m, "Channel");
05513    const char *channel2 = astman_get_header(m, "Channel2");
05514    const char *timeout = astman_get_header(m, "Timeout");
05515    const char *parkinglotname = astman_get_header(m, "Parkinglot");
05516    char buf[BUFSIZ];
05517    int res = 0;
05518    struct ast_channel *ch1, *ch2;
05519    struct ast_park_call_args args = {0,};
05520 
05521    if (ast_strlen_zero(channel)) {
05522       astman_send_error(s, m, "Channel not specified");
05523       return 0;
05524    }
05525 
05526    if (ast_strlen_zero(channel2)) {
05527       astman_send_error(s, m, "Channel2 not specified");
05528       return 0;
05529    }
05530 
05531    if (!(ch1 = ast_channel_get_by_name(channel))) {
05532       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
05533       astman_send_error(s, m, buf);
05534       return 0;
05535    }
05536 
05537    if (!(ch2 = ast_channel_get_by_name(channel2))) {
05538       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
05539       astman_send_error(s, m, buf);
05540       ast_channel_unref(ch1);
05541       return 0;
05542    }
05543 
05544    if (!ast_strlen_zero(timeout)) {
05545       sscanf(timeout, "%30d", &args.timeout);
05546    }
05547    if (!ast_strlen_zero(parkinglotname)) {
05548       args.parkinglot = find_parkinglot(parkinglotname);
05549    }
05550 
05551    ast_channel_lock(ch1);
05552    while (ast_channel_trylock(ch2)) {
05553       CHANNEL_DEADLOCK_AVOIDANCE(ch1);
05554    }
05555 
05556    res = masq_park_call(ch1, ch2, 0, NULL, 0, &args);
05557    if (!res) {
05558       ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
05559       astman_send_ack(s, m, "Park successful");
05560    } else {
05561       astman_send_error(s, m, "Park failure");
05562    }
05563 
05564    ast_channel_unlock(ch1);
05565    ast_channel_unlock(ch2);
05566 
05567    ch1 = ast_channel_unref(ch1);
05568    ch2 = ast_channel_unref(ch2);
05569 
05570    return 0;
05571 }
05572 
05573 static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
05574 {
05575    struct ast_channel *c = data;
05576    struct ast_channel *chan = obj;
05577 
05578    int i = !chan->pbx &&
05579       /* Accessing 'chan' here is safe without locking, because there is no way for
05580          the channel do disappear from under us at this point.  pickupgroup *could*
05581          change while we're here, but that isn't a problem. */
05582       (c != chan) &&
05583       (chan->pickupgroup & c->callgroup) &&
05584       ((chan->_state == AST_STATE_RINGING) || (chan->_state == AST_STATE_RING)) &&
05585       !c->masq;
05586 
05587    return i ? CMP_MATCH | CMP_STOP : 0;
05588 }
05589 
05590 /*!
05591  * \brief Pickup a call
05592  * \param chan channel that initiated pickup.
05593  *
05594  * Walk list of channels, checking it is not itself, channel is pbx one,
05595  * check that the callgroup for both channels are the same and the channel is ringing.
05596  * Answer calling channel, flag channel as answered on queue, masq channels together.
05597 */
05598 int ast_pickup_call(struct ast_channel *chan)
05599 {
05600    struct ast_channel *cur, *chans[2] = { chan, };
05601    struct ast_party_connected_line connected_caller;
05602    int res;
05603    const char *chan_name;
05604    const char *cur_name;
05605 
05606    if (!(cur = ast_channel_callback(find_channel_by_group, NULL, chan, 0))) {
05607       ast_debug(1, "No call pickup possible...\n");
05608       if (!ast_strlen_zero(pickupfailsound)) {
05609          ast_stream_and_wait(chan, pickupfailsound, "");
05610       }
05611       return -1;
05612    }
05613 
05614    chans[1] = cur;
05615 
05616    ast_channel_lock_both(cur, chan);
05617 
05618    cur_name = ast_strdupa(cur->name);
05619    chan_name = ast_strdupa(chan->name);
05620 
05621    ast_debug(1, "Call pickup on chan '%s' by '%s'\n", cur_name, chan_name);
05622 
05623    connected_caller = cur->connected;
05624    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
05625    if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
05626       ast_channel_update_connected_line(chan, &connected_caller, NULL);
05627    }
05628 
05629    ast_party_connected_line_collect_caller(&connected_caller, &chan->caller);
05630    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
05631    ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
05632 
05633    ast_channel_unlock(cur);
05634    ast_channel_unlock(chan);
05635 
05636    if (ast_answer(chan)) {
05637       ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
05638    }
05639 
05640    if (ast_queue_control(chan, AST_CONTROL_ANSWER)) {
05641       ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
05642    }
05643 
05644    if ((res = ast_channel_masquerade(cur, chan))) {
05645       ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan_name, cur_name);
05646    }
05647 
05648    if (!ast_strlen_zero(pickupsound)) {
05649       ast_stream_and_wait(cur, pickupsound, "");
05650    }
05651 
05652    /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
05653    ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
05654       "Channel: %s\r\nTargetChannel: %s\r\n", chan->name, cur->name);
05655 
05656    cur = ast_channel_unref(cur);
05657 
05658    return res;
05659 }
05660 
05661 static char *app_bridge = "Bridge";
05662 
05663 enum {
05664    BRIDGE_OPT_PLAYTONE = (1 << 0),
05665    OPT_CALLEE_HANGUP =  (1 << 1),
05666    OPT_CALLER_HANGUP =  (1 << 2),
05667    OPT_DURATION_LIMIT = (1 << 3),
05668    OPT_DURATION_STOP =  (1 << 4),
05669    OPT_CALLEE_TRANSFER = (1 << 5),
05670    OPT_CALLER_TRANSFER = (1 << 6),
05671    OPT_CALLEE_MONITOR = (1 << 7),
05672    OPT_CALLER_MONITOR = (1 << 8),
05673    OPT_CALLEE_PARK = (1 << 9),
05674    OPT_CALLER_PARK = (1 << 10),
05675    OPT_CALLEE_KILL = (1 << 11),
05676 };
05677  
05678 enum {
05679    OPT_ARG_DURATION_LIMIT = 0,
05680    OPT_ARG_DURATION_STOP,
05681    /* note: this entry _MUST_ be the last one in the enum */
05682    OPT_ARG_ARRAY_SIZE,
05683 };
05684 
05685 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
05686    AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE),
05687    AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
05688    AST_APP_OPTION('H', OPT_CALLER_HANGUP),
05689    AST_APP_OPTION('k', OPT_CALLEE_PARK),
05690    AST_APP_OPTION('K', OPT_CALLER_PARK),
05691    AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
05692    AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
05693    AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
05694    AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
05695    AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
05696    AST_APP_OPTION('W', OPT_CALLER_MONITOR),
05697    AST_APP_OPTION('x', OPT_CALLEE_KILL),
05698 END_OPTIONS );
05699 
05700 int ast_bridge_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
05701    char *parse, struct timeval *calldurationlimit)
05702 {
05703    char *stringp = ast_strdupa(parse);
05704    char *limit_str, *warning_str, *warnfreq_str;
05705    const char *var;
05706    int play_to_caller = 0, play_to_callee = 0;
05707    int delta;
05708 
05709    limit_str = strsep(&stringp, ":");
05710    warning_str = strsep(&stringp, ":");
05711    warnfreq_str = strsep(&stringp, ":");
05712 
05713    config->timelimit = atol(limit_str);
05714    if (warning_str)
05715       config->play_warning = atol(warning_str);
05716    if (warnfreq_str)
05717       config->warning_freq = atol(warnfreq_str);
05718 
05719    if (!config->timelimit) {
05720       ast_log(LOG_WARNING, "Bridge does not accept L(%s), hanging up.\n", limit_str);
05721       config->timelimit = config->play_warning = config->warning_freq = 0;
05722       config->warning_sound = NULL;
05723       return -1; /* error */
05724    } else if ( (delta = config->play_warning - config->timelimit) > 0) {
05725       int w = config->warning_freq;
05726 
05727       /* If the first warning is requested _after_ the entire call would end,
05728          and no warning frequency is requested, then turn off the warning. If
05729          a warning frequency is requested, reduce the 'first warning' time by
05730          that frequency until it falls within the call's total time limit.
05731          Graphically:
05732               timelim->|    delta        |<-playwarning
05733          0__________________|_________________|
05734                 | w  |    |    |    |
05735 
05736          so the number of intervals to cut is 1+(delta-1)/w
05737       */
05738 
05739       if (w == 0) {
05740          config->play_warning = 0;
05741       } else {
05742          config->play_warning -= w * ( 1 + (delta-1)/w );
05743          if (config->play_warning < 1)
05744             config->play_warning = config->warning_freq = 0;
05745       }
05746    }
05747    
05748    ast_channel_lock(chan);
05749 
05750    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
05751    play_to_caller = var ? ast_true(var) : 1;
05752 
05753    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
05754    play_to_callee = var ? ast_true(var) : 0;
05755 
05756    if (!play_to_caller && !play_to_callee)
05757       play_to_caller = 1;
05758 
05759    var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
05760    config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
05761 
05762    /* The code looking at config wants a NULL, not just "", to decide
05763     * that the message should not be played, so we replace "" with NULL.
05764     * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
05765     * not found.
05766     */
05767 
05768    var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
05769    config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
05770 
05771    var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
05772    config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
05773 
05774    ast_channel_unlock(chan);
05775 
05776    /* undo effect of S(x) in case they are both used */
05777    calldurationlimit->tv_sec = 0;
05778    calldurationlimit->tv_usec = 0;
05779 
05780    /* more efficient to do it like S(x) does since no advanced opts */
05781    if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
05782       calldurationlimit->tv_sec = config->timelimit / 1000;
05783       calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
05784       ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
05785          calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
05786       config->timelimit = play_to_caller = play_to_callee =
05787       config->play_warning = config->warning_freq = 0;
05788    } else {
05789       ast_verb(4, "Limit Data for this call:\n");
05790       ast_verb(4, "timelimit      = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0);
05791       ast_verb(4, "play_warning   = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0);
05792       ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
05793       ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
05794       ast_verb(4, "warning_freq   = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0);
05795       ast_verb(4, "start_sound    = %s\n", S_OR(config->start_sound, ""));
05796       ast_verb(4, "warning_sound  = %s\n", config->warning_sound);
05797       ast_verb(4, "end_sound      = %s\n", S_OR(config->end_sound, ""));
05798    }
05799    if (play_to_caller)
05800       ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
05801    if (play_to_callee)
05802       ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
05803    return 0;
05804 }
05805 
05806 
05807 /*!
05808  * \brief Bridge channels
05809  * \param chan
05810  * \param data channel to bridge with.
05811  * 
05812  * Split data, check we aren't bridging with ourself, check valid channel,
05813  * answer call if not already, check compatible channels, setup bridge config
05814  * now bridge call, if transfered party hangs up return to PBX extension.
05815 */
05816 static int bridge_exec(struct ast_channel *chan, const char *data)
05817 {
05818    struct ast_channel *current_dest_chan, *final_dest_chan, *chans[2];
05819    char *tmp_data  = NULL;
05820    struct ast_flags opts = { 0, };
05821    struct ast_bridge_config bconfig = { { 0, }, };
05822    char *opt_args[OPT_ARG_ARRAY_SIZE];
05823    struct timeval calldurationlimit = { 0, };
05824 
05825    AST_DECLARE_APP_ARGS(args,
05826       AST_APP_ARG(dest_chan);
05827       AST_APP_ARG(options);
05828    );
05829    
05830    if (ast_strlen_zero(data)) {
05831       ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
05832       return -1;
05833    }
05834 
05835    tmp_data = ast_strdupa(data);
05836    AST_STANDARD_APP_ARGS(args, tmp_data);
05837    if (!ast_strlen_zero(args.options))
05838       ast_app_parse_options(bridge_exec_options, &opts, opt_args, args.options);
05839 
05840    /* avoid bridge with ourselves */
05841    if (!strcmp(chan->name, args.dest_chan)) {
05842       ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
05843       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
05844                "Response: Failed\r\n"
05845                "Reason: Unable to bridge channel to itself\r\n"
05846                "Channel1: %s\r\n"
05847                "Channel2: %s\r\n",
05848                chan->name, args.dest_chan);
05849       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
05850       return 0;
05851    }
05852 
05853    /* make sure we have a valid end point */
05854    if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
05855          strlen(args.dest_chan)))) {
05856       ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
05857          "cannot get its lock\n", args.dest_chan);
05858       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
05859                "Response: Failed\r\n"
05860                "Reason: Cannot grab end point\r\n"
05861                "Channel1: %s\r\n"
05862                "Channel2: %s\r\n", chan->name, args.dest_chan);
05863       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
05864       return 0;
05865    }
05866 
05867    /* answer the channel if needed */
05868    if (current_dest_chan->_state != AST_STATE_UP) {
05869       ast_answer(current_dest_chan);
05870    }
05871 
05872    /* try to allocate a place holder where current_dest_chan will be placed */
05873    if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
05874       NULL, NULL, current_dest_chan->linkedid, 0, "Bridge/%s", current_dest_chan->name))) {
05875       ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
05876       ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
05877                "Response: Failed\r\n"
05878                "Reason: cannot create placeholder\r\n"
05879                "Channel1: %s\r\n"
05880                "Channel2: %s\r\n", chan->name, args.dest_chan);
05881    }
05882 
05883    ast_channel_unlock(current_dest_chan);
05884 
05885    do_bridge_masquerade(current_dest_chan, final_dest_chan);
05886 
05887    chans[0] = current_dest_chan;
05888    chans[1] = final_dest_chan;
05889 
05890    /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
05891    /* try to make compatible, send error if we fail */
05892    if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
05893       ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
05894       ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
05895                "Response: Failed\r\n"
05896                "Reason: Could not make channels compatible for bridge\r\n"
05897                "Channel1: %s\r\n"
05898                "Channel2: %s\r\n", chan->name, final_dest_chan->name);
05899       ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
05900       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
05901       current_dest_chan = ast_channel_unref(current_dest_chan);
05902       return 0;
05903    }
05904 
05905    /* Report that the bridge will be successfull */
05906    ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
05907             "Response: Success\r\n"
05908             "Channel1: %s\r\n"
05909             "Channel2: %s\r\n", chan->name, final_dest_chan->name);
05910 
05911    /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */  
05912    if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
05913       if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
05914          if (ast_waitstream(final_dest_chan, "") < 0)
05915             ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
05916       }
05917    }
05918    
05919    current_dest_chan = ast_channel_unref(current_dest_chan);
05920    
05921    if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
05922       if (ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
05923          goto done;
05924    }
05925 
05926    if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER))
05927       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_REDIRECT);
05928    if (ast_test_flag(&opts, OPT_CALLER_TRANSFER))
05929       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_REDIRECT);
05930    if (ast_test_flag(&opts, OPT_CALLEE_HANGUP))
05931       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
05932    if (ast_test_flag(&opts, OPT_CALLER_HANGUP))
05933       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
05934    if (ast_test_flag(&opts, OPT_CALLEE_MONITOR))
05935       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_AUTOMON);
05936    if (ast_test_flag(&opts, OPT_CALLER_MONITOR)) 
05937       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_AUTOMON);
05938    if (ast_test_flag(&opts, OPT_CALLEE_PARK))
05939       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_PARKCALL);
05940    if (ast_test_flag(&opts, OPT_CALLER_PARK))
05941       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_PARKCALL);
05942 
05943    ast_bridge_call(chan, final_dest_chan, &bconfig);
05944 
05945    /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
05946    pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
05947    if (!ast_check_hangup(final_dest_chan) && !ast_test_flag(&opts, OPT_CALLEE_KILL)) {
05948       ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n", 
05949          final_dest_chan->context, final_dest_chan->exten, 
05950          final_dest_chan->priority, final_dest_chan->name);
05951 
05952       if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
05953          ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
05954          ast_hangup(final_dest_chan);
05955       } else
05956          ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
05957    } else {
05958       ast_debug(1, "hangup chan %s since the other endpoint has hung up or the x flag was passed\n", final_dest_chan->name);
05959       ast_hangup(final_dest_chan);
05960    }
05961 done:
05962    if (bconfig.warning_sound) {
05963       ast_free((char *)bconfig.warning_sound);
05964    }
05965    if (bconfig.end_sound) {
05966       ast_free((char *)bconfig.end_sound);
05967    }
05968    if (bconfig.start_sound) {
05969       ast_free((char *)bconfig.start_sound);
05970    }
05971 
05972    return 0;
05973 }
05974 
05975 int ast_features_init(void)
05976 {
05977    int res;
05978 
05979    ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
05980 
05981    parkinglots = ao2_container_alloc(7, parkinglot_hash_cb, parkinglot_cmp_cb);
05982 
05983    if ((res = load_config()))
05984       return res;
05985    ast_cli_register_multiple(cli_features, ARRAY_LEN(cli_features));
05986    ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
05987    res = ast_register_application2(parkedcall, park_exec, NULL, NULL, NULL);
05988    if (!res)
05989       res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
05990    if (!res) {
05991       ast_manager_register_xml("ParkedCalls", 0, manager_parking_status);
05992       ast_manager_register_xml("Park", EVENT_FLAG_CALL, manager_park);
05993       ast_manager_register_xml("Bridge", EVENT_FLAG_CALL, action_bridge);
05994    }
05995 
05996    res |= ast_devstate_prov_add("Park", metermaidstate);
05997 #ifdef TEST_FRAMEWORK
05998    res |= AST_TEST_REGISTER(features_test);
05999 #endif
06000 
06001    return res;
06002 }

Generated on Mon Jun 27 16:50:53 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7