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

Generated on Wed Aug 18 22:33:51 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7