Tue Aug 24 2010 19:41:30

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