Thu Jul 9 13:40:33 2009

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

Generated on Thu Jul 9 13:40:34 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7