Fri Nov 12 11:46:39 2010

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: 249933 $")
00029 
00030 #include "asterisk/_private.h"
00031 
00032 #include <pthread.h>
00033 #include <sys/time.h>
00034 #include <sys/signal.h>
00035 #include <netinet/in.h>
00036 
00037 #include "asterisk/lock.h"
00038 #include "asterisk/file.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/causes.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/translate.h"
00044 #include "asterisk/app.h"
00045 #include "asterisk/say.h"
00046 #include "asterisk/features.h"
00047 #include "asterisk/musiconhold.h"
00048 #include "asterisk/config.h"
00049 #include "asterisk/cli.h"
00050 #include "asterisk/manager.h"
00051 #include "asterisk/utils.h"
00052 #include "asterisk/adsi.h"
00053 #include "asterisk/devicestate.h"
00054 #include "asterisk/monitor.h"
00055 #include "asterisk/audiohook.h"
00056 #include "asterisk/global_datastores.h"
00057 #include "asterisk/astobj2.h"
00058 
00059 /*** DOCUMENTATION
00060    <application name="Bridge" language="en_US">
00061       <synopsis>
00062          Bridge two channels.
00063       </synopsis>
00064       <syntax>
00065          <parameter name="channel" required="true">
00066             <para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
00067          </parameter>
00068          <parameter name="options">
00069             <optionlist>
00070                <option name="p">
00071                   <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
00072                </option>
00073             </optionlist>
00074          </parameter>
00075       </syntax>
00076       <description>
00077          <para>Allows the ability to bridge two channels via the dialplan.</para>
00078          <para>This application sets the following channel variable upon completion:</para>
00079          <variablelist>
00080             <variable name="BRIDGERESULT">
00081                <para>The result of the bridge attempt as a text string.</para>
00082                <value name="SUCCESS" />
00083                <value name="FAILURE" />
00084                <value name="LOOP" />
00085                <value name="NONEXISTENT" />
00086                <value name="INCOMPATIBLE" />
00087             </variable>
00088          </variablelist>
00089       </description>
00090    </application>
00091    <application name="ParkedCall" language="en_US">
00092       <synopsis>
00093          Answer a parked call.
00094       </synopsis>
00095       <syntax>
00096          <parameter name="exten" required="true" />
00097       </syntax>
00098       <description>
00099          <para>Used to connect to a parked call. This application is always
00100          registered internally and does not need to be explicitly added
00101          into the dialplan, although you should include the <literal>parkedcalls</literal>
00102          context. If no extension is provided, then the first available
00103          parked call will be acquired.</para>
00104       </description>
00105       <see-also>
00106          <ref type="application">Park</ref>
00107          <ref type="application">ParkAndAnnounce</ref>
00108       </see-also>
00109    </application>
00110    <application name="Park" language="en_US">
00111       <synopsis>
00112          Park yourself.
00113       </synopsis>
00114       <syntax>
00115          <parameter name="timeout">
00116             <para>A custom parking timeout for this parked call.</para>
00117          </parameter>
00118          <parameter name="return_context">
00119             <para>The context to return the call to after it times out.</para>
00120          </parameter>
00121          <parameter name="return_exten">
00122             <para>The extension to return the call to after it times out.</para>
00123          </parameter>
00124          <parameter name="return_priority">
00125             <para>The priority to return the call to after it times out.</para>
00126          </parameter>
00127          <parameter name="options">
00128             <para>A list of options for this parked call.</para>
00129             <optionlist>
00130                <option name="r">
00131                   <para>Send ringing instead of MOH to the parked call.</para>
00132                </option>
00133                <option name="R">
00134                   <para>Randomize the selection of a parking space.</para>
00135                </option>
00136                <option name="s">
00137                   <para>Silence announcement of the parking space number.</para>
00138                </option>
00139             </optionlist>
00140          </parameter>
00141       </syntax>
00142       <description>
00143          <para>Used to park yourself (typically in combination with a supervised
00144          transfer to know the parking space). This application is always
00145          registered internally and does not need to be explicitly added
00146          into the dialplan, although you should include the <literal>parkedcalls</literal>
00147          context (or the context specified in <filename>features.conf</filename>).</para>
00148          <para>If you set the <variable>PARKINGLOT</variable> variable, the call will be parked
00149          in the specifed parking context. Note setting this variable overrides the <variable>
00150          PARKINGLOT</variable> set by the <literal>CHANNEL</literal> function.</para>
00151          <para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
00152          parking context, Park() will park the call on that extension, unless
00153          it already exists. In that case, execution will continue at next priority.</para>
00154       </description>
00155       <see-also>
00156          <ref type="application">ParkAndAnnounce</ref>
00157          <ref type="application">ParkedCall</ref>
00158       </see-also>
00159    </application>
00160  ***/
00161 
00162 #define DEFAULT_PARK_TIME 45000
00163 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
00164 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 1000
00165 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
00166 #define DEFAULT_PARKINGLOT "default"         /*!< Default parking lot */
00167 #define DEFAULT_ATXFER_DROP_CALL 0
00168 #define DEFAULT_ATXFER_LOOP_DELAY 10000
00169 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
00170 
00171 #define AST_MAX_WATCHERS 256
00172 #define MAX_DIAL_FEATURE_OPTIONS 30
00173 
00174 struct feature_group_exten {
00175    AST_LIST_ENTRY(feature_group_exten) entry;
00176    AST_DECLARE_STRING_FIELDS(
00177       AST_STRING_FIELD(exten);
00178    );
00179    struct ast_call_feature *feature;
00180 };
00181 
00182 struct feature_group {
00183    AST_LIST_ENTRY(feature_group) entry;
00184    AST_DECLARE_STRING_FIELDS(
00185       AST_STRING_FIELD(gname);
00186    );
00187    AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
00188 };
00189 
00190 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
00191 
00192 static char *parkedcall = "ParkedCall";
00193 
00194 static char pickup_ext[AST_MAX_EXTENSION];                 /*!< Call pickup extension */
00195 
00196 /*! \brief Description of one parked call, added to a list while active, then removed.
00197    The list belongs to a parkinglot 
00198 */
00199 struct parkeduser {
00200    struct ast_channel *chan;                   /*!< Parking channel */
00201    struct timeval start;                       /*!< Time the parking started */
00202    int parkingnum;                             /*!< Parking lot */
00203    char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
00204    char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
00205    char exten[AST_MAX_EXTENSION];
00206    int priority;
00207    int parkingtime;                            /*!< Maximum length in parking lot before return */
00208    unsigned int notquiteyet:1;
00209    unsigned int options_specified:1;
00210    char peername[1024];
00211    unsigned char moh_trys;
00212    struct ast_parkinglot *parkinglot;
00213    AST_LIST_ENTRY(parkeduser) list;
00214 };
00215 
00216 /*! \brief Structure for parking lots which are put in a container. */
00217 struct ast_parkinglot {
00218    char name[AST_MAX_CONTEXT];
00219    char parking_con[AST_MAX_EXTENSION];      /*!< Context for which parking is made accessible */
00220    char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
00221    int parking_start;            /*!< First available extension for parking */
00222    int parking_stop;          /*!< Last available extension for parking */
00223    int parking_offset;
00224    int parkfindnext;
00225    int parkingtime;           /*!< Default parking time */
00226    char mohclass[MAX_MUSICCLASS];                  /*!< Music class used for parking */
00227    int parkaddhints;                               /*!< Add parking hints automatically */
00228    int parkedcalltransfers;                        /*!< Enable DTMF based transfers on bridge when picking up parked calls */
00229    int parkedcallreparking;                        /*!< Enable DTMF based parking on bridge when picking up parked calls */
00230    int parkedcallhangup;                           /*!< Enable DTMF based hangup on a bridge when pickup up parked calls */
00231    int parkedcallrecording;                        /*!< Enable DTMF based recording on a bridge when picking up parked calls */
00232    AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings; /*!< List of active parkings in this parkinglot */
00233 };
00234 
00235 /*! \brief The list of parking lots configured. Always at least one  - the default parking lot */
00236 static struct ao2_container *parkinglots;
00237  
00238 struct ast_parkinglot *default_parkinglot;
00239 char parking_ext[AST_MAX_EXTENSION];            /*!< Extension you type to park the call */
00240 
00241 static char courtesytone[256];                             /*!< Courtesy tone */
00242 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
00243 static char xfersound[256];                                /*!< Call transfer sound */
00244 static char xferfailsound[256];                            /*!< Call transfer failure sound */
00245 static char pickupsound[256];                              /*!< Pickup sound */
00246 static char pickupfailsound[256];                          /*!< Pickup failure sound */
00247 
00248 static int adsipark;
00249 
00250 static int transferdigittimeout;
00251 static int featuredigittimeout;
00252 static int comebacktoorigin = 1;
00253 
00254 static int atxfernoanswertimeout;
00255 static unsigned int atxferdropcall;
00256 static unsigned int atxferloopdelay;
00257 static unsigned int atxfercallbackretries;
00258 
00259 static char *registrar = "features";         /*!< Registrar for operations */
00260 
00261 /* module and CLI command definitions */
00262 static char *parkcall = PARK_APP_NAME;
00263 
00264 static struct ast_app *monitor_app = NULL;
00265 static int monitor_ok = 1;
00266 
00267 static struct ast_app *mixmonitor_app = NULL;
00268 static int mixmonitor_ok = 1;
00269 
00270 static struct ast_app *stopmixmonitor_app = NULL;
00271 static int stopmixmonitor_ok = 1;
00272 
00273 static pthread_t parking_thread;
00274 struct ast_dial_features {
00275    struct ast_flags features_caller;
00276    struct ast_flags features_callee;
00277    int is_caller;
00278 };
00279 
00280 static void *dial_features_duplicate(void *data)
00281 {
00282    struct ast_dial_features *df = data, *df_copy;
00283  
00284    if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
00285       return NULL;
00286    }
00287  
00288    memcpy(df_copy, df, sizeof(*df));
00289  
00290    return df_copy;
00291  }
00292  
00293  static void dial_features_destroy(void *data)
00294  {
00295    struct ast_dial_features *df = data;
00296    if (df) {
00297       ast_free(df);
00298    }
00299  }
00300  
00301  const struct ast_datastore_info dial_features_info = {
00302    .type = "dial-features",
00303    .destroy = dial_features_destroy,
00304    .duplicate = dial_features_duplicate,
00305  };
00306  
00307 /* Forward declarations */
00308 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
00309 static void parkinglot_unref(struct ast_parkinglot *parkinglot);
00310 static void parkinglot_destroy(void *obj);
00311 int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
00312 struct ast_parkinglot *find_parkinglot(const char *name);
00313 
00314 
00315 const char *ast_parking_ext(void)
00316 {
00317    return parking_ext;
00318 }
00319 
00320 const char *ast_pickup_ext(void)
00321 {
00322    return pickup_ext;
00323 }
00324 
00325 struct ast_bridge_thread_obj 
00326 {
00327    struct ast_bridge_config bconfig;
00328    struct ast_channel *chan;
00329    struct ast_channel *peer;
00330    unsigned int return_to_pbx:1;
00331 };
00332 
00333 static int parkinglot_hash_cb(const void *obj, const int flags)
00334 {
00335    const struct ast_parkinglot *parkinglot = obj;
00336 
00337    return ast_str_case_hash(parkinglot->name);
00338 }
00339 
00340 static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
00341 {
00342    struct ast_parkinglot *parkinglot = obj, *parkinglot2 = arg;
00343 
00344    return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
00345 }
00346 
00347 /*!
00348  * \brief store context, extension and priority 
00349  * \param chan, context, ext, pri
00350 */
00351 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
00352 {
00353    ast_copy_string(chan->context, context, sizeof(chan->context));
00354    ast_copy_string(chan->exten, ext, sizeof(chan->exten));
00355    chan->priority = pri;
00356 }
00357 
00358 /*!
00359  * \brief Check goto on transfer
00360  * \param chan
00361  *
00362  * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
00363  * When found make sure the types are compatible. Check if channel is valid
00364  * if so start the new channel else hangup the call. 
00365 */
00366 static void check_goto_on_transfer(struct ast_channel *chan) 
00367 {
00368    struct ast_channel *xferchan;
00369    const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
00370    char *x, *goto_on_transfer;
00371    struct ast_frame *f;
00372 
00373    if (ast_strlen_zero(val))
00374       return;
00375 
00376    goto_on_transfer = ast_strdupa(val);
00377 
00378    if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", chan->name)))
00379       return;
00380 
00381    for (x = goto_on_transfer; x && *x; x++) {
00382       if (*x == '^')
00383          *x = '|';
00384    }
00385    /* Make formats okay */
00386    xferchan->readformat = chan->readformat;
00387    xferchan->writeformat = chan->writeformat;
00388    ast_channel_masquerade(xferchan, chan);
00389    ast_parseable_goto(xferchan, goto_on_transfer);
00390    xferchan->_state = AST_STATE_UP;
00391    ast_clear_flag(xferchan, AST_FLAGS_ALL);  
00392    xferchan->_softhangup = 0;
00393    if ((f = ast_read(xferchan))) {
00394       ast_frfree(f);
00395       f = NULL;
00396       ast_pbx_start(xferchan);
00397    } else {
00398       ast_hangup(xferchan);
00399    }
00400 }
00401 
00402 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language);
00403 
00404 /*!
00405  * \brief bridge the call 
00406  * \param data thread bridge.
00407  *
00408  * Set Last Data for respective channels, reset cdr for channels
00409  * bridge call, check if we're going back to dialplan
00410  * if not hangup both legs of the call
00411 */
00412 static void *bridge_call_thread(void *data)
00413 {
00414    struct ast_bridge_thread_obj *tobj = data;
00415    int res;
00416 
00417    tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
00418    tobj->chan->data = tobj->peer->name;
00419    tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
00420    tobj->peer->data = tobj->chan->name;
00421 
00422    ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
00423 
00424    if (tobj->return_to_pbx) {
00425       if (!ast_check_hangup(tobj->peer)) {
00426          ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
00427          res = ast_pbx_start(tobj->peer);
00428          if (res != AST_PBX_SUCCESS)
00429             ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
00430       } else
00431          ast_hangup(tobj->peer);
00432       if (!ast_check_hangup(tobj->chan)) {
00433          ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
00434          res = ast_pbx_start(tobj->chan);
00435          if (res != AST_PBX_SUCCESS)
00436             ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
00437       } else
00438          ast_hangup(tobj->chan);
00439    } else {
00440       ast_hangup(tobj->chan);
00441       ast_hangup(tobj->peer);
00442    }
00443 
00444    ast_free(tobj);
00445 
00446    return NULL;
00447 }
00448 
00449 /*!
00450  * \brief create thread for the parked call
00451  * \param data
00452  *
00453  * Create thread and attributes, call bridge_call_thread
00454 */
00455 static void bridge_call_thread_launch(void *data) 
00456 {
00457    pthread_t thread;
00458    pthread_attr_t attr;
00459    struct sched_param sched;
00460 
00461    pthread_attr_init(&attr);
00462    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00463    ast_pthread_create(&thread, &attr, bridge_call_thread, data);
00464    pthread_attr_destroy(&attr);
00465    memset(&sched, 0, sizeof(sched));
00466    pthread_setschedparam(thread, SCHED_RR, &sched);
00467 }
00468 
00469 /*!
00470  * \brief Announce call parking by ADSI
00471  * \param chan .
00472  * \param parkingexten .
00473  * Create message to show for ADSI, display message.
00474  * \retval 0 on success.
00475  * \retval -1 on failure.
00476 */
00477 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
00478 {
00479    int res;
00480    int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
00481    char tmp[256];
00482    char *message[5] = {NULL, NULL, NULL, NULL, NULL};
00483 
00484    snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
00485    message[0] = tmp;
00486    res = ast_adsi_load_session(chan, NULL, 0, 1);
00487    if (res == -1)
00488       return res;
00489    return ast_adsi_print(chan, message, justify, 1);
00490 }
00491 
00492 /*! \brief Find parking lot name from channel */
00493 static const char *findparkinglotname(struct ast_channel *chan)
00494 {
00495    const char *temp, *parkinglot = NULL;
00496 
00497    /* Check if the channel has a parking lot */
00498    if (!ast_strlen_zero(chan->parkinglot))
00499       parkinglot = chan->parkinglot;
00500 
00501    /* Channel variables override everything */
00502 
00503    if ((temp  = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
00504       return temp;
00505 
00506    return parkinglot;
00507 }
00508 
00509 /*! \brief Notify metermaids that we've changed an extension */
00510 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
00511 {
00512    ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'", 
00513       exten, context, ast_devstate2str(state));
00514 
00515    ast_devstate_changed(state, "park:%s@%s", exten, context);
00516 }
00517 
00518 /*! \brief metermaids callback from devicestate.c */
00519 static enum ast_device_state metermaidstate(const char *data)
00520 {
00521    char *context;
00522    char *exten;
00523 
00524    context = ast_strdupa(data);
00525 
00526    exten = strsep(&context, "@");
00527    if (!context)
00528       return AST_DEVICE_INVALID;
00529    
00530    ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
00531 
00532    if (!ast_exists_extension(NULL, context, exten, 1, NULL))
00533       return AST_DEVICE_NOT_INUSE;
00534 
00535    return AST_DEVICE_INUSE;
00536 }
00537 
00538 /*! Options to pass to park_call_full */
00539 enum ast_park_call_options {
00540    /*! Provide ringing to the parked caller instead of music on hold */
00541    AST_PARK_OPT_RINGING =   (1 << 0),
00542    /*! Randomly choose a parking spot for the caller instead of choosing
00543     *  the first one that is available. */
00544    AST_PARK_OPT_RANDOMIZE = (1 << 1),
00545    /*! Do not announce the parking number */
00546    AST_PARK_OPT_SILENCE = (1 << 2),
00547 };
00548 
00549 struct ast_park_call_args {
00550    /*! How long to wait in the parking lot before the call gets sent back
00551     *  to the specified return extension (or a best guess at where it came
00552     *  from if not explicitly specified). */
00553    int timeout;
00554    /*! An output parameter to store the parking space where the parked caller
00555     *  was placed. */
00556    int *extout;
00557    const char *orig_chan_name;
00558    const char *return_con;
00559    const char *return_ext;
00560    int return_pri;
00561    uint32_t flags;
00562    /*! Parked user that has already obtained a parking space */
00563    struct parkeduser *pu;
00564 };
00565 
00566 static struct parkeduser *park_space_reserve(struct ast_channel *chan,
00567  struct ast_channel *peer, struct ast_park_call_args *args)
00568 {
00569    struct parkeduser *pu;
00570    int i, parking_space = -1, parking_range;
00571    const char *parkinglotname = NULL;
00572    const char *parkingexten;
00573    struct ast_parkinglot *parkinglot = NULL;
00574    
00575    if (peer)
00576       parkinglotname = findparkinglotname(peer);
00577 
00578    if (parkinglotname) {
00579       if (option_debug)
00580          ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
00581       parkinglot = find_parkinglot(parkinglotname);   
00582    }
00583    if (!parkinglot) {
00584       parkinglot = parkinglot_addref(default_parkinglot);
00585    }
00586 
00587    if (option_debug)
00588       ast_log(LOG_DEBUG, "Parkinglot: %s\n", parkinglot->name);
00589 
00590    /* Allocate memory for parking data */
00591    if (!(pu = ast_calloc(1, sizeof(*pu)))) {
00592       parkinglot_unref(parkinglot);
00593       return NULL;
00594    }
00595 
00596    /* Lock parking list */
00597    AST_LIST_LOCK(&parkinglot->parkings);
00598    /* Check for channel variable PARKINGEXTEN */
00599    ast_channel_lock(chan);
00600    parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"), ""));
00601    ast_channel_unlock(chan);
00602    if (!ast_strlen_zero(parkingexten)) {
00603       /*!\note The API forces us to specify a numeric parking slot, even
00604        * though the architecture would tend to support non-numeric extensions
00605        * (as are possible with SIP, for example).  Hence, we enforce that
00606        * limitation here.  If extout was not numeric, we could permit
00607        * arbitrary non-numeric extensions.
00608        */
00609         if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space < 0) {
00610          AST_LIST_UNLOCK(&parkinglot->parkings);
00611          parkinglot_unref(parkinglot);
00612             free(pu);
00613             ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
00614             return NULL;
00615         }
00616         snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
00617 
00618       if (ast_exists_extension(NULL, parkinglot->parking_con, pu->parkingexten, 1, NULL)) {
00619          ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
00620          AST_LIST_UNLOCK(&parkinglot->parkings);
00621          parkinglot_unref(parkinglot);
00622          ast_free(pu);
00623          return NULL;
00624       }
00625    } else {
00626       int start;
00627       struct parkeduser *cur = NULL;
00628 
00629       /* Select parking space within range */
00630       parking_range = parkinglot->parking_stop - parkinglot->parking_start + 1;
00631 
00632       if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
00633          start = ast_random() % (parkinglot->parking_stop - parkinglot->parking_start + 1);
00634       } else {
00635          start = parkinglot->parking_start;
00636       }
00637 
00638       for (i = start; 1; i++) {
00639          if (i == parkinglot->parking_stop + 1) {
00640             i = parkinglot->parking_start - 1;
00641             break;
00642          }
00643 
00644          AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
00645             if (cur->parkingnum == i) {
00646                break;
00647             }
00648          }
00649          if (!cur) {
00650             parking_space = i;
00651             break;
00652          }
00653       }
00654 
00655       if (i == start - 1 && cur) {
00656          ast_log(LOG_WARNING, "No more parking spaces\n");
00657          ast_free(pu);
00658          AST_LIST_UNLOCK(&parkinglot->parkings);
00659          parkinglot_unref(parkinglot);
00660          return NULL;
00661       }
00662       /* Set pointer for next parking */
00663       if (parkinglot->parkfindnext) 
00664          parkinglot->parking_offset = parking_space - parkinglot->parking_start + 1;
00665       snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
00666    }
00667 
00668    pu->notquiteyet = 1;
00669    pu->parkingnum = parking_space;
00670    pu->parkinglot = parkinglot_addref(parkinglot);
00671    AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
00672    parkinglot_unref(parkinglot);
00673 
00674    return pu;
00675 }
00676 
00677 /* Park a call */
00678 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
00679 {
00680    struct ast_context *con;
00681    int parkingnum_copy;
00682    struct parkeduser *pu = args->pu;
00683    const char *event_from;
00684 
00685    if (pu == NULL)
00686       pu = park_space_reserve(chan, peer, args);
00687    if (pu == NULL)
00688       return 1; /* Continue execution if possible */
00689 
00690    snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", pu->parkingnum);
00691    
00692    chan->appl = "Parked Call";
00693    chan->data = NULL; 
00694 
00695    pu->chan = chan;
00696    
00697    /* Put the parked channel on hold if we have two different channels */
00698    if (chan != peer) {
00699       if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
00700          ast_indicate(pu->chan, AST_CONTROL_RINGING);
00701       } else {
00702          ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
00703             S_OR(pu->parkinglot->mohclass, NULL),
00704             !ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
00705       }
00706    }
00707    
00708    pu->start = ast_tvnow();
00709    pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->parkingtime;
00710    parkingnum_copy = pu->parkingnum;
00711    if (args->extout)
00712       *(args->extout) = pu->parkingnum;
00713 
00714    if (peer) { 
00715       /* This is so ugly that it hurts, but implementing get_base_channel() on local channels
00716          could have ugly side effects.  We could have transferer<->local,1<->local,2<->parking
00717          and we need the callback name to be that of transferer.  Since local,1/2 have the same
00718          name we can be tricky and just grab the bridged channel from the other side of the local
00719       */
00720       if (!strcasecmp(peer->tech->type, "Local")) {
00721          struct ast_channel *tmpchan, *base_peer;
00722          char other_side[AST_CHANNEL_NAME];
00723          char *c;
00724          ast_copy_string(other_side, S_OR(args->orig_chan_name, peer->name), sizeof(other_side));
00725          if ((c = strrchr(other_side, ';'))) {
00726             *++c = '1';
00727          }
00728          if ((tmpchan = ast_get_channel_by_name_locked(other_side))) {
00729             if ((base_peer = ast_bridged_channel(tmpchan))) {
00730                ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
00731             }
00732             ast_channel_unlock(tmpchan);
00733          }
00734       } else {
00735          ast_copy_string(pu->peername, S_OR(args->orig_chan_name, peer->name), sizeof(pu->peername));
00736       }
00737    }
00738 
00739    /* Remember what had been dialed, so that if the parking
00740       expires, we try to come back to the same place */
00741 
00742    pu->options_specified = (!ast_strlen_zero(args->return_con) || !ast_strlen_zero(args->return_ext) || args->return_pri);
00743 
00744    /* If extension has options specified, they override all other possibilities
00745    such as the returntoorigin flag and transferred context. Information on
00746    extension options is lost here, so we set a flag */
00747 
00748    ast_copy_string(pu->context, 
00749       S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)), 
00750       sizeof(pu->context));
00751    ast_copy_string(pu->exten, 
00752       S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)), 
00753       sizeof(pu->exten));
00754    pu->priority = args->return_pri ? args->return_pri : 
00755       (chan->macropriority ? chan->macropriority : chan->priority);
00756 
00757    /* If parking a channel directly, don't quiet yet get parking running on it.
00758     * All parking lot entries are put into the parking lot with notquiteyet on. */
00759    if (peer != chan) 
00760       pu->notquiteyet = 0;
00761 
00762    /* Wake up the (presumably select()ing) thread */
00763    pthread_kill(parking_thread, SIGURG);
00764    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));
00765 
00766    if (peer) {
00767       event_from = peer->name;
00768    } else {
00769       event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
00770    }
00771 
00772    manager_event(EVENT_FLAG_CALL, "ParkedCall",
00773       "Exten: %s\r\n"
00774       "Channel: %s\r\n"
00775       "Parkinglot: %s\r\n"
00776       "From: %s\r\n"
00777       "Timeout: %ld\r\n"
00778       "CallerIDNum: %s\r\n"
00779       "CallerIDName: %s\r\n"
00780       "Uniqueid: %s\r\n",
00781       pu->parkingexten, pu->chan->name, pu->parkinglot->name, event_from ? event_from : "",
00782       (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
00783       S_OR(pu->chan->cid.cid_num, "<unknown>"),
00784       S_OR(pu->chan->cid.cid_name, "<unknown>"),
00785       pu->chan->uniqueid
00786       );
00787 
00788    if (peer && adsipark && ast_adsi_available(peer)) {
00789       adsi_announce_park(peer, pu->parkingexten);  /* Only supports parking numbers */
00790       ast_adsi_unload_session(peer);
00791    }
00792 
00793    con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con, registrar);
00794    if (!con)   /* Still no context? Bad */
00795       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con);
00796    if (con) {
00797       if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
00798          notify_metermaids(pu->parkingexten, pu->parkinglot->parking_con, AST_DEVICE_INUSE);
00799    }
00800 
00801    AST_LIST_UNLOCK(&pu->parkinglot->parkings);
00802 
00803    /* Only say number if it's a number and the channel hasn't been masqueraded away */
00804    if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE) && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
00805       /* 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. */
00806       ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
00807       /* Tell the peer channel the number of the parking space */
00808       ast_say_digits(peer, pu->parkingnum, "", peer->language);
00809       ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
00810    }
00811    if (peer == chan) { /* pu->notquiteyet = 1 */
00812       /* Wake up parking thread if we're really done */
00813       ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
00814          S_OR(pu->parkinglot->mohclass, NULL),
00815          !ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
00816       pu->notquiteyet = 0;
00817       pthread_kill(parking_thread, SIGURG);
00818    }
00819    return 0;
00820 }
00821 
00822 /*! \brief Park a call */
00823 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
00824 {
00825    struct ast_park_call_args args = {
00826       .timeout = timeout,
00827       .extout = extout,
00828    };
00829 
00830    return park_call_full(chan, peer, &args);
00831 }
00832 
00833 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)
00834 {
00835    struct ast_channel *chan;
00836    struct ast_frame *f;
00837    int park_status;
00838    struct ast_park_call_args park_args = {0,};
00839 
00840    if (!args) {
00841       args = &park_args;
00842       args->timeout = timeout;
00843       args->extout = extout;
00844    }
00845 
00846    if ((args->pu = park_space_reserve(rchan, peer, args)) == NULL) {
00847       if (peer)
00848          ast_stream_and_wait(peer, "beeperr", "");
00849       return AST_FEATURE_RETURN_PARKFAILED;
00850    }
00851 
00852    /* Make a new, fake channel that we'll use to masquerade in the real one */
00853    if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
00854       ast_log(LOG_WARNING, "Unable to create parked channel\n");
00855       return -1;
00856    }
00857 
00858    /* Make formats okay */
00859    chan->readformat = rchan->readformat;
00860    chan->writeformat = rchan->writeformat;
00861    ast_channel_masquerade(chan, rchan);
00862 
00863    /* Setup the extensions and such */
00864    set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
00865 
00866    /* Setup the macro extension and such */
00867    ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
00868    ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
00869    chan->macropriority = rchan->macropriority;
00870 
00871    /* Make the masq execute */
00872    if ((f = ast_read(chan)))
00873       ast_frfree(f);
00874 
00875    if (peer == rchan) {
00876       peer = chan;
00877    }
00878 
00879    if (peer && (!play_announcement && args == &park_args)) {
00880       args->orig_chan_name = ast_strdupa(peer->name);
00881    }
00882 
00883    park_status = park_call_full(chan, peer, args);
00884    if (park_status == 1) {
00885    /* would be nice to play "invalid parking extension" */
00886       ast_hangup(chan);
00887       return -1;
00888    }
00889 
00890    return 0;
00891 }
00892 
00893 /* Park call via masquraded channel */
00894 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
00895 {
00896    return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
00897 }
00898 
00899 static int masq_park_call_announce_args(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
00900 {
00901    return masq_park_call(rchan, peer, 0, NULL, 1, args);
00902 }
00903 
00904 static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
00905 {
00906    return masq_park_call(rchan, peer, timeout, extout, 1, NULL);
00907 }
00908 
00909 #define FEATURE_SENSE_CHAN (1 << 0)
00910 #define FEATURE_SENSE_PEER (1 << 1)
00911 
00912 /*! 
00913  * \brief set caller and callee according to the direction 
00914  * \param caller, callee, peer, chan, sense
00915  *
00916  * Detect who triggered feature and set callee/caller variables accordingly
00917 */
00918 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
00919    struct ast_channel *peer, struct ast_channel *chan, int sense)
00920 {
00921    if (sense == FEATURE_SENSE_PEER) {
00922       *caller = peer;
00923       *callee = chan;
00924    } else {
00925       *callee = peer;
00926       *caller = chan;
00927    }
00928 }
00929 
00930 /*! 
00931  * \brief support routing for one touch call parking
00932  * \param chan channel parking call
00933  * \param peer channel to be parked
00934  * \param config unsed
00935  * \param code unused
00936  * \param sense feature options
00937  *
00938  * \param data
00939  * Setup channel, set return exten,priority to 's,1'
00940  * answer chan, sleep chan, park call
00941 */
00942 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00943 {
00944    struct ast_channel *parker;
00945    struct ast_channel *parkee;
00946    int res = 0;
00947 
00948    set_peers(&parker, &parkee, peer, chan, sense);
00949    /* we used to set chan's exten and priority to "s" and 1
00950       here, but this generates (in some cases) an invalid
00951       extension, and if "s" exists, could errantly
00952       cause execution of extensions you don't expect. It
00953       makes more sense to let nature take its course
00954       when chan finishes, and let the pbx do its thing
00955       and hang up when the park is over.
00956    */
00957    if (chan->_state != AST_STATE_UP)
00958       res = ast_answer(chan);
00959    if (!res)
00960       res = ast_safe_sleep(chan, 1000);
00961 
00962    if (!res) { /* one direction used to call park_call.... */
00963       res = masq_park_call_announce(parkee, parker, 0, NULL);
00964       /* PBX should hangup zombie channel if a masquerade actually occurred (res=0) */
00965    }
00966 
00967    return res;
00968 }
00969 
00970 /*! \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
00971    other channel during the message, so please don't use this for very long messages
00972  */
00973 static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
00974 {
00975    /* First play for caller, put other channel on auto service */
00976    if (ast_autoservice_start(callee_chan))
00977       return -1;
00978    if (ast_stream_and_wait(caller_chan, audiofile, "")) {
00979       ast_log(LOG_WARNING, "Failed to play automon message!\n");
00980       ast_autoservice_stop(callee_chan);
00981       return -1;
00982    }
00983    if (ast_autoservice_stop(callee_chan))
00984       return -1;
00985    /* Then play for callee, put other channel on auto service */
00986    if (ast_autoservice_start(caller_chan))
00987       return -1;
00988    if (ast_stream_and_wait(callee_chan, audiofile, "")) {
00989       ast_log(LOG_WARNING, "Failed to play automon message !\n");
00990       ast_autoservice_stop(caller_chan);
00991       return -1;
00992    }
00993    if (ast_autoservice_stop(caller_chan))
00994       return -1;
00995    return(0);
00996 }
00997 
00998 /*!
00999  * \brief Monitor a channel by DTMF
01000  * \param chan channel requesting monitor
01001  * \param peer channel to be monitored
01002  * \param config
01003  * \param code
01004  * \param sense feature options
01005  *
01006  * \param data
01007  * Check monitor app enabled, setup channels, both caller/callee chans not null
01008  * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
01009  * \retval AST_FEATURE_RETURN_SUCCESS on success.
01010  * \retval -1 on error.
01011 */
01012 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01013 {
01014    char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
01015    int x = 0;
01016    size_t len;
01017    struct ast_channel *caller_chan, *callee_chan;
01018    const char *automon_message_start = NULL;
01019    const char *automon_message_stop = NULL;
01020 
01021    if (!monitor_ok) {
01022       ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
01023       return -1;
01024    }
01025 
01026    if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
01027       monitor_ok = 0;
01028       ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
01029       return -1;
01030    }
01031 
01032    set_peers(&caller_chan, &callee_chan, peer, chan, sense);
01033    if (caller_chan) {   /* Find extra messages */
01034       automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
01035       automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
01036    }
01037 
01038    if (!ast_strlen_zero(courtesytone)) {  /* Play courtesy tone if configured */
01039       if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
01040          return -1;
01041       }
01042    }
01043    
01044    if (callee_chan->monitor) {
01045       ast_verb(4, "User hit '%s' to stop recording call.\n", code);
01046       if (!ast_strlen_zero(automon_message_stop)) {
01047          play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
01048       }
01049       callee_chan->monitor->stop(callee_chan, 1);
01050       return AST_FEATURE_RETURN_SUCCESS;
01051    }
01052 
01053    if (caller_chan && callee_chan) {
01054       const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
01055       const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
01056       const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
01057 
01058       if (!touch_format)
01059          touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
01060 
01061       if (!touch_monitor)
01062          touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
01063    
01064       if (!touch_monitor_prefix)
01065          touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
01066    
01067       if (touch_monitor) {
01068          len = strlen(touch_monitor) + 50;
01069          args = alloca(len);
01070          touch_filename = alloca(len);
01071          snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
01072          snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
01073       } else {
01074          caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
01075          callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
01076          len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
01077          args = alloca(len);
01078          touch_filename = alloca(len);
01079          snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
01080          snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
01081       }
01082 
01083       for(x = 0; x < strlen(args); x++) {
01084          if (args[x] == '/')
01085             args[x] = '-';
01086       }
01087       
01088       ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
01089 
01090       pbx_exec(callee_chan, monitor_app, args);
01091       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
01092       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
01093 
01094       if (!ast_strlen_zero(automon_message_start)) {  /* Play start message for both channels */
01095          play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
01096       }
01097    
01098       return AST_FEATURE_RETURN_SUCCESS;
01099    }
01100    
01101    ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");  
01102    return -1;
01103 }
01104 
01105 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01106 {
01107    char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
01108    int x = 0;
01109    size_t len;
01110    struct ast_channel *caller_chan, *callee_chan;
01111    const char *mixmonitor_spy_type = "MixMonitor";
01112    int count = 0;
01113 
01114    if (!mixmonitor_ok) {
01115       ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
01116       return -1;
01117    }
01118 
01119    if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
01120       mixmonitor_ok = 0;
01121       ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
01122       return -1;
01123    }
01124 
01125    set_peers(&caller_chan, &callee_chan, peer, chan, sense);
01126 
01127    if (!ast_strlen_zero(courtesytone)) {
01128       if (ast_autoservice_start(callee_chan))
01129          return -1;
01130       if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
01131          ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
01132          ast_autoservice_stop(callee_chan);
01133          return -1;
01134       }
01135       if (ast_autoservice_stop(callee_chan))
01136          return -1;
01137    }
01138 
01139    ast_channel_lock(callee_chan);
01140    count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
01141    ast_channel_unlock(callee_chan);
01142 
01143    /* This means a mixmonitor is attached to the channel, running or not is unknown. */
01144    if (count > 0) {
01145       
01146       ast_verb(3, "User hit '%s' to stop recording call.\n", code);
01147 
01148       /* Make sure they are running */
01149       ast_channel_lock(callee_chan);
01150       count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
01151       ast_channel_unlock(callee_chan);
01152       if (count > 0) {
01153          if (!stopmixmonitor_ok) {
01154             ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
01155             return -1;
01156          }
01157          if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
01158             stopmixmonitor_ok = 0;
01159             ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
01160             return -1;
01161          } else {
01162             pbx_exec(callee_chan, stopmixmonitor_app, "");
01163             return AST_FEATURE_RETURN_SUCCESS;
01164          }
01165       }
01166       
01167       ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n"); 
01168    }        
01169 
01170    if (caller_chan && callee_chan) {
01171       const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
01172       const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
01173 
01174       if (!touch_format)
01175          touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
01176 
01177       if (!touch_monitor)
01178          touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
01179 
01180       if (touch_monitor) {
01181          len = strlen(touch_monitor) + 50;
01182          args = alloca(len);
01183          touch_filename = alloca(len);
01184          snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
01185          snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
01186       } else {
01187          caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
01188          callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
01189          len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
01190          args = alloca(len);
01191          touch_filename = alloca(len);
01192          snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
01193          snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
01194       }
01195 
01196       for( x = 0; x < strlen(args); x++) {
01197          if (args[x] == '/')
01198             args[x] = '-';
01199       }
01200 
01201       ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
01202 
01203       pbx_exec(callee_chan, mixmonitor_app, args);
01204       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
01205       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
01206       return AST_FEATURE_RETURN_SUCCESS;
01207    
01208    }
01209 
01210    ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
01211    return -1;
01212 
01213 }
01214 
01215 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01216 {
01217    ast_verb(4, "User hit '%s' to disconnect call.\n", code);
01218    return AST_FEATURE_RETURN_HANGUP;
01219 }
01220 
01221 static int finishup(struct ast_channel *chan)
01222 {
01223    ast_indicate(chan, AST_CONTROL_UNHOLD);
01224 
01225    return ast_autoservice_stop(chan);
01226 }
01227 
01228 /*!
01229  * \brief Find the context for the transfer
01230  * \param transferer
01231  * \param transferee
01232  * 
01233  * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
01234  * \return a context string
01235 */
01236 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
01237 {
01238    const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
01239    if (ast_strlen_zero(s)) {
01240       s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
01241    }
01242    if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
01243       s = transferer->macrocontext;
01244    }
01245    if (ast_strlen_zero(s)) {
01246       s = transferer->context;
01247    }
01248    return s;  
01249 }
01250 
01251 /*!
01252  * \brief Blind transfer user to another extension
01253  * \param chan channel to be transfered
01254  * \param peer channel initiated blind transfer
01255  * \param config
01256  * \param code
01257  * \param data
01258  * \param sense  feature options
01259  * 
01260  * Place chan on hold, check if transferred to parkinglot extension,
01261  * otherwise check extension exists and transfer caller.
01262  * \retval AST_FEATURE_RETURN_SUCCESS.
01263  * \retval -1 on failure.
01264 */
01265 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01266 {
01267    struct ast_channel *transferer;
01268    struct ast_channel *transferee;
01269    const char *transferer_real_context;
01270    char xferto[256];
01271    int res, parkstatus = 0;
01272 
01273    set_peers(&transferer, &transferee, peer, chan, sense);
01274    transferer_real_context = real_ctx(transferer, transferee);
01275    /* Start autoservice on chan while we talk to the originator */
01276    ast_autoservice_start(transferee);
01277    ast_indicate(transferee, AST_CONTROL_HOLD);
01278 
01279    memset(xferto, 0, sizeof(xferto));
01280 
01281    /* Transfer */
01282    res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
01283    if (res < 0) {
01284       finishup(transferee);
01285       return -1; /* error ? */
01286    }
01287    if (res > 0)   /* If they've typed a digit already, handle it */
01288       xferto[0] = (char) res;
01289 
01290    ast_stopstream(transferer);
01291    res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
01292    if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
01293       finishup(transferee);
01294       return res;
01295    }
01296    if (!strcmp(xferto, ast_parking_ext())) {
01297       res = finishup(transferee);
01298       if (res)
01299          res = -1;
01300       else if (!(parkstatus = masq_park_call_announce(transferee, transferer, 0, NULL))) {   /* success */
01301          /* We return non-zero, but tell the PBX not to hang the channel when
01302             the thread dies -- We have to be careful now though.  We are responsible for 
01303             hanging up the channel, else it will never be hung up! */
01304 
01305          return 0;
01306       } else {
01307          ast_log(LOG_WARNING, "Unable to park call %s, parkstatus = %d\n", transferee->name, parkstatus);
01308       }
01309       /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
01310    } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
01311       pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
01312       pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
01313       res=finishup(transferee);
01314       if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
01315          transferer->cdr=ast_cdr_alloc();
01316          if (transferer->cdr) {
01317             ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
01318             ast_cdr_start(transferer->cdr);
01319          }
01320       }
01321       if (transferer->cdr) {
01322          struct ast_cdr *swap = transferer->cdr;
01323          ast_log(LOG_DEBUG,"transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
01324                transferer->name, transferee->name, transferer->cdr->lastapp, transferer->cdr->lastdata, 
01325                transferer->cdr->channel, transferer->cdr->dstchannel);
01326          ast_log(LOG_DEBUG,"TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
01327                transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel, transferee->cdr->dstchannel);
01328          ast_log(LOG_DEBUG,"transferer_real_context=%s; xferto=%s\n", transferer_real_context, xferto);
01329          /* swap cdrs-- it will save us some time & work */
01330          transferer->cdr = transferee->cdr;
01331          transferee->cdr = swap;
01332       }
01333       if (!transferee->pbx) {
01334          /* Doh!  Use our handy async_goto functions */
01335          ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
01336                         ,transferee->name, xferto, transferer_real_context);
01337          if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
01338             ast_log(LOG_WARNING, "Async goto failed :-(\n");
01339       } else {
01340          /* Set the channel's new extension, since it exists, using transferer context */
01341          ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
01342          ast_log(LOG_DEBUG,"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
01343          set_c_e_p(transferee, transferer_real_context, xferto, 0);
01344       }
01345       check_goto_on_transfer(transferer);
01346       return res;
01347    } else {
01348       ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
01349    }
01350    if (parkstatus != AST_FEATURE_RETURN_PARKFAILED && ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
01351       finishup(transferee);
01352       return -1;
01353    }
01354    ast_stopstream(transferer);
01355    res = finishup(transferee);
01356    if (res) {
01357       ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
01358       return res;
01359    }
01360    return AST_FEATURE_RETURN_SUCCESS;
01361 }
01362 
01363 /*!
01364  * \brief make channels compatible
01365  * \param c
01366  * \param newchan
01367  * \retval 0 on success.
01368  * \retval -1 on failure.
01369 */
01370 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
01371 {
01372    if (ast_channel_make_compatible(c, newchan) < 0) {
01373       ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
01374          c->name, newchan->name);
01375       ast_hangup(newchan);
01376       return -1;
01377    }
01378    return 0;
01379 }
01380 
01381 /*!
01382  * \brief Attended transfer
01383  * \param chan transfered user
01384  * \param peer person transfering call
01385  * \param config
01386  * \param code
01387  * \param sense feature options
01388  * 
01389  * \param data
01390  * Get extension to transfer to, if you cannot generate channel (or find extension) 
01391  * return to host channel. After called channel answered wait for hangup of transferer,
01392  * bridge call between transfer peer (taking them off hold) to attended transfer channel.
01393  *
01394  * \return -1 on failure
01395 */
01396 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01397 {
01398    struct ast_channel *transferer;
01399    struct ast_channel *transferee;
01400    const char *transferer_real_context;
01401    char xferto[256] = "";
01402    int res;
01403    int outstate=0;
01404    struct ast_channel *newchan;
01405    struct ast_channel *xferchan;
01406    struct ast_bridge_thread_obj *tobj;
01407    struct ast_bridge_config bconfig;
01408    struct ast_frame *f;
01409    int l;
01410    struct ast_datastore *features_datastore;
01411    struct ast_dial_features *dialfeatures = NULL;
01412 
01413    ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
01414    set_peers(&transferer, &transferee, peer, chan, sense);
01415    transferer_real_context = real_ctx(transferer, transferee);
01416    /* Start autoservice on chan while we talk to the originator */
01417    ast_autoservice_start(transferee);
01418    ast_indicate(transferee, AST_CONTROL_HOLD);
01419    
01420    /* Transfer */
01421    res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
01422    if (res < 0) {
01423       finishup(transferee);
01424       return res;
01425    }
01426    if (res > 0) /* If they've typed a digit already, handle it */
01427       xferto[0] = (char) res;
01428 
01429    /* this is specific of atxfer */
01430    res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
01431    if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
01432       finishup(transferee);
01433       return res;
01434    }
01435    if (res == 0) {
01436       ast_log(LOG_WARNING, "Did not read data.\n");
01437       finishup(transferee);
01438       if (ast_stream_and_wait(transferer, "beeperr", ""))
01439          return -1;
01440       return AST_FEATURE_RETURN_SUCCESS;
01441    }
01442 
01443    /* valid extension, res == 1 */
01444    if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
01445       ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
01446       finishup(transferee);
01447       if (ast_stream_and_wait(transferer, "beeperr", ""))
01448          return -1;
01449       return AST_FEATURE_RETURN_SUCCESS;
01450    }
01451 
01452    /* If we are attended transfering to parking, just use builtin_parkcall instead of trying to track all of
01453     * the different variables for handling this properly with a builtin_atxfer */
01454    if (!strcmp(xferto, ast_parking_ext())) {
01455       finishup(transferee);
01456       return builtin_parkcall(chan, peer, config, code, sense, data);
01457    }
01458 
01459    l = strlen(xferto);
01460    snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);   /* append context */
01461 
01462    /* If we are performing an attended transfer and we have two channels involved then
01463       copy sound file information to play upon attended transfer completion */
01464    if (transferee) {
01465       const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
01466       const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
01467 
01468       if (!ast_strlen_zero(chan1_attended_sound)) {
01469          pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
01470       }
01471       if (!ast_strlen_zero(chan2_attended_sound)) {
01472          pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
01473       }
01474    }
01475 
01476    newchan = feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
01477       xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
01478 
01479    if (!ast_check_hangup(transferer)) {
01480       /* Transferer is up - old behaviour */
01481       ast_indicate(transferer, -1);
01482       if (!newchan) {
01483          finishup(transferee);
01484          /* any reason besides user requested cancel and busy triggers the failed sound */
01485          if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
01486             ast_stream_and_wait(transferer, xferfailsound, ""))
01487             return -1;
01488          if (ast_stream_and_wait(transferer, xfersound, ""))
01489             ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
01490          return AST_FEATURE_RETURN_SUCCESS;
01491       }
01492 
01493       if (check_compat(transferer, newchan)) {
01494          /* we do mean transferee here, NOT transferer */
01495          finishup(transferee);
01496          return -1;
01497       }
01498       memset(&bconfig,0,sizeof(struct ast_bridge_config));
01499       ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
01500       ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
01501       res = ast_bridge_call(transferer, newchan, &bconfig);
01502       if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
01503          ast_hangup(newchan);
01504          if (ast_stream_and_wait(transferer, xfersound, ""))
01505             ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
01506          finishup(transferee);
01507          transferer->_softhangup = 0;
01508          return AST_FEATURE_RETURN_SUCCESS;
01509       }
01510       if (check_compat(transferee, newchan)) {
01511          finishup(transferee);
01512          return -1;
01513       }
01514       ast_indicate(transferee, AST_CONTROL_UNHOLD);
01515 
01516       if ((ast_autoservice_stop(transferee) < 0)
01517        || (ast_waitfordigit(transferee, 100) < 0)
01518        || (ast_waitfordigit(newchan, 100) < 0)
01519        || ast_check_hangup(transferee)
01520        || ast_check_hangup(newchan)) {
01521          ast_hangup(newchan);
01522          return -1;
01523       }
01524       xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
01525       if (!xferchan) {
01526          ast_hangup(newchan);
01527          return -1;
01528       }
01529       /* Make formats okay */
01530       xferchan->visible_indication = transferer->visible_indication;
01531       xferchan->readformat = transferee->readformat;
01532       xferchan->writeformat = transferee->writeformat;
01533       ast_channel_masquerade(xferchan, transferee);
01534       ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
01535       xferchan->_state = AST_STATE_UP;
01536       ast_clear_flag(xferchan, AST_FLAGS_ALL);
01537       xferchan->_softhangup = 0;
01538       if ((f = ast_read(xferchan)))
01539          ast_frfree(f);
01540       newchan->_state = AST_STATE_UP;
01541       ast_clear_flag(newchan, AST_FLAGS_ALL);
01542       newchan->_softhangup = 0;
01543       if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
01544          ast_hangup(xferchan);
01545          ast_hangup(newchan);
01546          return -1;
01547       }
01548 
01549       ast_channel_lock(newchan);
01550       if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
01551             dialfeatures = features_datastore->data;
01552       }
01553       ast_channel_unlock(newchan);
01554 
01555       if (dialfeatures) {
01556          /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
01557             I don't currently understand, the abilities of newchan seem to be stored on the caller side */
01558          ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
01559          dialfeatures = NULL;
01560       }
01561 
01562       ast_channel_lock(xferchan);
01563       if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
01564          dialfeatures = features_datastore->data;
01565       }
01566       ast_channel_unlock(xferchan);
01567     
01568       if (dialfeatures) {
01569          ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
01570       }
01571     
01572       tobj->chan = newchan;
01573       tobj->peer = xferchan;
01574       tobj->bconfig = *config;
01575 
01576       if (tobj->bconfig.end_bridge_callback_data_fixup) {
01577          tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
01578       }
01579 
01580       if (ast_stream_and_wait(newchan, xfersound, ""))
01581          ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
01582       bridge_call_thread_launch(tobj);
01583       return -1;      /* XXX meaning the channel is bridged ? */
01584    } else if (!ast_check_hangup(transferee)) {
01585       /* act as blind transfer */
01586       if (ast_autoservice_stop(transferee) < 0) {
01587          ast_hangup(newchan);
01588          return -1;
01589       }
01590 
01591       if (!newchan) {
01592          unsigned int tries = 0;
01593          char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
01594 
01595          transferer_tech = strsep(&transferer_name, "/");
01596          transferer_name = strsep(&transferer_name, "-");
01597 
01598          if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
01599             ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
01600             if (ast_stream_and_wait(transferee, "beeperr", ""))
01601                return -1;
01602             return AST_FEATURE_RETURN_SUCCESS;
01603          }
01604 
01605          ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
01606          newchan = feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
01607             transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
01608          while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
01609             /* Trying to transfer again */
01610             ast_autoservice_start(transferee);
01611             ast_indicate(transferee, AST_CONTROL_HOLD);
01612 
01613             newchan = feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
01614                xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
01615             if (ast_autoservice_stop(transferee) < 0) {
01616                if (newchan)
01617                   ast_hangup(newchan);
01618                return -1;
01619             }
01620             if (!newchan) {
01621                /* Transfer failed, sleeping */
01622                ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
01623                ast_safe_sleep(transferee, atxferloopdelay);
01624                ast_debug(1, "Trying to callback...\n");
01625                newchan = feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
01626                   transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
01627             }
01628             tries++;
01629          }
01630       }
01631       if (!newchan)
01632          return -1;
01633 
01634       /* newchan is up, we should prepare transferee and bridge them */
01635       if (check_compat(transferee, newchan)) {
01636          finishup(transferee);
01637          return -1;
01638       }
01639       ast_indicate(transferee, AST_CONTROL_UNHOLD);
01640 
01641       if ((ast_waitfordigit(transferee, 100) < 0)
01642          || (ast_waitfordigit(newchan, 100) < 0)
01643          || ast_check_hangup(transferee)
01644          || ast_check_hangup(newchan)) {
01645          ast_hangup(newchan);
01646          return -1;
01647       }
01648 
01649       xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
01650       if (!xferchan) {
01651          ast_hangup(newchan);
01652          return -1;
01653       }
01654       /* Make formats okay */
01655       xferchan->visible_indication = transferer->visible_indication;
01656       xferchan->readformat = transferee->readformat;
01657       xferchan->writeformat = transferee->writeformat;
01658       ast_channel_masquerade(xferchan, transferee);
01659       ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
01660       xferchan->_state = AST_STATE_UP;
01661       ast_clear_flag(xferchan, AST_FLAGS_ALL);
01662       xferchan->_softhangup = 0;
01663       if ((f = ast_read(xferchan)))
01664          ast_frfree(f);
01665       newchan->_state = AST_STATE_UP;
01666       ast_clear_flag(newchan, AST_FLAGS_ALL);
01667       newchan->_softhangup = 0;
01668       if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
01669          ast_hangup(xferchan);
01670          ast_hangup(newchan);
01671          return -1;
01672       }
01673       tobj->chan = newchan;
01674       tobj->peer = xferchan;
01675       tobj->bconfig = *config;
01676 
01677       if (tobj->bconfig.end_bridge_callback_data_fixup) {
01678          tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
01679       }
01680 
01681       if (ast_stream_and_wait(newchan, xfersound, ""))
01682          ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
01683       bridge_call_thread_launch(tobj);
01684       return -1;      /* XXX meaning the channel is bridged ? */
01685    } else {
01686       /* Transferee hung up */
01687       finishup(transferee);
01688       return -1;
01689    }
01690 }
01691 
01692 /* add atxfer and automon as undefined so you can only use em if you configure them */
01693 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
01694 
01695 AST_RWLOCK_DEFINE_STATIC(features_lock);
01696 
01697 static struct ast_call_feature builtin_features[] = 
01698 {
01699    { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01700    { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01701    { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01702    { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01703    { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01704    { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01705 };
01706 
01707 
01708 static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
01709 
01710 /*! \brief register new feature into feature_list*/
01711 void ast_register_feature(struct ast_call_feature *feature)
01712 {
01713    if (!feature) {
01714       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
01715       return;
01716    }
01717   
01718    AST_RWLIST_WRLOCK(&feature_list);
01719    AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
01720    AST_RWLIST_UNLOCK(&feature_list);
01721 
01722    ast_verb(2, "Registered Feature '%s'\n",feature->sname);
01723 }
01724 
01725 /*! 
01726  * \brief Add new feature group
01727  * \param fgname feature group name.
01728  *
01729  * Add new feature group to the feature group list insert at head of list.
01730  * \note This function MUST be called while feature_groups is locked.
01731 */
01732 static struct feature_group* register_group(const char *fgname)
01733 {
01734    struct feature_group *fg;
01735 
01736    if (!fgname) {
01737       ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
01738       return NULL;
01739    }
01740 
01741    if (!(fg = ast_calloc(1, sizeof(*fg))))
01742       return NULL;
01743 
01744    if (ast_string_field_init(fg, 128)) {
01745       ast_free(fg);
01746       return NULL;
01747    }
01748 
01749    ast_string_field_set(fg, gname, fgname);
01750 
01751    AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
01752 
01753    ast_verb(2, "Registered group '%s'\n", fg->gname);
01754 
01755    return fg;
01756 }
01757 
01758 /*! 
01759  * \brief Add feature to group
01760  * \param fg feature group
01761  * \param exten
01762  * \param feature feature to add.
01763  *
01764  * Check fg and feature specified, add feature to list
01765  * \note This function MUST be called while feature_groups is locked. 
01766 */
01767 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature) 
01768 {
01769    struct feature_group_exten *fge;
01770 
01771    if (!fg) {
01772       ast_log(LOG_NOTICE, "You didn't pass a group!\n");
01773       return;
01774    }
01775 
01776    if (!feature) {
01777       ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
01778       return;
01779    }
01780 
01781    if (!(fge = ast_calloc(1, sizeof(*fge))))
01782       return;
01783 
01784    if (ast_string_field_init(fge, 128)) {
01785       ast_free(fge);
01786       return;
01787    }
01788 
01789    ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
01790 
01791    fge->feature = feature;
01792 
01793    AST_LIST_INSERT_HEAD(&fg->features, fge, entry);      
01794 
01795    ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
01796                feature->sname, fg->gname, exten);
01797 }
01798 
01799 void ast_unregister_feature(struct ast_call_feature *feature)
01800 {
01801    if (!feature) {
01802       return;
01803    }
01804 
01805    AST_RWLIST_WRLOCK(&feature_list);
01806    AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
01807    AST_RWLIST_UNLOCK(&feature_list);
01808 
01809    ast_free(feature);
01810 }
01811 
01812 /*! \brief Remove all features in the list */
01813 static void ast_unregister_features(void)
01814 {
01815    struct ast_call_feature *feature;
01816 
01817    AST_RWLIST_WRLOCK(&feature_list);
01818    while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
01819       ast_free(feature);
01820    }
01821    AST_RWLIST_UNLOCK(&feature_list);
01822 }
01823 
01824 /*! \brief find a call feature by name */
01825 static struct ast_call_feature *find_dynamic_feature(const char *name)
01826 {
01827    struct ast_call_feature *tmp;
01828 
01829    AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
01830       if (!strcasecmp(tmp->sname, name)) {
01831          break;
01832       }
01833    }
01834 
01835    return tmp;
01836 }
01837 
01838 /*! \brief Remove all feature groups in the list */
01839 static void ast_unregister_groups(void)
01840 {
01841    struct feature_group *fg;
01842    struct feature_group_exten *fge;
01843 
01844    AST_RWLIST_WRLOCK(&feature_groups);
01845    while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
01846       while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
01847          ast_string_field_free_memory(fge);
01848          ast_free(fge);
01849       }
01850 
01851       ast_string_field_free_memory(fg);
01852       ast_free(fg);
01853    }
01854    AST_RWLIST_UNLOCK(&feature_groups);
01855 }
01856 
01857 /*! 
01858  * \brief Find a group by name 
01859  * \param name feature name
01860  * \retval feature group on success.
01861  * \retval NULL on failure.
01862 */
01863 static struct feature_group *find_group(const char *name) {
01864    struct feature_group *fg = NULL;
01865 
01866    AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
01867       if (!strcasecmp(fg->gname, name))
01868          break;
01869    }
01870 
01871    return fg;
01872 }
01873 
01874 void ast_rdlock_call_features(void)
01875 {
01876    ast_rwlock_rdlock(&features_lock);
01877 }
01878 
01879 void ast_unlock_call_features(void)
01880 {
01881    ast_rwlock_unlock(&features_lock);
01882 }
01883 
01884 struct ast_call_feature *ast_find_call_feature(const char *name)
01885 {
01886    int x;
01887    for (x = 0; x < FEATURES_COUNT; x++) {
01888       if (!strcasecmp(name, builtin_features[x].sname))
01889          return &builtin_features[x];
01890    }
01891    return NULL;
01892 }
01893 
01894 /*!
01895  * \brief exec an app by feature 
01896  * \param chan,peer,config,code,sense,data
01897  *
01898  * Find a feature, determine which channel activated
01899  * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
01900  * \retval -1 error.
01901  * \retval -2 when an application cannot be found.
01902 */
01903 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01904 {
01905    struct ast_app *app;
01906    struct ast_call_feature *feature = data;
01907    struct ast_channel *work, *idle;
01908    int res;
01909 
01910    if (!feature) { /* shouldn't ever happen! */
01911       ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
01912       return -1; 
01913    }
01914 
01915    if (sense == FEATURE_SENSE_CHAN) {
01916       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
01917          return AST_FEATURE_RETURN_KEEPTRYING;
01918       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
01919          work = chan;
01920          idle = peer;
01921       } else {
01922          work = peer;
01923          idle = chan;
01924       }
01925    } else {
01926       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
01927          return AST_FEATURE_RETURN_KEEPTRYING;
01928       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
01929          work = peer;
01930          idle = chan;
01931       } else {
01932          work = chan;
01933          idle = peer;
01934       }
01935    }
01936 
01937    if (!(app = pbx_findapp(feature->app))) {
01938       ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
01939       return -2;
01940    }
01941 
01942    ast_autoservice_start(idle);
01943    
01944    if (!ast_strlen_zero(feature->moh_class))
01945       ast_moh_start(idle, feature->moh_class, NULL);
01946 
01947    res = pbx_exec(work, app, feature->app_args);
01948 
01949    if (!ast_strlen_zero(feature->moh_class))
01950       ast_moh_stop(idle);
01951 
01952    ast_autoservice_stop(idle);
01953 
01954    if (res) {
01955       return AST_FEATURE_RETURN_SUCCESSBREAK;
01956    }
01957    return AST_FEATURE_RETURN_SUCCESS;  /*! \todo XXX should probably return res */
01958 }
01959 
01960 static void unmap_features(void)
01961 {
01962    int x;
01963 
01964    ast_rwlock_wrlock(&features_lock);
01965    for (x = 0; x < FEATURES_COUNT; x++)
01966       strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
01967    ast_rwlock_unlock(&features_lock);
01968 }
01969 
01970 static int remap_feature(const char *name, const char *value)
01971 {
01972    int x, res = -1;
01973 
01974    ast_rwlock_wrlock(&features_lock);
01975    for (x = 0; x < FEATURES_COUNT; x++) {
01976       if (strcasecmp(builtin_features[x].sname, name))
01977          continue;
01978 
01979       ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
01980       res = 0;
01981       break;
01982    }
01983    ast_rwlock_unlock(&features_lock);
01984 
01985    return res;
01986 }
01987 
01988 /*!
01989  * \brief Check the dynamic features
01990  * \param chan,peer,config,code,sense
01991  *
01992  * Lock features list, browse for code, unlock list
01993  * \retval res on success.
01994  * \retval -1 on failure.
01995 */
01996 static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
01997 {
01998    int x;
01999    struct ast_flags features;
02000    struct ast_call_feature *feature;
02001    struct feature_group *fg = NULL;
02002    struct feature_group_exten *fge;
02003    const char *peer_dynamic_features, *chan_dynamic_features;
02004    char dynamic_features_buf[128];
02005    char *tmp, *tok;
02006    int res = AST_FEATURE_RETURN_PASSDIGITS;
02007    int feature_detected = 0;
02008 
02009    if (sense == FEATURE_SENSE_CHAN) {
02010       ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
02011    }
02012    else {
02013       ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
02014    }
02015 
02016    ast_channel_lock(peer);
02017    peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
02018    ast_channel_unlock(peer);
02019 
02020    ast_channel_lock(chan);
02021    chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
02022    ast_channel_unlock(chan);
02023 
02024    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,""));
02025 
02026    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);
02027 
02028    ast_rwlock_rdlock(&features_lock);
02029    for (x = 0; x < FEATURES_COUNT; x++) {
02030       if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
02031           !ast_strlen_zero(builtin_features[x].exten)) {
02032          /* Feature is up for consideration */
02033          if (!strcmp(builtin_features[x].exten, code)) {
02034             ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
02035             res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
02036             feature_detected = 1;
02037             break;
02038          } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
02039             if (res == AST_FEATURE_RETURN_PASSDIGITS)
02040                res = AST_FEATURE_RETURN_STOREDIGITS;
02041          }
02042       }
02043    }
02044    ast_rwlock_unlock(&features_lock);
02045 
02046    if (ast_strlen_zero(dynamic_features_buf) || feature_detected)
02047       return res;
02048 
02049    tmp = dynamic_features_buf;
02050 
02051    while ((tok = strsep(&tmp, "#"))) {
02052       AST_RWLIST_RDLOCK(&feature_groups);
02053 
02054       fg = find_group(tok);
02055 
02056       if (fg) {
02057          AST_LIST_TRAVERSE(&fg->features, fge, entry) {
02058             if (strcasecmp(fge->exten, code))
02059                continue;
02060 
02061             res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
02062             if (res != AST_FEATURE_RETURN_KEEPTRYING) {
02063                AST_RWLIST_UNLOCK(&feature_groups);
02064                break;
02065             }
02066             res = AST_FEATURE_RETURN_PASSDIGITS;
02067          }
02068          if (fge)
02069             break;
02070       }
02071 
02072       AST_RWLIST_UNLOCK(&feature_groups);
02073 
02074       AST_RWLIST_RDLOCK(&feature_list);
02075 
02076       if (!(feature = find_dynamic_feature(tok))) {
02077          AST_RWLIST_UNLOCK(&feature_list);
02078          continue;
02079       }
02080          
02081       /* Feature is up for consideration */
02082       if (!strcmp(feature->exten, code)) {
02083          ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
02084          res = feature->operation(chan, peer, config, code, sense, feature);
02085          if (res != AST_FEATURE_RETURN_KEEPTRYING) {
02086             AST_RWLIST_UNLOCK(&feature_list);
02087             break;
02088          }
02089          res = AST_FEATURE_RETURN_PASSDIGITS;
02090       } else if (!strncmp(feature->exten, code, strlen(code)))
02091          res = AST_FEATURE_RETURN_STOREDIGITS;
02092 
02093       AST_RWLIST_UNLOCK(&feature_list);
02094    }
02095    
02096    return res;
02097 }
02098 
02099 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
02100 {
02101    int x;
02102    
02103    ast_clear_flag(config, AST_FLAGS_ALL);
02104 
02105    ast_rwlock_rdlock(&features_lock);
02106    for (x = 0; x < FEATURES_COUNT; x++) {
02107       if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
02108          continue;
02109 
02110       if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
02111          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
02112 
02113       if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
02114          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
02115    }
02116    ast_rwlock_unlock(&features_lock);
02117    
02118    if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
02119       const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
02120 
02121       if (dynamic_features) {
02122          char *tmp = ast_strdupa(dynamic_features);
02123          char *tok;
02124          struct ast_call_feature *feature;
02125 
02126          /* while we have a feature */
02127          while ((tok = strsep(&tmp, "#"))) {
02128             AST_RWLIST_RDLOCK(&feature_list);
02129             if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
02130                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
02131                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
02132                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
02133                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
02134             }
02135             AST_RWLIST_UNLOCK(&feature_list);
02136          }
02137       }
02138    }
02139 }
02140 
02141 /*! 
02142  * \brief Get feature and dial
02143  * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
02144  *
02145  * Request channel, set channel variables, initiate call,check if they want to disconnect
02146  * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
02147  * check for answer break loop, set cdr return channel.
02148  *
02149  * \todo XXX Check - this is very similar to the code in channel.c 
02150  * \return always a channel
02151 */
02152 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language)
02153 {
02154    int state = 0;
02155    int cause = 0;
02156    int to;
02157    struct ast_channel *chan;
02158    struct ast_channel *monitor_chans[2];
02159    struct ast_channel *active_channel;
02160    int res = 0, ready = 0;
02161    struct timeval started;
02162    int x, len = 0;
02163    char *disconnect_code = NULL, *dialed_code = NULL;
02164 
02165    if (!(chan = ast_request(type, format, data, &cause))) {
02166       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
02167       switch(cause) {
02168       case AST_CAUSE_BUSY:
02169          state = AST_CONTROL_BUSY;
02170          break;
02171       case AST_CAUSE_CONGESTION:
02172          state = AST_CONTROL_CONGESTION;
02173          break;
02174       }
02175       goto done;
02176    }
02177 
02178    ast_set_callerid(chan, cid_num, cid_name, cid_num);
02179    ast_string_field_set(chan, language, language);
02180    ast_channel_inherit_variables(caller, chan); 
02181    pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
02182       
02183    if (ast_call(chan, data, timeout)) {
02184       ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
02185       goto done;
02186    }
02187    
02188    ast_indicate(caller, AST_CONTROL_RINGING);
02189    /* support dialing of the featuremap disconnect code while performing an attended tranfer */
02190    ast_rwlock_rdlock(&features_lock);
02191    for (x = 0; x < FEATURES_COUNT; x++) {
02192       if (strcasecmp(builtin_features[x].sname, "disconnect"))
02193          continue;
02194 
02195       disconnect_code = builtin_features[x].exten;
02196       len = strlen(disconnect_code) + 1;
02197       dialed_code = alloca(len);
02198       memset(dialed_code, 0, len);
02199       break;
02200    }
02201    ast_rwlock_unlock(&features_lock);
02202    x = 0;
02203    started = ast_tvnow();
02204    to = timeout;
02205 
02206    ast_poll_channel_add(caller, chan);
02207 
02208    while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
02209       struct ast_frame *f = NULL;
02210 
02211       monitor_chans[0] = caller;
02212       monitor_chans[1] = chan;
02213       active_channel = ast_waitfor_n(monitor_chans, 2, &to);
02214 
02215       /* see if the timeout has been violated */
02216       if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
02217          state = AST_CONTROL_UNHOLD;
02218          ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
02219          break; /*doh! timeout*/
02220       }
02221 
02222       if (!active_channel)
02223          continue;
02224 
02225       if (chan && (chan == active_channel)){
02226          if (!ast_strlen_zero(chan->call_forward)) {
02227             if (!(chan = ast_call_forward(caller, chan, &to, format, NULL, outstate))) {
02228                return NULL;
02229             }
02230             continue;
02231          }
02232          f = ast_read(chan);
02233          if (f == NULL) { /*doh! where'd he go?*/
02234             state = AST_CONTROL_HANGUP;
02235             res = 0;
02236             break;
02237          }
02238          
02239          if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
02240             if (f->subclass == AST_CONTROL_RINGING) {
02241                state = f->subclass;
02242                ast_verb(3, "%s is ringing\n", chan->name);
02243                ast_indicate(caller, AST_CONTROL_RINGING);
02244             } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
02245                state = f->subclass;
02246                ast_verb(3, "%s is busy\n", chan->name);
02247                ast_indicate(caller, AST_CONTROL_BUSY);
02248                ast_frfree(f);
02249                f = NULL;
02250                break;
02251             } else if (f->subclass == AST_CONTROL_ANSWER) {
02252                /* This is what we are hoping for */
02253                state = f->subclass;
02254                ast_frfree(f);
02255                f = NULL;
02256                ready=1;
02257                break;
02258             } else if (f->subclass != -1 && f->subclass != AST_CONTROL_PROGRESS) {
02259                ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
02260             }
02261             /* else who cares */
02262          } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
02263             ast_write(caller, f);
02264          }
02265 
02266       } else if (caller && (active_channel == caller)) {
02267          f = ast_read(caller);
02268          if (f == NULL) { /*doh! where'd he go?*/
02269             if (!igncallerstate) {
02270                if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
02271                   /* make this a blind transfer */
02272                   ready = 1;
02273                   break;
02274                }
02275                state = AST_CONTROL_HANGUP;
02276                res = 0;
02277                break;
02278             }
02279          } else {
02280          
02281             if (f->frametype == AST_FRAME_DTMF) {
02282                dialed_code[x++] = f->subclass;
02283                dialed_code[x] = '\0';
02284                if (strlen(dialed_code) == len) {
02285                   x = 0;
02286                } else if (x && strncmp(dialed_code, disconnect_code, x)) {
02287                   x = 0;
02288                   dialed_code[x] = '\0';
02289                }
02290                if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
02291                   /* Caller Canceled the call */
02292                   state = AST_CONTROL_UNHOLD;
02293                   ast_frfree(f);
02294                   f = NULL;
02295                   break;
02296                }
02297             } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
02298                ast_write(chan, f);
02299             }
02300          }
02301       }
02302       if (f)
02303          ast_frfree(f);
02304    } /* end while */
02305 
02306    ast_poll_channel_del(caller, chan);
02307       
02308 done:
02309    ast_indicate(caller, -1);
02310    if (chan && ready) {
02311       if (chan->_state == AST_STATE_UP) 
02312          state = AST_CONTROL_ANSWER;
02313       res = 0;
02314    } else if (chan) {
02315       res = -1;
02316       ast_hangup(chan);
02317       chan = NULL;
02318    } else {
02319       res = -1;
02320    }
02321    
02322    if (outstate)
02323       *outstate = state;
02324 
02325    return chan;
02326 }
02327 
02328 /*!
02329  * \brief return the first unlocked cdr in a possible chain
02330 */
02331 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
02332 {
02333    struct ast_cdr *cdr_orig = cdr;
02334    while (cdr) {
02335       if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
02336          return cdr;
02337       cdr = cdr->next;
02338    }
02339    return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
02340 }
02341 
02342 static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
02343 {
02344    const char *feature;
02345 
02346    if (ast_strlen_zero(features)) {
02347       return;
02348    }
02349 
02350    for (feature = features; *feature; feature++) {
02351       switch (*feature) {
02352       case 'T' :
02353       case 't' :
02354          ast_set_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
02355          break;
02356       case 'K' :
02357       case 'k' :
02358          ast_set_flag(&(config->features_caller), AST_FEATURE_PARKCALL);
02359          break;
02360       case 'H' :
02361       case 'h' :
02362          ast_set_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
02363          break;
02364       case 'W' :
02365       case 'w' :
02366          ast_set_flag(&(config->features_caller), AST_FEATURE_AUTOMON);
02367          break;
02368       default :
02369          ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
02370       }
02371    }
02372 }
02373 
02374 static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
02375 {
02376    struct ast_datastore *ds_callee_features = NULL, *ds_caller_features = NULL;
02377    struct ast_dial_features *callee_features = NULL, *caller_features = NULL;
02378 
02379    ast_channel_lock(caller);
02380    ds_caller_features = ast_channel_datastore_find(caller, &dial_features_info, NULL);
02381    ast_channel_unlock(caller);
02382    if (!ds_caller_features) {
02383       if (!(ds_caller_features = ast_datastore_alloc(&dial_features_info, NULL))) {
02384          ast_log(LOG_WARNING, "Unable to create channel datastore for caller features. Aborting!\n");
02385          return;
02386       }
02387       if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
02388          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
02389          ast_datastore_free(ds_caller_features);
02390          return;
02391       }
02392       ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
02393       caller_features->is_caller = 1;
02394       ast_copy_flags(&(caller_features->features_callee), &(config->features_callee), AST_FLAGS_ALL);
02395       ast_copy_flags(&(caller_features->features_caller), &(config->features_caller), AST_FLAGS_ALL);
02396       ds_caller_features->data = caller_features;
02397       ast_channel_lock(caller);
02398       ast_channel_datastore_add(caller, ds_caller_features);
02399       ast_channel_unlock(caller);
02400    } else {
02401       /* If we don't return here, then when we do a builtin_atxfer we will copy the disconnect
02402        * flags over from the atxfer to the caller */
02403       return;
02404    }
02405 
02406    ast_channel_lock(callee);
02407    ds_callee_features = ast_channel_datastore_find(callee, &dial_features_info, NULL);
02408    ast_channel_unlock(callee);
02409    if (!ds_callee_features) {
02410       if (!(ds_callee_features = ast_datastore_alloc(&dial_features_info, NULL))) {
02411          ast_log(LOG_WARNING, "Unable to create channel datastore for callee features. Aborting!\n");
02412          return;
02413       }
02414       if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
02415          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
02416          ast_datastore_free(ds_callee_features);
02417          return;
02418       }
02419       ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
02420       callee_features->is_caller = 0;
02421       ast_copy_flags(&(callee_features->features_callee), &(config->features_caller), AST_FLAGS_ALL);
02422       ast_copy_flags(&(callee_features->features_caller), &(config->features_callee), AST_FLAGS_ALL);
02423       ds_callee_features->data = callee_features;
02424       ast_channel_lock(callee);
02425       ast_channel_datastore_add(callee, ds_callee_features);
02426       ast_channel_unlock(callee);
02427    }
02428 
02429    return;
02430 }
02431 
02432 /*!
02433  * \brief bridge the call and set CDR
02434  * \param chan,peer,config
02435  * 
02436  * Set start time, check for two channels,check if monitor on
02437  * check for feature activation, create new CDR
02438  * \retval res on success.
02439  * \retval -1 on failure to bridge.
02440 */
02441 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
02442 {
02443    /* Copy voice back and forth between the two channels.  Give the peer
02444       the ability to transfer calls with '#<extension' syntax. */
02445    struct ast_frame *f;
02446    struct ast_channel *who;
02447    char chan_featurecode[FEATURE_MAX_LEN + 1]="";
02448    char peer_featurecode[FEATURE_MAX_LEN + 1]="";
02449    char orig_channame[AST_MAX_EXTENSION];
02450    char orig_peername[AST_MAX_EXTENSION];
02451    int res;
02452    int diff;
02453    int hasfeatures=0;
02454    int hadfeatures=0;
02455    int autoloopflag;
02456    struct ast_option_header *aoh;
02457    struct ast_bridge_config backup_config;
02458    struct ast_cdr *bridge_cdr = NULL;
02459    struct ast_cdr *orig_peer_cdr = NULL;
02460    struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
02461    struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
02462    struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
02463    struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
02464 
02465    memset(&backup_config, 0, sizeof(backup_config));
02466 
02467    config->start_time = ast_tvnow();
02468 
02469    if (chan && peer) {
02470       pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
02471       pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
02472    } else if (chan) {
02473       pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
02474    }
02475 
02476    set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
02477    add_features_datastores(chan, peer, config);
02478 
02479    /* This is an interesting case.  One example is if a ringing channel gets redirected to
02480     * an extension that picks up a parked call.  This will make sure that the call taken
02481     * out of parking gets told that the channel it just got bridged to is still ringing. */
02482    if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
02483       ast_indicate(peer, AST_CONTROL_RINGING);
02484    }
02485 
02486    if (monitor_ok) {
02487       const char *monitor_exec;
02488       struct ast_channel *src = NULL;
02489       if (!monitor_app) { 
02490          if (!(monitor_app = pbx_findapp("Monitor")))
02491             monitor_ok=0;
02492       }
02493       if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
02494          src = chan;
02495       else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
02496          src = peer;
02497       if (monitor_app && src) {
02498          char *tmp = ast_strdupa(monitor_exec);
02499          pbx_exec(src, monitor_app, tmp);
02500       }
02501    }
02502 
02503    set_config_flags(chan, peer, config);
02504    config->firstpass = 1;
02505 
02506    /* Answer if need be */
02507    if (chan->_state != AST_STATE_UP) {
02508       if (ast_raw_answer(chan, 1)) {
02509          return -1;
02510       }
02511    }
02512 
02513    ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
02514    ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
02515    orig_peer_cdr = peer_cdr;
02516    
02517    if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
02518       
02519       if (chan_cdr) {
02520          ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
02521          ast_cdr_update(chan);
02522          bridge_cdr = ast_cdr_dup(chan_cdr);
02523          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
02524          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
02525          if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) {
02526             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
02527          }
02528          if (peer_cdr && ast_strlen_zero(peer->accountcode)) {
02529             ast_cdr_setaccount(peer, chan->accountcode);
02530          }
02531 
02532       } else {
02533          /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
02534          bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
02535          ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
02536          ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
02537          ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
02538          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
02539          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
02540          ast_cdr_setcid(bridge_cdr, chan);
02541          bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
02542          bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
02543          ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
02544          /* Destination information */
02545          ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
02546          ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
02547          if (peer_cdr) {
02548             bridge_cdr->start = peer_cdr->start;
02549             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
02550          } else {
02551             ast_cdr_start(bridge_cdr);
02552          }
02553       }
02554       ast_debug(4,"bridge answer set, chan answer set\n");
02555       /* peer_cdr->answer will be set when a macro runs on the peer;
02556          in that case, the bridge answer will be delayed while the
02557          macro plays on the peer channel. The peer answered the call
02558          before the macro started playing. To the phone system,
02559          this is billable time for the call, even tho the caller
02560          hears nothing but ringing while the macro does its thing. */
02561 
02562       /* Another case where the peer cdr's time will be set, is when
02563          A self-parks by pickup up phone and dialing 700, then B
02564          picks up A by dialing its parking slot; there may be more 
02565          practical paths that get the same result, tho... in which
02566          case you get the previous answer time from the Park... which
02567          is before the bridge's start time, so I added in the 
02568          tvcmp check to the if below */
02569 
02570       if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) {
02571          bridge_cdr->answer = peer_cdr->answer;
02572          bridge_cdr->disposition = peer_cdr->disposition;
02573          if (chan_cdr) {
02574             chan_cdr->answer = peer_cdr->answer;
02575             chan_cdr->disposition = peer_cdr->disposition;
02576          }
02577       } else {
02578          ast_cdr_answer(bridge_cdr);
02579          if (chan_cdr) {
02580             ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
02581          }
02582       }
02583       if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
02584          if (chan_cdr) {
02585             ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
02586          }
02587          if (peer_cdr) {
02588             ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
02589          }
02590       }
02591    }
02592    for (;;) {
02593       struct ast_channel *other; /* used later */
02594    
02595       res = ast_channel_bridge(chan, peer, config, &f, &who);
02596       
02597       /* When frame is not set, we are probably involved in a situation
02598          where we've timed out.
02599          When frame is set, we'll come this code twice; once for DTMF_BEGIN
02600          and also for DTMF_END. If we flow into the following 'if' for both, then 
02601          our wait times are cut in half, as both will subtract from the
02602          feature_timer. Not good!
02603       */
02604       if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
02605          /* Update time limit for next pass */
02606          diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
02607          if (res == AST_BRIDGE_RETRY) {
02608             /* The feature fully timed out but has not been updated. Skip
02609              * the potential round error from the diff calculation and
02610              * explicitly set to expired. */
02611             config->feature_timer = -1;
02612          } else {
02613             config->feature_timer -= diff;
02614          }
02615 
02616          if (hasfeatures) {
02617             /* Running on backup config, meaning a feature might be being
02618                activated, but that's no excuse to keep things going 
02619                indefinitely! */
02620             if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
02621                ast_debug(1, "Timed out, realtime this time!\n");
02622                config->feature_timer = 0;
02623                who = chan;
02624                if (f)
02625                   ast_frfree(f);
02626                f = NULL;
02627                res = 0;
02628             } else if (config->feature_timer <= 0) {
02629                /* Not *really* out of time, just out of time for
02630                   digits to come in for features. */
02631                ast_debug(1, "Timed out for feature!\n");
02632                if (!ast_strlen_zero(peer_featurecode)) {
02633                   ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
02634                   memset(peer_featurecode, 0, sizeof(peer_featurecode));
02635                }
02636                if (!ast_strlen_zero(chan_featurecode)) {
02637                   ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
02638                   memset(chan_featurecode, 0, sizeof(chan_featurecode));
02639                }
02640                if (f)
02641                   ast_frfree(f);
02642                hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
02643                if (!hasfeatures) {
02644                   /* Restore original (possibly time modified) bridge config */
02645                   memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
02646                   memset(&backup_config, 0, sizeof(backup_config));
02647                }
02648                hadfeatures = hasfeatures;
02649                /* Continue as we were */
02650                continue;
02651             } else if (!f) {
02652                /* The bridge returned without a frame and there is a feature in progress.
02653                 * However, we don't think the feature has quite yet timed out, so just
02654                 * go back into the bridge. */
02655                continue;
02656             }
02657          } else {
02658             if (config->feature_timer <=0) {
02659                /* We ran out of time */
02660                config->feature_timer = 0;
02661                who = chan;
02662                if (f)
02663                   ast_frfree(f);
02664                f = NULL;
02665                res = 0;
02666             }
02667          }
02668       }
02669       if (res < 0) {
02670          if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
02671             ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
02672          goto before_you_go;
02673       }
02674       
02675       if (!f || (f->frametype == AST_FRAME_CONTROL &&
02676             (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 
02677                f->subclass == AST_CONTROL_CONGESTION))) {
02678          res = -1;
02679          break;
02680       }
02681       /* many things should be sent to the 'other' channel */
02682       other = (who == chan) ? peer : chan;
02683       if (f->frametype == AST_FRAME_CONTROL) {
02684          switch (f->subclass) {
02685          case AST_CONTROL_RINGING:
02686          case AST_CONTROL_FLASH:
02687          case -1:
02688             ast_indicate(other, f->subclass);
02689             break;
02690          case AST_CONTROL_HOLD:
02691          case AST_CONTROL_UNHOLD:
02692             ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
02693             break;
02694          case AST_CONTROL_OPTION:
02695             aoh = f->data.ptr;
02696             /* Forward option Requests */
02697             if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
02698                ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 
02699                   f->datalen - sizeof(struct ast_option_header), 0);
02700             }
02701             break;
02702          }
02703       } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
02704          /* eat it */
02705       } else if (f->frametype == AST_FRAME_DTMF) {
02706          char *featurecode;
02707          int sense;
02708 
02709          hadfeatures = hasfeatures;
02710          /* This cannot overrun because the longest feature is one shorter than our buffer */
02711          if (who == chan) {
02712             sense = FEATURE_SENSE_CHAN;
02713             featurecode = chan_featurecode;
02714          } else  {
02715             sense = FEATURE_SENSE_PEER;
02716             featurecode = peer_featurecode;
02717          }
02718          /*! append the event to featurecode. we rely on the string being zero-filled, and
02719           * not overflowing it. 
02720           * \todo XXX how do we guarantee the latter ?
02721           */
02722          featurecode[strlen(featurecode)] = f->subclass;
02723          /* Get rid of the frame before we start doing "stuff" with the channels */
02724          ast_frfree(f);
02725          f = NULL;
02726          config->feature_timer = backup_config.feature_timer;
02727          res = feature_interpret(chan, peer, config, featurecode, sense);
02728          switch(res) {
02729          case AST_FEATURE_RETURN_PASSDIGITS:
02730             ast_dtmf_stream(other, who, featurecode, 0, 0);
02731             /* Fall through */
02732          case AST_FEATURE_RETURN_SUCCESS:
02733             memset(featurecode, 0, sizeof(chan_featurecode));
02734             break;
02735          }
02736          if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
02737             res = 0;
02738          } else 
02739             break;
02740          hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
02741          if (hadfeatures && !hasfeatures) {
02742             /* Restore backup */
02743             memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
02744             memset(&backup_config, 0, sizeof(struct ast_bridge_config));
02745          } else if (hasfeatures) {
02746             if (!hadfeatures) {
02747                /* Backup configuration */
02748                memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
02749                /* Setup temporary config options */
02750                config->play_warning = 0;
02751                ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
02752                ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
02753                config->warning_freq = 0;
02754                config->warning_sound = NULL;
02755                config->end_sound = NULL;
02756                config->start_sound = NULL;
02757                config->firstpass = 0;
02758             }
02759             config->start_time = ast_tvnow();
02760             config->feature_timer = featuredigittimeout;
02761             ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
02762          }
02763       }
02764       if (f)
02765          ast_frfree(f);
02766 
02767    }
02768    before_you_go:
02769 
02770    if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) {
02771       ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
02772       if (bridge_cdr) {
02773          ast_cdr_discard(bridge_cdr);
02774          /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */
02775       }
02776       return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */
02777    }
02778 
02779    if (config->end_bridge_callback) {
02780       config->end_bridge_callback(config->end_bridge_callback_data);
02781    }
02782 
02783    /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation 
02784     * if it were, then chan belongs to a different thread now, and might have been hung up long
02785      * ago.
02786     */
02787    if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) &&
02788       ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
02789       struct ast_cdr *swapper = NULL;
02790       char savelastapp[AST_MAX_EXTENSION];
02791       char savelastdata[AST_MAX_EXTENSION];
02792       char save_exten[AST_MAX_EXTENSION];
02793       int  save_prio;
02794       int  found = 0;   /* set if we find at least one match */
02795       int  spawn_error = 0;
02796       
02797       autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
02798       ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
02799       if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
02800          ast_cdr_end(bridge_cdr);
02801       }
02802       /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
02803          dialplan code operate on it */
02804       ast_channel_lock(chan);
02805       if (bridge_cdr) {
02806          swapper = chan->cdr;
02807          ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
02808          ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
02809          chan->cdr = bridge_cdr;
02810       }
02811       ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
02812       save_prio = chan->priority;
02813       ast_copy_string(chan->exten, "h", sizeof(chan->exten));
02814       chan->priority = 1;
02815       ast_channel_unlock(chan);
02816       while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) {
02817          chan->priority++;
02818       }
02819       if (spawn_error && (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num) || ast_check_hangup(chan))) {
02820          /* if the extension doesn't exist or a hangup occurred, this isn't really a spawn error */
02821          spawn_error = 0;
02822       }
02823       if (found && spawn_error) {
02824          /* Something bad happened, or a hangup has been requested. */
02825          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
02826          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
02827       }
02828       /* swap it back */
02829       ast_channel_lock(chan);
02830       ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
02831       chan->priority = save_prio;
02832       if (bridge_cdr) {
02833          if (chan->cdr == bridge_cdr) {
02834             chan->cdr = swapper;
02835          } else {
02836             bridge_cdr = NULL;
02837          }
02838       }
02839       if (!spawn_error) {
02840          ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
02841       }
02842       ast_channel_unlock(chan);
02843       /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
02844       if (bridge_cdr) {
02845          ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
02846          ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
02847       }
02848       ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
02849    }
02850    
02851    /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
02852    new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
02853    if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))
02854       ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
02855 
02856    /* we can post the bridge CDR at this point */
02857    if (bridge_cdr) {
02858       ast_cdr_end(bridge_cdr);
02859       ast_cdr_detach(bridge_cdr);
02860    }
02861    
02862    /* do a specialized reset on the beginning channel
02863       CDR's, if they still exist, so as not to mess up
02864       issues in future bridges;
02865       
02866       Here are the rules of the game:
02867       1. The chan and peer channel pointers will not change
02868          during the life of the bridge.
02869       2. But, in transfers, the channel names will change.
02870          between the time the bridge is started, and the
02871          time the channel ends. 
02872          Usually, when a channel changes names, it will
02873          also change CDR pointers.
02874       3. Usually, only one of the two channels (chan or peer)
02875          will change names.
02876       4. Usually, if a channel changes names during a bridge,
02877          it is because of a transfer. Usually, in these situations,
02878          it is normal to see 2 bridges running simultaneously, and
02879          it is not unusual to see the two channels that change
02880          swapped between bridges.
02881       5. After a bridge occurs, we have 2 or 3 channels' CDRs
02882          to attend to; if the chan or peer changed names,
02883          we have the before and after attached CDR's.
02884    */
02885    
02886    if (new_chan_cdr) {
02887       struct ast_channel *chan_ptr = NULL;
02888  
02889       if (strcasecmp(orig_channame, chan->name) != 0) { 
02890          /* old channel */
02891          chan_ptr = ast_get_channel_by_name_locked(orig_channame);
02892          if (chan_ptr) {
02893             if (!ast_bridged_channel(chan_ptr)) {
02894                struct ast_cdr *cur;
02895                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
02896                   if (cur == chan_cdr) {
02897                      break;
02898                   }
02899                }
02900                if (cur)
02901                   ast_cdr_specialized_reset(chan_cdr,0);
02902             }
02903             ast_channel_unlock(chan_ptr);
02904          }
02905          /* new channel */
02906          ast_cdr_specialized_reset(new_chan_cdr,0);
02907       } else {
02908          ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr  */
02909       }
02910    }
02911    
02912    {
02913       struct ast_channel *chan_ptr = NULL;
02914       new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
02915       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))
02916          ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
02917       if (strcasecmp(orig_peername, peer->name) != 0) { 
02918          /* old channel */
02919          chan_ptr = ast_get_channel_by_name_locked(orig_peername);
02920          if (chan_ptr) {
02921             if (!ast_bridged_channel(chan_ptr)) {
02922                struct ast_cdr *cur;
02923                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
02924                   if (cur == peer_cdr) {
02925                      break;
02926                   }
02927                }
02928                if (cur)
02929                   ast_cdr_specialized_reset(peer_cdr,0);
02930             }
02931             ast_channel_unlock(chan_ptr);
02932          }
02933          /* new channel */
02934          if (new_peer_cdr) {
02935             ast_cdr_specialized_reset(new_peer_cdr, 0);
02936          }
02937       } else {
02938          ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr  */
02939       }
02940    }
02941    
02942    return res;
02943 }
02944 
02945 /*! \brief Output parking event to manager */
02946 static void post_manager_event(const char *s, struct parkeduser *pu)
02947 {
02948    manager_event(EVENT_FLAG_CALL, s,
02949       "Exten: %s\r\n"
02950       "Channel: %s\r\n"
02951       "Parkinglot: %s\r\n"
02952       "CallerIDNum: %s\r\n"
02953       "CallerIDName: %s\r\n"
02954       "UniqueID: %s\r\n\r\n",
02955       pu->parkingexten, 
02956       pu->chan->name,
02957       pu->parkinglot->name,
02958       S_OR(pu->chan->cid.cid_num, "<unknown>"),
02959       S_OR(pu->chan->cid.cid_name, "<unknown>"),
02960       pu->chan->uniqueid
02961       );
02962 }
02963 
02964 static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
02965 {
02966    int i = 0;
02967    enum {
02968       OPT_CALLEE_REDIRECT   = 't',
02969       OPT_CALLER_REDIRECT   = 'T',
02970       OPT_CALLEE_AUTOMON    = 'w',
02971       OPT_CALLER_AUTOMON    = 'W',
02972       OPT_CALLEE_DISCONNECT = 'h',
02973       OPT_CALLER_DISCONNECT = 'H',
02974       OPT_CALLEE_PARKCALL   = 'k',
02975       OPT_CALLER_PARKCALL   = 'K',
02976    };
02977 
02978    memset(options, 0, len);
02979    if (ast_test_flag(features_caller, AST_FEATURE_REDIRECT) && i < len) {
02980       options[i++] = OPT_CALLER_REDIRECT;
02981    }
02982    if (ast_test_flag(features_caller, AST_FEATURE_AUTOMON) && i < len) {
02983       options[i++] = OPT_CALLER_AUTOMON;
02984    }
02985    if (ast_test_flag(features_caller, AST_FEATURE_DISCONNECT) && i < len) {
02986       options[i++] = OPT_CALLER_DISCONNECT;
02987    }
02988    if (ast_test_flag(features_caller, AST_FEATURE_PARKCALL) && i < len) {
02989       options[i++] = OPT_CALLER_PARKCALL;
02990    }
02991 
02992    if (ast_test_flag(features_callee, AST_FEATURE_REDIRECT) && i < len) {
02993       options[i++] = OPT_CALLEE_REDIRECT;
02994    }
02995    if (ast_test_flag(features_callee, AST_FEATURE_AUTOMON) && i < len) {
02996       options[i++] = OPT_CALLEE_AUTOMON;
02997    }
02998    if (ast_test_flag(features_callee, AST_FEATURE_DISCONNECT) && i < len) {
02999       options[i++] = OPT_CALLEE_DISCONNECT;
03000    }
03001    if (ast_test_flag(features_callee, AST_FEATURE_PARKCALL) && i < len) {
03002       options[i++] = OPT_CALLEE_PARKCALL;
03003    }
03004 
03005    return options;
03006 }
03007 
03008 /*! \brief Run management on parkinglots, called once per parkinglot */
03009 int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *ms, int *max)
03010 {
03011 
03012    struct parkeduser *pu;
03013    int res = 0;
03014    char parkingslot[AST_MAX_EXTENSION];
03015 
03016    /* Lock parking list */
03017    AST_LIST_LOCK(&curlot->parkings);
03018    AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
03019       struct ast_channel *chan = pu->chan;   /* shorthand */
03020       int tms;        /* timeout for this item */
03021       int x;          /* fd index in channel */
03022       struct ast_context *con;
03023 
03024       if (pu->notquiteyet) { /* Pretend this one isn't here yet */
03025          continue;
03026       }
03027       tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
03028       if (tms > pu->parkingtime) {
03029          /* Stop music on hold */
03030          ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
03031          /* Get chan, exten from derived kludge */
03032          if (pu->peername[0]) {
03033             char *peername = ast_strdupa(pu->peername);
03034             char *cp = strrchr(peername, '-');
03035             char peername_flat[AST_MAX_EXTENSION]; /* using something like DAHDI/52 for an extension name is NOT a good idea */
03036             int i;
03037 
03038             if (cp) 
03039                *cp = 0;
03040             ast_copy_string(peername_flat,peername,sizeof(peername_flat));
03041             for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
03042                if (peername_flat[i] == '/') 
03043                   peername_flat[i]= '0';
03044             }
03045             con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
03046             if (!con) {
03047                ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
03048             }
03049             if (con) {
03050                char returnexten[AST_MAX_EXTENSION];
03051                struct ast_datastore *features_datastore;
03052                struct ast_dial_features *dialfeatures = NULL;
03053 
03054                ast_channel_lock(chan);
03055 
03056                if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
03057                   dialfeatures = features_datastore->data;
03058 
03059                ast_channel_unlock(chan);
03060 
03061                if (!strncmp(peername, "Parked/", 7)) {
03062                   peername += 7;
03063                }
03064 
03065                if (dialfeatures) {
03066                   char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
03067                   snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername, callback_dialoptions(&(dialfeatures->features_callee), &(dialfeatures->features_caller), buf, sizeof(buf)));
03068                } else { /* Existing default */
03069                   ast_log(LOG_WARNING, "Dialfeatures not found on %s, using default!\n", chan->name);
03070                   snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
03071                }
03072 
03073                ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
03074             }
03075             if (pu->options_specified == 1) {
03076                /* Park() was called with overriding return arguments, respect those arguments */
03077                set_c_e_p(chan, pu->context, pu->exten, pu->priority);
03078             } else {
03079                if (comebacktoorigin) {
03080                   set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername_flat, 1);
03081                } else {
03082                   ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
03083                   snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
03084                   pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
03085                   set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
03086                }
03087             }
03088          } else {
03089             /* They've been waiting too long, send them back to where they came.  Theoretically they
03090                should have their original extensions and such, but we copy to be on the safe side */
03091             set_c_e_p(chan, pu->context, pu->exten, pu->priority);
03092          }
03093          post_manager_event("ParkedCallTimeOut", pu);
03094 
03095          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);
03096          /* Start up the PBX, or hang them up */
03097          if (ast_pbx_start(chan))  {
03098             ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
03099             ast_hangup(chan);
03100          }
03101          /* And take them out of the parking lot */
03102          con = ast_context_find(pu->parkinglot->parking_con);
03103          if (con) {
03104             if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
03105                ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
03106             else
03107                notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
03108          } else
03109             ast_log(LOG_WARNING, "Whoa, no parking context?\n");
03110          AST_LIST_REMOVE_CURRENT(list);
03111          free(pu);
03112       } else { /* still within parking time, process descriptors */
03113          for (x = 0; x < AST_MAX_FDS; x++) {
03114             struct ast_frame *f;
03115 
03116             if ((chan->fds[x] == -1) || (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds))) 
03117                continue;
03118             
03119             if (FD_ISSET(chan->fds[x], efds))
03120                ast_set_flag(chan, AST_FLAG_EXCEPTION);
03121             else
03122                ast_clear_flag(chan, AST_FLAG_EXCEPTION);
03123             chan->fdno = x;
03124 
03125             /* See if they need servicing */
03126             f = ast_read(pu->chan);
03127             /* Hangup? */
03128             if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
03129                if (f)
03130                   ast_frfree(f);
03131                post_manager_event("ParkedCallGiveUp", pu);
03132 
03133                /* There's a problem, hang them up*/
03134                ast_verb(2, "%s got tired of being parked\n", chan->name);
03135                ast_hangup(chan);
03136                /* And take them out of the parking lot */
03137                con = ast_context_find(curlot->parking_con);
03138                if (con) {
03139                   if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
03140                      ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
03141                   else
03142                      notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
03143                } else
03144                   ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
03145                AST_LIST_REMOVE_CURRENT(list);
03146                free(pu);
03147                break;
03148             } else {
03149                /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
03150                ast_frfree(f);
03151                if (pu->moh_trys < 3 && !chan->generatordata) {
03152                   ast_debug(1, "MOH on parked call stopped by outside source.  Restarting on channel %s.\n", chan->name);
03153                   ast_indicate_data(chan, AST_CONTROL_HOLD, 
03154                      S_OR(curlot->mohclass, NULL),
03155                      (!ast_strlen_zero(curlot->mohclass) ? strlen(curlot->mohclass) + 1 : 0));
03156                   pu->moh_trys++;
03157                }
03158                goto std;   /* XXX Ick: jumping into an else statement??? XXX */
03159             }
03160          } /* End for */
03161          if (x >= AST_MAX_FDS) {
03162 std:           for (x=0; x<AST_MAX_FDS; x++) {  /* mark fds for next round */
03163                if (chan->fds[x] > -1) {
03164                   FD_SET(chan->fds[x], nrfds);
03165                   FD_SET(chan->fds[x], nefds);
03166                   if (chan->fds[x] > *max)
03167                      *max = chan->fds[x];
03168                }
03169             }
03170             /* Keep track of our shortest wait */
03171             if (tms < *ms || *ms < 0)
03172                *ms = tms;
03173          }
03174       }
03175    }
03176    AST_LIST_TRAVERSE_SAFE_END;
03177    AST_LIST_UNLOCK(&curlot->parkings);
03178    return res;
03179 }
03180 
03181 /*! 
03182  * \brief Take care of parked calls and unpark them if needed 
03183  * \param ignore unused var.
03184  * 
03185  * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
03186  * if so, remove channel from parking lot and return it to the extension that parked it.
03187  * Check if parked channel decided to hangup, wait until next FD via select().
03188 */
03189 static void *do_parking_thread(void *ignore)
03190 {
03191    fd_set rfds, efds;   /* results from previous select, to be preserved across loops. */
03192    fd_set nrfds, nefds; /* args for the next select */
03193    FD_ZERO(&rfds);
03194    FD_ZERO(&efds);
03195 
03196    for (;;) {
03197       int res = 0;
03198       int ms = -1;   /* select timeout, uninitialized */
03199       int max = -1;  /* max fd, none there yet */
03200       struct ao2_iterator iter;
03201       struct ast_parkinglot *curlot;
03202       FD_ZERO(&nrfds);
03203       FD_ZERO(&nefds);
03204       iter = ao2_iterator_init(parkinglots, 0);
03205 
03206       while ((curlot = ao2_iterator_next(&iter))) {
03207          res = manage_parkinglot(curlot, &rfds, &efds, &nrfds, &nefds, &ms, &max);
03208          ao2_ref(curlot, -1);
03209       }
03210 
03211       rfds = nrfds;
03212       efds = nefds;
03213       {
03214          struct timeval wait = ast_samp2tv(ms, 1000);
03215          /* Wait for something to happen */
03216          ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &wait : NULL);
03217       }
03218       pthread_testcancel();
03219    }
03220    return NULL;   /* Never reached */
03221 }
03222 
03223 /*! \brief Find parkinglot by name */
03224 struct ast_parkinglot *find_parkinglot(const char *name)
03225 {
03226    struct ast_parkinglot *parkinglot = NULL;
03227    struct ast_parkinglot tmp_parkinglot;
03228    
03229    if (ast_strlen_zero(name))
03230       return NULL;
03231 
03232    ast_copy_string(tmp_parkinglot.name, name, sizeof(tmp_parkinglot.name));
03233 
03234    parkinglot = ao2_find(parkinglots, &tmp_parkinglot, OBJ_POINTER);
03235 
03236    if (parkinglot && option_debug)
03237       ast_log(LOG_DEBUG, "Found Parkinglot: %s\n", parkinglot->name);
03238 
03239    return parkinglot;
03240 }
03241 
03242 AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
03243    AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
03244    AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
03245    AST_APP_OPTION('s', AST_PARK_OPT_SILENCE),
03246 END_OPTIONS );
03247 
03248 /*! \brief Park a call */
03249 static int park_call_exec(struct ast_channel *chan, void *data)
03250 {
03251    /* Cache the original channel name in case we get masqueraded in the middle
03252     * of a park--it is still theoretically possible for a transfer to happen before
03253     * we get here, but it is _really_ unlikely */
03254    char *orig_chan_name = ast_strdupa(chan->name);
03255    char orig_exten[AST_MAX_EXTENSION];
03256    int orig_priority = chan->priority;
03257 
03258    /* Data is unused at the moment but could contain a parking
03259       lot context eventually */
03260    int res = 0;
03261 
03262    char *parse = NULL;
03263    AST_DECLARE_APP_ARGS(app_args,
03264       AST_APP_ARG(timeout);
03265       AST_APP_ARG(return_con);
03266       AST_APP_ARG(return_ext);
03267       AST_APP_ARG(return_pri);
03268       AST_APP_ARG(options);
03269    );
03270 
03271    parse = ast_strdupa(data);
03272    AST_STANDARD_APP_ARGS(app_args, parse);
03273 
03274    ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
03275 
03276    /* Setup the exten/priority to be s/1 since we don't know
03277       where this call should return */
03278    strcpy(chan->exten, "s");
03279    chan->priority = 1;
03280 
03281    /* Answer if call is not up */
03282    if (chan->_state != AST_STATE_UP)
03283       res = ast_answer(chan);
03284 
03285    /* Sleep to allow VoIP streams to settle down */
03286    if (!res)
03287       res = ast_safe_sleep(chan, 1000);
03288 
03289    /* Park the call */
03290    if (!res) {
03291       struct ast_park_call_args args = {
03292          .orig_chan_name = orig_chan_name,
03293       };
03294       struct ast_flags flags = { 0 };
03295 
03296       if (parse) {
03297          if (!ast_strlen_zero(app_args.timeout)) {
03298             if (sscanf(app_args.timeout, "%30d", &args.timeout) != 1) {
03299                ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
03300                args.timeout = 0;
03301             }
03302          }
03303          if (!ast_strlen_zero(app_args.return_con)) {
03304             args.return_con = app_args.return_con;
03305          }
03306          if (!ast_strlen_zero(app_args.return_ext)) {
03307             args.return_ext = app_args.return_ext;
03308          }
03309          if (!ast_strlen_zero(app_args.return_pri)) {
03310             if (sscanf(app_args.return_pri, "%30d", &args.return_pri) != 1) {
03311                ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
03312                args.return_pri = 0;
03313             }
03314          }
03315       }
03316 
03317       ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
03318       args.flags = flags.flags;
03319 
03320       res = masq_park_call_announce_args(chan, chan, &args);
03321       /* Continue on in the dialplan */
03322       if (res == 1) {
03323          ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
03324          chan->priority = orig_priority;
03325          res = 0;
03326       } else if (!res) {
03327          res = 1;
03328       }
03329    }
03330 
03331    return res;
03332 }
03333 
03334 /*! \brief Pickup parked call */
03335 static int park_exec_full(struct ast_channel *chan, void *data, struct ast_parkinglot *parkinglot)
03336 {
03337    int res = 0;
03338    struct ast_channel *peer=NULL;
03339    struct parkeduser *pu;
03340    struct ast_context *con;
03341    int park = 0;
03342    struct ast_bridge_config config;
03343 
03344    if (data)
03345       park = atoi((char *)data);
03346 
03347    parkinglot = find_parkinglot(findparkinglotname(chan));  
03348    if (!parkinglot)
03349       parkinglot = default_parkinglot;
03350 
03351    AST_LIST_LOCK(&parkinglot->parkings);
03352    AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
03353       if (!data || pu->parkingnum == park) {
03354          if (pu->chan->pbx) { /* do not allow call to be picked up until the PBX thread is finished */
03355             AST_LIST_UNLOCK(&parkinglot->parkings);
03356             return -1;
03357          }
03358          AST_LIST_REMOVE_CURRENT(list);
03359          break;
03360       }
03361    }
03362    AST_LIST_TRAVERSE_SAFE_END;
03363    AST_LIST_UNLOCK(&parkinglot->parkings);
03364 
03365    if (pu) {
03366       peer = pu->chan;
03367       con = ast_context_find(parkinglot->parking_con);
03368       if (con) {
03369          if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
03370             ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
03371          else
03372             notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
03373       } else
03374          ast_log(LOG_WARNING, "Whoa, no parking context?\n");
03375 
03376       manager_event(EVENT_FLAG_CALL, "UnParkedCall",
03377          "Exten: %s\r\n"
03378          "Channel: %s\r\n"
03379          "From: %s\r\n"
03380          "CallerIDNum: %s\r\n"
03381          "CallerIDName: %s\r\n",
03382          pu->parkingexten, pu->chan->name, chan->name,
03383          S_OR(pu->chan->cid.cid_num, "<unknown>"),
03384          S_OR(pu->chan->cid.cid_name, "<unknown>")
03385          );
03386 
03387       ast_free(pu);
03388    }
03389    /* JK02: it helps to answer the channel if not already up */
03390    if (chan->_state != AST_STATE_UP)
03391       ast_answer(chan);
03392 
03393    //XXX Why do we unlock here ?
03394    // uncomment it for now, till my setup with debug_threads and detect_deadlocks starts to complain
03395    //ASTOBJ_UNLOCK(parkinglot);
03396 
03397    if (peer) {
03398       struct ast_datastore *features_datastore;
03399       struct ast_dial_features *dialfeatures = NULL;
03400 
03401       /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
03402 
03403       if (!ast_strlen_zero(courtesytone)) {
03404          int error = 0;
03405          ast_indicate(peer, AST_CONTROL_UNHOLD);
03406          if (parkedplay == 0) {
03407             error = ast_stream_and_wait(chan, courtesytone, "");
03408          } else if (parkedplay == 1) {
03409             error = ast_stream_and_wait(peer, courtesytone, "");
03410          } else if (parkedplay == 2) {
03411             if (!ast_streamfile(chan, courtesytone, chan->language) &&
03412                   !ast_streamfile(peer, courtesytone, chan->language)) {
03413                /*! \todo XXX we would like to wait on both! */
03414                res = ast_waitstream(chan, "");
03415                if (res >= 0)
03416                   res = ast_waitstream(peer, "");
03417                if (res < 0)
03418                   error = 1;
03419             }
03420          }
03421          if (error) {
03422             ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
03423             ast_hangup(peer);
03424             return -1;
03425          }
03426       } else
03427          ast_indicate(peer, AST_CONTROL_UNHOLD);
03428 
03429       res = ast_channel_make_compatible(chan, peer);
03430       if (res < 0) {
03431          ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
03432          ast_hangup(peer);
03433          return -1;
03434       }
03435       /* This runs sorta backwards, since we give the incoming channel control, as if it
03436          were the person called. */
03437       ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
03438 
03439       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
03440       ast_cdr_setdestchan(chan->cdr, peer->name);
03441       memset(&config, 0, sizeof(struct ast_bridge_config));
03442 
03443       /* Get datastore for peer and apply it's features to the callee side of the bridge config */
03444       ast_channel_lock(peer);
03445       if ((features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL))) {
03446          dialfeatures = features_datastore->data;
03447       }
03448       ast_channel_unlock(peer);
03449 
03450       /* When the datastores for both caller and callee are created, both the callee and caller channels
03451        * use the features_caller flag variable to represent themselves. With that said, the config.features_callee
03452        * flags should be copied from the datastore's caller feature flags regardless if peer was a callee
03453        * or caller. */
03454       if (dialfeatures) {
03455          ast_copy_flags(&(config.features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
03456       }
03457 
03458       if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
03459          ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
03460       }
03461       if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
03462          ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
03463       }
03464       if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
03465          ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
03466       }
03467       if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
03468          ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
03469       }
03470       if ((parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
03471          ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
03472       }
03473       if ((parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
03474          ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
03475       }
03476       if ((parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
03477          ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
03478       }
03479       if ((parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
03480          ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
03481       }
03482 
03483       res = ast_bridge_call(chan, peer, &config);
03484 
03485       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
03486       ast_cdr_setdestchan(chan->cdr, peer->name);
03487 
03488       /* Simulate the PBX hanging up */
03489       ast_hangup(peer);
03490       return -1;
03491    } else {
03492       /*! \todo XXX Play a message XXX */
03493       if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
03494          ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
03495       ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
03496       res = -1;
03497    }
03498 
03499    return -1;
03500 }
03501 
03502 static int park_exec(struct ast_channel *chan, void *data) 
03503 {
03504    return park_exec_full(chan, data, default_parkinglot);
03505 }
03506 
03507 /*! \brief Unreference parkinglot object. If no more references,
03508    then go ahead and delete it */
03509 static void parkinglot_unref(struct ast_parkinglot *parkinglot) 
03510 {
03511    int refcount = ao2_ref(parkinglot, -1);
03512    if (option_debug > 2)
03513       ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount - 1);
03514 }
03515 
03516 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
03517 {
03518    int refcount = ao2_ref(parkinglot, +1);
03519    if (option_debug > 2)
03520       ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
03521    return parkinglot;
03522 }
03523 
03524 /*! \brief Allocate parking lot structure */
03525 static struct ast_parkinglot *create_parkinglot(char *name)
03526 {
03527    struct ast_parkinglot *newlot = (struct ast_parkinglot *) NULL;
03528 
03529    if (!name)
03530       return NULL;
03531 
03532    newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);
03533    if (!newlot)
03534       return NULL;
03535    
03536    ast_copy_string(newlot->name, name, sizeof(newlot->name));
03537    AST_LIST_HEAD_INIT(&newlot->parkings);
03538 
03539    return newlot;
03540 }
03541 
03542 /*! \brief Destroy a parking lot */
03543 static void parkinglot_destroy(void *obj)
03544 {
03545    struct ast_parkinglot *ruin = obj;
03546    struct ast_context *con;
03547    con = ast_context_find(ruin->parking_con);
03548    if (con)
03549       ast_context_destroy(con, registrar);
03550    ao2_unlink(parkinglots, ruin);
03551 }
03552 
03553 /*! \brief Build parkinglot from configuration and chain it in */
03554 static struct ast_parkinglot *build_parkinglot(char *name, struct ast_variable *var)
03555 {
03556    struct ast_parkinglot *parkinglot;
03557    struct ast_context *con = NULL;
03558 
03559    struct ast_variable *confvar = var;
03560    int error = 0;
03561    int start = 0, end = 0;
03562    int oldparkinglot = 0;
03563 
03564    parkinglot = find_parkinglot(name);
03565    if (parkinglot)
03566       oldparkinglot = 1;
03567    else
03568       parkinglot = create_parkinglot(name);
03569 
03570    if (!parkinglot)
03571       return NULL;
03572 
03573    ao2_lock(parkinglot);
03574 
03575    if (option_debug)
03576       ast_log(LOG_DEBUG, "Building parking lot %s\n", name);
03577    
03578    /* Do some config stuff */
03579    while(confvar) {
03580       if (!strcasecmp(confvar->name, "context")) {
03581          ast_copy_string(parkinglot->parking_con, confvar->value, sizeof(parkinglot->parking_con));
03582       } else if (!strcasecmp(confvar->name, "parkingtime")) {
03583          if ((sscanf(confvar->value, "%30d", &parkinglot->parkingtime) != 1) || (parkinglot->parkingtime < 1)) {
03584             ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", confvar->value);
03585             parkinglot->parkingtime = DEFAULT_PARK_TIME;
03586          } else
03587             parkinglot->parkingtime = parkinglot->parkingtime * 1000;
03588       } else if (!strcasecmp(confvar->name, "parkpos")) {
03589          if (sscanf(confvar->value, "%30d-%30d", &start, &end) != 2) {
03590             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);
03591             error = 1;
03592          } else {
03593             parkinglot->parking_start = start;
03594             parkinglot->parking_stop = end;
03595          }
03596       } else if (!strcasecmp(confvar->name, "findslot")) {
03597          parkinglot->parkfindnext = (!strcasecmp(confvar->value, "next"));
03598       }
03599       confvar = confvar->next;
03600    }
03601    /* make sure parkingtime is set if not specified */
03602    if (parkinglot->parkingtime == 0) {
03603       parkinglot->parkingtime = DEFAULT_PARK_TIME;
03604    }
03605 
03606    if (!var) { /* Default parking lot */
03607       ast_copy_string(parkinglot->parking_con, "parkedcalls", sizeof(parkinglot->parking_con));
03608       ast_copy_string(parkinglot->parking_con_dial, "park-dial", sizeof(parkinglot->parking_con_dial));
03609       ast_copy_string(parkinglot->mohclass, "default", sizeof(parkinglot->mohclass));
03610    }
03611 
03612    /* Check for errors */
03613    if (ast_strlen_zero(parkinglot->parking_con)) {
03614       ast_log(LOG_WARNING, "Parking lot %s lacks context\n", name);
03615       error = 1;
03616    }
03617 
03618    /* Create context */
03619    if (!error && !(con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar))) {
03620       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
03621       error = 1;
03622    }
03623 
03624    /* Add a parking extension into the context */
03625    if (!error && !oldparkinglot) {
03626       if (!ast_strlen_zero(ast_parking_ext())) {
03627          if (ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), ast_free_ptr, registrar) == -1)
03628             error = 1;
03629       }
03630    }
03631 
03632    ao2_unlock(parkinglot);
03633 
03634    if (error) {
03635       ast_log(LOG_WARNING, "Parking %s not open for business. Configuration error.\n", name);
03636       parkinglot_destroy(parkinglot);
03637       return NULL;
03638    }
03639    if (option_debug)
03640       ast_log(LOG_DEBUG, "Parking %s now open for business. (start exten %d end %d)\n", name, start, end);
03641 
03642 
03643    /* Move it into the list, if it wasn't already there */
03644    if (!oldparkinglot) {
03645       ao2_link(parkinglots, parkinglot);
03646    }
03647    parkinglot_unref(parkinglot);
03648 
03649    return parkinglot;
03650 }
03651 
03652 
03653 /*! 
03654  * \brief Add parking hints for all defined parking lots 
03655  * \param context
03656  * \param start starting parkinglot number
03657  * \param stop ending parkinglot number
03658 */
03659 static void park_add_hints(char *context, int start, int stop)
03660 {
03661    int numext;
03662    char device[AST_MAX_EXTENSION];
03663    char exten[10];
03664 
03665    for (numext = start; numext <= stop; numext++) {
03666       snprintf(exten, sizeof(exten), "%d", numext);
03667       snprintf(device, sizeof(device), "park:%s@%s", exten, context);
03668       ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
03669    }
03670 }
03671 
03672 static int load_config(void) 
03673 {
03674    int start = 0, end = 0;
03675    int res;
03676    int i;
03677    struct ast_context *con = NULL;
03678    struct ast_config *cfg = NULL;
03679    struct ast_variable *var = NULL;
03680    struct feature_group *fg = NULL;
03681    struct ast_flags config_flags = { 0 };
03682    char old_parking_ext[AST_MAX_EXTENSION];
03683    char old_parking_con[AST_MAX_EXTENSION] = "";
03684    char *ctg; 
03685    static const char *categories[] = { 
03686       /* Categories in features.conf that are not
03687        * to be parsed as group categories
03688        */
03689       "general",
03690       "featuremap",
03691       "applicationmap"
03692    };
03693 
03694    if (default_parkinglot) {
03695       strcpy(old_parking_con, default_parkinglot->parking_con);
03696       strcpy(old_parking_ext, parking_ext);
03697    } else {
03698       default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
03699       if (default_parkinglot) {
03700          ao2_lock(default_parkinglot);
03701          default_parkinglot->parking_start = 701;
03702          default_parkinglot->parking_stop = 750;
03703          default_parkinglot->parking_offset = 0;
03704          default_parkinglot->parkfindnext = 0;
03705          default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
03706          ao2_unlock(default_parkinglot);
03707       }
03708    }
03709    if (default_parkinglot) {
03710       if (option_debug)
03711          ast_log(LOG_DEBUG, "Configuration of default parkinglot done.\n");
03712    } else {
03713       ast_log(LOG_ERROR, "Configuration of default parkinglot failed.\n");
03714       return -1;
03715    }
03716    
03717 
03718    /* Reset to defaults */
03719    strcpy(parking_ext, "700");
03720    strcpy(pickup_ext, "*8");
03721    courtesytone[0] = '\0';
03722    strcpy(xfersound, "beep");
03723    strcpy(xferfailsound, "pbx-invalid");
03724    pickupsound[0] = '\0';
03725    pickupfailsound[0] = '\0';
03726    adsipark = 0;
03727    comebacktoorigin = 1;
03728 
03729    default_parkinglot->parkaddhints = 0;
03730    default_parkinglot->parkedcalltransfers = 0;
03731    default_parkinglot->parkedcallreparking = 0;
03732    default_parkinglot->parkedcallrecording = 0;
03733    default_parkinglot->parkedcallhangup = 0;
03734 
03735    transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
03736    featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
03737    atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
03738    atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
03739    atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
03740    atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
03741 
03742    cfg = ast_config_load2("features.conf", "features", config_flags);
03743    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
03744       ast_log(LOG_WARNING,"Could not load features.conf\n");
03745       return 0;
03746    }
03747    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
03748       if (!strcasecmp(var->name, "parkext")) {
03749          ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
03750       } else if (!strcasecmp(var->name, "context")) {
03751          ast_copy_string(default_parkinglot->parking_con, var->value, sizeof(default_parkinglot->parking_con));
03752       } else if (!strcasecmp(var->name, "parkingtime")) {
03753          if ((sscanf(var->value, "%30d", &default_parkinglot->parkingtime) != 1) || (default_parkinglot->parkingtime < 1)) {
03754             ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
03755             default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
03756          } else
03757             default_parkinglot->parkingtime = default_parkinglot->parkingtime * 1000;
03758       } else if (!strcasecmp(var->name, "parkpos")) {
03759          if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
03760             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);
03761          } else if (default_parkinglot) {
03762             default_parkinglot->parking_start = start;
03763             default_parkinglot->parking_stop = end;
03764          } else {
03765             ast_log(LOG_WARNING, "No default parking lot!\n");
03766          }
03767       } else if (!strcasecmp(var->name, "findslot")) {
03768          default_parkinglot->parkfindnext = (!strcasecmp(var->value, "next"));
03769       } else if (!strcasecmp(var->name, "parkinghints")) {
03770          default_parkinglot->parkaddhints = ast_true(var->value);
03771       } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
03772          if (!strcasecmp(var->value, "both"))
03773             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
03774          else if (!strcasecmp(var->value, "caller"))
03775             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
03776          else if (!strcasecmp(var->value, "callee"))
03777             default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
03778       } else if (!strcasecmp(var->name, "parkedcallreparking")) {
03779          if (!strcasecmp(var->value, "both"))
03780             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYBOTH;
03781          else if (!strcasecmp(var->value, "caller"))
03782             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLER;
03783          else if (!strcasecmp(var->value, "callee"))
03784             default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLEE;
03785       } else if (!strcasecmp(var->name, "parkedcallhangup")) {
03786          if (!strcasecmp(var->value, "both"))
03787             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYBOTH;
03788          else if (!strcasecmp(var->value, "caller"))
03789             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLER;
03790          else if (!strcasecmp(var->value, "callee"))
03791             default_parkinglot->parkedcallhangup = AST_FEATURE_FLAG_BYCALLEE;
03792       } else if (!strcasecmp(var->name, "parkedcallrecording")) {
03793          if (!strcasecmp(var->value, "both"))
03794             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYBOTH;
03795          else if (!strcasecmp(var->value, "caller"))
03796             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
03797          else if (!strcasecmp(var->value, "callee"))
03798             default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
03799       } else if (!strcasecmp(var->name, "adsipark")) {
03800          adsipark = ast_true(var->value);
03801       } else if (!strcasecmp(var->name, "transferdigittimeout")) {
03802          if ((sscanf(var->value, "%30d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
03803             ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
03804             transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
03805          } else
03806             transferdigittimeout = transferdigittimeout * 1000;
03807       } else if (!strcasecmp(var->name, "featuredigittimeout")) {
03808          if ((sscanf(var->value, "%30d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
03809             ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
03810             featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
03811          }
03812       } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
03813          if ((sscanf(var->value, "%30d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
03814             ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
03815             atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
03816          } else
03817             atxfernoanswertimeout = atxfernoanswertimeout * 1000;
03818       } else if (!strcasecmp(var->name, "atxferloopdelay")) {
03819          if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
03820             ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
03821             atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
03822          } else 
03823             atxferloopdelay *= 1000;
03824       } else if (!strcasecmp(var->name, "atxferdropcall")) {
03825          atxferdropcall = ast_true(var->value);
03826       } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
03827          if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
03828             ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
03829             atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
03830          }
03831       } else if (!strcasecmp(var->name, "courtesytone")) {
03832          ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
03833       }  else if (!strcasecmp(var->name, "parkedplay")) {
03834          if (!strcasecmp(var->value, "both"))
03835             parkedplay = 2;
03836          else if (!strcasecmp(var->value, "parked"))
03837             parkedplay = 1;
03838          else
03839             parkedplay = 0;
03840       } else if (!strcasecmp(var->name, "xfersound")) {
03841          ast_copy_string(xfersound, var->value, sizeof(xfersound));
03842       } else if (!strcasecmp(var->name, "xferfailsound")) {
03843          ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
03844       } else if (!strcasecmp(var->name, "pickupexten")) {
03845          ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
03846       } else if (!strcasecmp(var->name, "pickupsound")) {
03847          ast_copy_string(pickupsound, var->value, sizeof(pickupsound));
03848       } else if (!strcasecmp(var->name, "pickupfailsound")) {
03849          ast_copy_string(pickupfailsound, var->value, sizeof(pickupfailsound));
03850       } else if (!strcasecmp(var->name, "comebacktoorigin")) {
03851          comebacktoorigin = ast_true(var->value);
03852       } else if (!strcasecmp(var->name, "parkedmusicclass")) {
03853          ast_copy_string(default_parkinglot->mohclass, var->value, sizeof(default_parkinglot->mohclass));
03854       }
03855    }
03856 
03857    unmap_features();
03858    for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
03859       if (remap_feature(var->name, var->value))
03860          ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
03861    }
03862 
03863    /* Map a key combination to an application*/
03864    ast_unregister_features();
03865    for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
03866       char *tmp_val = ast_strdupa(var->value);
03867       char *exten, *activateon, *activatedby, *app, *app_args, *moh_class; 
03868       struct ast_call_feature *feature;
03869 
03870       /* strsep() sets the argument to NULL if match not found, and it
03871        * is safe to use it with a NULL argument, so we don't check
03872        * between calls.
03873        */
03874       exten = strsep(&tmp_val,",");
03875       activatedby = strsep(&tmp_val,",");
03876       app = strsep(&tmp_val,",");
03877       app_args = strsep(&tmp_val,",");
03878       moh_class = strsep(&tmp_val,",");
03879 
03880       activateon = strsep(&activatedby, "/");   
03881 
03882       /*! \todo XXX var_name or app_args ? */
03883       if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
03884          ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
03885             app, exten, activateon, var->name);
03886          continue;
03887       }
03888 
03889       AST_RWLIST_RDLOCK(&feature_list);
03890       if ((feature = find_dynamic_feature(var->name))) {
03891          AST_RWLIST_UNLOCK(&feature_list);
03892          ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
03893          continue;
03894       }
03895       AST_RWLIST_UNLOCK(&feature_list);
03896             
03897       if (!(feature = ast_calloc(1, sizeof(*feature))))
03898          continue;               
03899 
03900       ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
03901       ast_copy_string(feature->app, app, FEATURE_APP_LEN);
03902       ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
03903       
03904       if (app_args) 
03905          ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
03906 
03907       if (moh_class)
03908          ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
03909          
03910       ast_copy_string(feature->exten, exten, sizeof(feature->exten));
03911       feature->operation = feature_exec_app;
03912       ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
03913 
03914       /* Allow caller and calle to be specified for backwards compatability */
03915       if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
03916          ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
03917       else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
03918          ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
03919       else {
03920          ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
03921             " must be 'self', or 'peer'\n", var->name);
03922          continue;
03923       }
03924 
03925       if (ast_strlen_zero(activatedby))
03926          ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
03927       else if (!strcasecmp(activatedby, "caller"))
03928          ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
03929       else if (!strcasecmp(activatedby, "callee"))
03930          ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
03931       else if (!strcasecmp(activatedby, "both"))
03932          ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
03933       else {
03934          ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
03935             " must be 'caller', or 'callee', or 'both'\n", var->name);
03936          continue;
03937       }
03938 
03939       ast_register_feature(feature);
03940          
03941       ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
03942    }
03943 
03944    ast_unregister_groups();
03945    AST_RWLIST_WRLOCK(&feature_groups);
03946 
03947    ctg = NULL;
03948    while ((ctg = ast_category_browse(cfg, ctg))) {
03949       /* Is this a parkinglot definition ? */
03950       if (!strncasecmp(ctg, "parkinglot_", strlen("parkinglot_"))) {
03951          ast_debug(2, "Found configuration section %s, assume parking context\n", ctg);
03952          if(!build_parkinglot(ctg, ast_variable_browse(cfg, ctg)))
03953             ast_log(LOG_ERROR, "Could not build parking lot %s. Configuration error.\n", ctg);
03954          else
03955             ast_debug(1, "Configured parking context %s\n", ctg);
03956          continue;   
03957       }
03958       /* No, check if it's a group */
03959       for (i = 0; i < ARRAY_LEN(categories); i++) {
03960          if (!strcasecmp(categories[i], ctg))
03961             break;
03962       }
03963 
03964       if (i < ARRAY_LEN(categories)) 
03965          continue;
03966 
03967       if (!(fg = register_group(ctg)))
03968          continue;
03969 
03970       for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
03971          struct ast_call_feature *feature;
03972 
03973          AST_RWLIST_RDLOCK(&feature_list);
03974          if (!(feature = find_dynamic_feature(var->name)) && 
03975              !(feature = ast_find_call_feature(var->name))) {
03976             AST_RWLIST_UNLOCK(&feature_list);
03977             ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
03978             continue;
03979          }
03980          AST_RWLIST_UNLOCK(&feature_list);
03981 
03982          register_group_feature(fg, var->value, feature);
03983       }
03984    }
03985 
03986    AST_RWLIST_UNLOCK(&feature_groups);
03987 
03988    ast_config_destroy(cfg);
03989 
03990    /* Remove the old parking extension */
03991    if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
03992       if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar, 0))
03993             notify_metermaids(old_parking_ext, old_parking_con, AST_DEVICE_NOT_INUSE);
03994       ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
03995    }
03996    
03997    if (!(con = ast_context_find_or_create(NULL, NULL, default_parkinglot->parking_con, registrar))) {
03998       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", default_parkinglot->parking_con);
03999       return -1;
04000    }
04001    res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
04002    if (default_parkinglot->parkaddhints)
04003       park_add_hints(default_parkinglot->parking_con, default_parkinglot->parking_start, default_parkinglot->parking_stop);
04004    if (!res)
04005       notify_metermaids(ast_parking_ext(), default_parkinglot->parking_con, AST_DEVICE_INUSE);
04006    return res;
04007 
04008 }
04009 
04010 /*!
04011  * \brief CLI command to list configured features
04012  * \param e
04013  * \param cmd
04014  * \param a
04015  *
04016  * \retval CLI_SUCCESS on success.
04017  * \retval NULL when tab completion is used.
04018  */
04019 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04020 {
04021    int i;
04022    struct ast_call_feature *feature;
04023    struct ao2_iterator iter;
04024    struct ast_parkinglot *curlot;
04025 #define HFS_FORMAT "%-25s %-7s %-7s\n"
04026 
04027    switch (cmd) {
04028    
04029    case CLI_INIT:
04030       e->command = "features show";
04031       e->usage =
04032          "Usage: features show\n"
04033          "       Lists configured features\n";
04034       return NULL;
04035    case CLI_GENERATE:
04036       return NULL;
04037    }
04038 
04039    ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
04040    ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
04041 
04042    ast_cli(a->fd, HFS_FORMAT, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
04043 
04044    ast_rwlock_rdlock(&features_lock);
04045    for (i = 0; i < FEATURES_COUNT; i++)
04046       ast_cli(a->fd, HFS_FORMAT, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
04047    ast_rwlock_unlock(&features_lock);
04048 
04049    ast_cli(a->fd, "\n");
04050    ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
04051    ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
04052    if (AST_RWLIST_EMPTY(&feature_list)) {
04053       ast_cli(a->fd, "(none)\n");
04054    } else {
04055       AST_RWLIST_RDLOCK(&feature_list);
04056       AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
04057          ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
04058       }
04059       AST_RWLIST_UNLOCK(&feature_list);
04060    }
04061 
04062    // loop through all the parking lots
04063    iter = ao2_iterator_init(parkinglots, 0);
04064 
04065    while ((curlot = ao2_iterator_next(&iter))) {
04066       ast_cli(a->fd, "\nCall parking (Parking lot: %s)\n", curlot->name);
04067       ast_cli(a->fd, "------------\n");
04068       ast_cli(a->fd,"%-22s:      %s\n", "Parking extension", parking_ext);
04069       ast_cli(a->fd,"%-22s:      %s\n", "Parking context", curlot->parking_con);
04070       ast_cli(a->fd,"%-22s:      %d-%d\n", "Parked call extensions", curlot->parking_start, curlot->parking_stop);
04071       ast_cli(a->fd,"\n");
04072       ao2_ref(curlot, -1);
04073    }
04074 
04075 
04076    return CLI_SUCCESS;
04077 }
04078 
04079 int ast_features_reload(void)
04080 {
04081    int res;
04082    /* Release parking lot list */
04083    //ASTOBJ_CONTAINER_MARKALL(&parkinglots);
04084    // TODO: I don't think any marking is necessary
04085 
04086    /* Reload configuration */
04087    res = load_config();
04088    
04089    //ASTOBJ_CONTAINER_PRUNE_MARKED(&parkinglots, parkinglot_destroy);
04090    return res;
04091 }
04092 
04093 static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04094 {
04095    switch (cmd) { 
04096    case CLI_INIT:
04097       e->command = "features reload";
04098       e->usage =
04099          "Usage: features reload\n"
04100          "       Reloads configured call features from features.conf\n";
04101       return NULL;
04102    case CLI_GENERATE:
04103       return NULL;
04104    }
04105    ast_features_reload();
04106 
04107    return CLI_SUCCESS;
04108 }
04109 
04110 static char mandescr_bridge[] =
04111 "Description: Bridge together two channels already in the PBX\n"
04112 "Variables: ( Headers marked with * are required )\n"
04113 "   *Channel1: Channel to Bridge to Channel2\n"
04114 "   *Channel2: Channel to Bridge to Channel1\n"
04115 "        Tone: (Yes|No) Play courtesy tone to Channel 2\n"
04116 "\n";
04117 
04118 /*!
04119  * \brief Actual bridge
04120  * \param chan
04121  * \param tmpchan
04122  * 
04123  * Stop hold music, lock both channels, masq channels,
04124  * after bridge return channel to next priority.
04125 */
04126 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
04127 {
04128    ast_moh_stop(chan);
04129    ast_channel_lock(chan);
04130    ast_setstate(tmpchan, chan->_state);
04131    tmpchan->readformat = chan->readformat;
04132    tmpchan->writeformat = chan->writeformat;
04133    ast_channel_masquerade(tmpchan, chan);
04134    ast_channel_lock(tmpchan);
04135    ast_do_masquerade(tmpchan);
04136    /* when returning from bridge, the channel will continue at the next priority */
04137    ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
04138    ast_channel_unlock(tmpchan);
04139    ast_channel_unlock(chan);
04140 }
04141 
04142 /*!
04143  * \brief Bridge channels together
04144  * \param s
04145  * \param m
04146  * 
04147  * Make sure valid channels were specified, 
04148  * send errors if any of the channels could not be found/locked, answer channels if needed,
04149  * create the placeholder channels and grab the other channels 
04150  * make the channels compatible, send error if we fail doing so 
04151  * setup the bridge thread object and start the bridge.
04152  * 
04153  * \retval 0 on success or on incorrect use.
04154  * \retval 1 on failure to bridge channels.
04155 */
04156 static int action_bridge(struct mansession *s, const struct message *m)
04157 {
04158    const char *channela = astman_get_header(m, "Channel1");
04159    const char *channelb = astman_get_header(m, "Channel2");
04160    const char *playtone = astman_get_header(m, "Tone");
04161    struct ast_channel *chana = NULL, *chanb = NULL;
04162    struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
04163    struct ast_bridge_thread_obj *tobj = NULL;
04164 
04165    /* make sure valid channels were specified */
04166    if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
04167       astman_send_error(s, m, "Missing channel parameter in request");
04168       return 0;
04169    }
04170 
04171    /* The same code must be executed for chana and chanb.  To avoid a
04172     * theoretical deadlock, this code is separated so both chana and chanb will
04173     * not hold locks at the same time. */
04174 
04175    /* Start with chana */
04176    chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
04177 
04178    /* send errors if any of the channels could not be found/locked */
04179    if (!chana) {
04180       char buf[256];
04181       snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
04182       astman_send_error(s, m, buf);
04183       return 0;
04184    }
04185 
04186    /* Answer the channels if needed */
04187    if (chana->_state != AST_STATE_UP)
04188       ast_answer(chana);
04189 
04190    /* create the placeholder channels and grab the other channels */
04191    if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
04192       NULL, NULL, 0, "Bridge/%s", chana->name))) {
04193       astman_send_error(s, m, "Unable to create temporary channel!");
04194       ast_channel_unlock(chana);
04195       return 1;
04196    }
04197 
04198    do_bridge_masquerade(chana, tmpchana);
04199    ast_channel_unlock(chana);
04200    chana = NULL;
04201 
04202    /* now do chanb */
04203    chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
04204    /* send errors if any of the channels could not be found/locked */
04205    if (!chanb) {
04206       char buf[256];
04207       snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
04208       ast_hangup(tmpchana);
04209       astman_send_error(s, m, buf);
04210       return 0;
04211    }
04212 
04213    /* Answer the channels if needed */
04214    if (chanb->_state != AST_STATE_UP)
04215       ast_answer(chanb);
04216 
04217    /* create the placeholder channels and grab the other channels */
04218    if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
04219       NULL, NULL, 0, "Bridge/%s", chanb->name))) {
04220       astman_send_error(s, m, "Unable to create temporary channels!");
04221       ast_hangup(tmpchana);
04222       ast_channel_unlock(chanb);
04223       return 1;
04224    }
04225    do_bridge_masquerade(chanb, tmpchanb);
04226    ast_channel_unlock(chanb);
04227    chanb = NULL;
04228 
04229    /* make the channels compatible, send error if we fail doing so */
04230    if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
04231       ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
04232       astman_send_error(s, m, "Could not make channels compatible for manager bridge");
04233       ast_hangup(tmpchana);
04234       ast_hangup(tmpchanb);
04235       return 1;
04236    }
04237 
04238    /* setup the bridge thread object and start the bridge */
04239    if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
04240       ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
04241       astman_send_error(s, m, "Unable to spawn a new bridge thread");
04242       ast_hangup(tmpchana);
04243       ast_hangup(tmpchanb);
04244       return 1;
04245    }
04246 
04247    tobj->chan = tmpchana;
04248    tobj->peer = tmpchanb;
04249    tobj->return_to_pbx = 1;
04250 
04251    if (ast_true(playtone)) {
04252       if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
04253          if (ast_waitstream(tmpchanb, "") < 0)
04254             ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
04255       }
04256    }
04257 
04258    bridge_call_thread_launch(tobj);
04259 
04260    astman_send_ack(s, m, "Launched bridge thread with success");
04261 
04262    return 0;
04263 }
04264 
04265 /*!
04266  * \brief CLI command to list parked calls
04267  * \param e 
04268  * \param cmd
04269  * \param a
04270  *  
04271  * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
04272  * \retval CLI_SUCCESS on success.
04273  * \retval CLI_SHOWUSAGE on incorrect number of arguments.
04274  * \retval NULL when tab completion is used.
04275 */
04276 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04277 {
04278    struct parkeduser *cur;
04279    int numparked = 0;
04280    struct ao2_iterator iter;
04281    struct ast_parkinglot *curlot;
04282 
04283    switch (cmd) {
04284    case CLI_INIT:
04285       e->command = "parkedcalls show";
04286       e->usage =
04287          "Usage: parkedcalls show\n"
04288          "       List currently parked calls\n";
04289       return NULL;
04290    case CLI_GENERATE:
04291       return NULL;
04292    }
04293 
04294    if (a->argc > e->args)
04295       return CLI_SHOWUSAGE;
04296 
04297    ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
04298       , "Context", "Extension", "Pri", "Timeout");
04299 
04300    iter = ao2_iterator_init(parkinglots, 0);
04301    while ((curlot = ao2_iterator_next(&iter))) {
04302       int lotparked = 0;
04303       ast_cli(a->fd, "*** Parking lot: %s\n", curlot->name);
04304 
04305       AST_LIST_LOCK(&curlot->parkings);
04306       AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
04307          ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
04308             ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
04309             ,cur->priority,
04310             (long)(cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL)) );
04311          numparked++;
04312          numparked += lotparked;
04313       }
04314       AST_LIST_UNLOCK(&curlot->parkings);
04315       if (lotparked)
04316          ast_cli(a->fd, "   %d parked call%s in parking lot %s\n", lotparked, ESS(lotparked), curlot->name);
04317 
04318       ao2_ref(curlot, -1);
04319    }
04320 
04321    ast_cli(a->fd, "---\n%d parked call%s in total.\n", numparked, ESS(numparked));
04322 
04323    return CLI_SUCCESS;
04324 }
04325 
04326 static struct ast_cli_entry cli_features[] = {
04327    AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
04328    AST_CLI_DEFINE(handle_features_reload, "Reloads configured features"),
04329    AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls"),
04330 };
04331 
04332 /*! 
04333  * \brief Dump parking lot status
04334  * \param s
04335  * \param m
04336  * 
04337  * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
04338  * \return Always RESULT_SUCCESS 
04339 */
04340 static int manager_parking_status(struct mansession *s, const struct message *m)
04341 {
04342    struct parkeduser *cur;
04343    const char *id = astman_get_header(m, "ActionID");
04344    char idText[256] = "";
04345    struct ao2_iterator iter;
04346    struct ast_parkinglot *curlot;
04347 
04348    if (!ast_strlen_zero(id))
04349       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
04350 
04351    astman_send_ack(s, m, "Parked calls will follow");
04352 
04353    iter = ao2_iterator_init(parkinglots, 0);
04354    while ((curlot = ao2_iterator_next(&iter))) {
04355 
04356       AST_LIST_LOCK(&curlot->parkings);
04357       AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
04358          astman_append(s, "Event: ParkedCall\r\n"
04359             "Exten: %d\r\n"
04360             "Channel: %s\r\n"
04361             "From: %s\r\n"
04362             "Timeout: %ld\r\n"
04363             "CallerIDNum: %s\r\n"
04364             "CallerIDName: %s\r\n"
04365             "%s"
04366             "\r\n",
04367             cur->parkingnum, cur->chan->name, cur->peername,
04368             (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
04369             S_OR(cur->chan->cid.cid_num, ""),   /* XXX in other places it is <unknown> */
04370             S_OR(cur->chan->cid.cid_name, ""),
04371             idText);
04372       }
04373       AST_LIST_UNLOCK(&curlot->parkings);
04374       ao2_ref(curlot, -1);
04375    }
04376 
04377    astman_append(s,
04378       "Event: ParkedCallsComplete\r\n"
04379       "%s"
04380       "\r\n",idText);
04381 
04382 
04383    return RESULT_SUCCESS;
04384 }
04385 
04386 static char mandescr_park[] =
04387 "Description: Park a channel.\n"
04388 "Variables: (Names marked with * are required)\n"
04389 "  *Channel: Channel name to park\n"
04390 "  *Channel2: Channel to announce park info to (and return to if timeout)\n"
04391 "  Timeout: Number of milliseconds to wait before callback.\n";  
04392 
04393 /*!
04394  * \brief Create manager event for parked calls
04395  * \param s
04396  * \param m
04397  *
04398  * Get channels involved in park, create event.
04399  * \return Always 0
04400 */
04401 static int manager_park(struct mansession *s, const struct message *m)
04402 {
04403    const char *channel = astman_get_header(m, "Channel");
04404    const char *channel2 = astman_get_header(m, "Channel2");
04405    const char *timeout = astman_get_header(m, "Timeout");
04406    char buf[BUFSIZ];
04407    int to = 0;
04408    int res = 0;
04409    int parkExt = 0;
04410    struct ast_channel *ch1, *ch2;
04411 
04412    if (ast_strlen_zero(channel)) {
04413       astman_send_error(s, m, "Channel not specified");
04414       return 0;
04415    }
04416 
04417    if (ast_strlen_zero(channel2)) {
04418       astman_send_error(s, m, "Channel2 not specified");
04419       return 0;
04420    }
04421 
04422    ch1 = ast_get_channel_by_name_locked(channel);
04423    if (!ch1) {
04424       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
04425       astman_send_error(s, m, buf);
04426       return 0;
04427    }
04428 
04429    ch2 = ast_get_channel_by_name_locked(channel2);
04430    if (!ch2) {
04431       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
04432       astman_send_error(s, m, buf);
04433       ast_channel_unlock(ch1);
04434       return 0;
04435    }
04436 
04437    if (!ast_strlen_zero(timeout)) {
04438       sscanf(timeout, "%30d", &to);
04439    }
04440 
04441    res = ast_masq_park_call(ch1, ch2, to, &parkExt);
04442    if (!res) {
04443       ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
04444       astman_send_ack(s, m, "Park successful");
04445    } else {
04446       astman_send_error(s, m, "Park failure");
04447    }
04448 
04449    ast_channel_unlock(ch1);
04450    ast_channel_unlock(ch2);
04451 
04452    return 0;
04453 }
04454 
04455 static int find_channel_by_group(struct ast_channel *c, void *data) {
04456    struct ast_channel *chan = data;
04457 
04458    return !c->pbx &&
04459       /* Accessing 'chan' here is safe without locking, because there is no way for
04460          the channel do disappear from under us at this point.  pickupgroup *could*
04461          change while we're here, but that isn't a problem. */
04462       (c != chan) &&
04463       (chan->pickupgroup & c->callgroup) &&
04464       ((c->_state == AST_STATE_RINGING) || (c->_state == AST_STATE_RING));
04465 }
04466 
04467 /*!
04468  * \brief Pickup a call
04469  * \param chan channel that initiated pickup.
04470  *
04471  * Walk list of channels, checking it is not itself, channel is pbx one,
04472  * check that the callgroup for both channels are the same and the channel is ringing.
04473  * Answer calling channel, flag channel as answered on queue, masq channels together.
04474 */
04475 int ast_pickup_call(struct ast_channel *chan)
04476 {
04477    struct ast_channel *cur = ast_channel_search_locked(find_channel_by_group, chan);
04478 
04479    if (cur) {
04480       int res = -1;
04481       ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
04482       res = ast_answer(chan);
04483       if (res)
04484          ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
04485       res = ast_queue_control(chan, AST_CONTROL_ANSWER);
04486       if (res)
04487          ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
04488       res = ast_channel_masquerade(cur, chan);
04489       if (res)
04490          ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);     /* Done */
04491       if (!ast_strlen_zero(pickupsound)) {
04492          ast_stream_and_wait(cur, pickupsound, "");
04493       }
04494       ast_channel_unlock(cur);
04495       return res;
04496    } else   {
04497       ast_debug(1, "No call pickup possible...\n");
04498       if (!ast_strlen_zero(pickupfailsound)) {
04499          ast_stream_and_wait(chan, pickupfailsound, "");
04500       }
04501    }
04502    return -1;
04503 }
04504 
04505 static char *app_bridge = "Bridge";
04506 
04507 enum {
04508    BRIDGE_OPT_PLAYTONE = (1 << 0),
04509 };
04510 
04511 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
04512    AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
04513 END_OPTIONS );
04514 
04515 /*!
04516  * \brief Bridge channels
04517  * \param chan
04518  * \param data channel to bridge with.
04519  * 
04520  * Split data, check we aren't bridging with ourself, check valid channel,
04521  * answer call if not already, check compatible channels, setup bridge config
04522  * now bridge call, if transfered party hangs up return to PBX extension.
04523 */
04524 static int bridge_exec(struct ast_channel *chan, void *data)
04525 {
04526    struct ast_channel *current_dest_chan, *final_dest_chan;
04527    char *tmp_data  = NULL;
04528    struct ast_flags opts = { 0, };
04529    struct ast_bridge_config bconfig = { { 0, }, };
04530 
04531    AST_DECLARE_APP_ARGS(args,
04532       AST_APP_ARG(dest_chan);
04533       AST_APP_ARG(options);
04534    );
04535    
04536    if (ast_strlen_zero(data)) {
04537       ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
04538       return -1;
04539    }
04540 
04541    tmp_data = ast_strdupa(data);
04542    AST_STANDARD_APP_ARGS(args, tmp_data);
04543    if (!ast_strlen_zero(args.options))
04544       ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
04545 
04546    /* avoid bridge with ourselves */
04547    if (!strcmp(chan->name, args.dest_chan)) {
04548       ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
04549       manager_event(EVENT_FLAG_CALL, "BridgeExec",
04550                "Response: Failed\r\n"
04551                "Reason: Unable to bridge channel to itself\r\n"
04552                "Channel1: %s\r\n"
04553                "Channel2: %s\r\n",
04554                chan->name, args.dest_chan);
04555       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
04556       return 0;
04557    }
04558 
04559    /* make sure we have a valid end point */
04560    if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan, 
04561       strlen(args.dest_chan)))) {
04562       ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
04563          "cannot get its lock\n", args.dest_chan);
04564       manager_event(EVENT_FLAG_CALL, "BridgeExec",
04565                "Response: Failed\r\n"
04566                "Reason: Cannot grab end point\r\n"
04567                "Channel1: %s\r\n"
04568                "Channel2: %s\r\n", chan->name, args.dest_chan);
04569       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
04570       return 0;
04571    }
04572 
04573    /* answer the channel if needed */
04574    if (current_dest_chan->_state != AST_STATE_UP)
04575       ast_answer(current_dest_chan);
04576 
04577    /* try to allocate a place holder where current_dest_chan will be placed */
04578    if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
04579       NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
04580       ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
04581       manager_event(EVENT_FLAG_CALL, "BridgeExec",
04582                "Response: Failed\r\n"
04583                "Reason: cannot create placeholder\r\n"
04584                "Channel1: %s\r\n"
04585                "Channel2: %s\r\n", chan->name, args.dest_chan);
04586    }
04587    do_bridge_masquerade(current_dest_chan, final_dest_chan);
04588 
04589    ast_channel_unlock(current_dest_chan);
04590 
04591    /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
04592    /* try to make compatible, send error if we fail */
04593    if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
04594       ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
04595       manager_event(EVENT_FLAG_CALL, "BridgeExec",
04596                "Response: Failed\r\n"
04597                "Reason: Could not make channels compatible for bridge\r\n"
04598                "Channel1: %s\r\n"
04599                "Channel2: %s\r\n", chan->name, final_dest_chan->name);
04600       ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
04601       pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
04602       return 0;
04603    }
04604 
04605    /* Report that the bridge will be successfull */
04606    manager_event(EVENT_FLAG_CALL, "BridgeExec",
04607             "Response: Success\r\n"
04608             "Channel1: %s\r\n"
04609             "Channel2: %s\r\n", chan->name, final_dest_chan->name);
04610 
04611    /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */  
04612    if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
04613       if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
04614          if (ast_waitstream(final_dest_chan, "") < 0)
04615             ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
04616       }
04617    }
04618    
04619    /* do the bridge */
04620    ast_bridge_call(chan, final_dest_chan, &bconfig);
04621 
04622    /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
04623    pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
04624    if (!ast_check_hangup(final_dest_chan)) {
04625       ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n", 
04626          final_dest_chan->context, final_dest_chan->exten, 
04627          final_dest_chan->priority, final_dest_chan->name);
04628 
04629       if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
04630          ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
04631          ast_hangup(final_dest_chan);
04632       } else
04633          ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
04634    } else {
04635       ast_debug(1, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
04636       ast_hangup(final_dest_chan);
04637    }
04638 
04639    return 0;
04640 }
04641 
04642 int ast_features_init(void)
04643 {
04644    int res;
04645 
04646    ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
04647 
04648    parkinglots = ao2_container_alloc(7, parkinglot_hash_cb, parkinglot_cmp_cb);
04649 
04650    if ((res = load_config()))
04651       return res;
04652    ast_cli_register_multiple(cli_features, ARRAY_LEN(cli_features));
04653    ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
04654    res = ast_register_application2(parkedcall, park_exec, NULL, NULL, NULL);
04655    if (!res)
04656       res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
04657    if (!res) {
04658       ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
04659       ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park, "Park a channel", mandescr_park); 
04660       ast_manager_register2("Bridge", EVENT_FLAG_CALL, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
04661    }
04662 
04663    res |= ast_devstate_prov_add("Park", metermaidstate);
04664 
04665    return res;
04666 }

Generated by  doxygen 1.6.2