Tue Mar 2 17:31:49 2010

Asterisk developer's documentation


features.c

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

Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1