Fri Sep 11 13:45:01 2009

Asterisk developer's documentation


res_features.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, 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 /*** MODULEINFO
00027         <depend>chan_local</depend>
00028  ***/
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211596 $")
00033 
00034 #include <pthread.h>
00035 #include <stdlib.h>
00036 #include <errno.h>
00037 #include <unistd.h>
00038 #include <string.h>
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041 #include <sys/time.h>
00042 #include <sys/signal.h>
00043 #include <netinet/in.h>
00044 
00045 #include "asterisk/lock.h"
00046 #include "asterisk/file.h"
00047 #include "asterisk/logger.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/pbx.h"
00050 #include "asterisk/options.h"
00051 #include "asterisk/causes.h"
00052 #include "asterisk/module.h"
00053 #include "asterisk/translate.h"
00054 #include "asterisk/app.h"
00055 #include "asterisk/say.h"
00056 #include "asterisk/features.h"
00057 #include "asterisk/musiconhold.h"
00058 #include "asterisk/config.h"
00059 #include "asterisk/cli.h"
00060 #include "asterisk/manager.h"
00061 #include "asterisk/utils.h"
00062 #include "asterisk/adsi.h"
00063 #include "asterisk/devicestate.h"
00064 #include "asterisk/monitor.h"
00065 #include "asterisk/global_datastores.h"
00066 
00067 #define DEFAULT_PARK_TIME 45000
00068 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
00069 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 1000
00070 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
00071 
00072 #define AST_MAX_WATCHERS 256
00073 #define MAX_DIAL_FEATURE_OPTIONS 30
00074 
00075 #define FEATURE_RETURN_HANGUP                  -1
00076 #define FEATURE_RETURN_SUCCESSBREAK             0
00077 #define FEATURE_RETURN_PASSDIGITS               21
00078 #define FEATURE_RETURN_STOREDIGITS              22
00079 #define FEATURE_RETURN_SUCCESS                  23
00080 #define FEATURE_RETURN_KEEPTRYING               24
00081 #define FEATURE_RETURN_PARKFAILED               25
00082 
00083 enum {
00084    AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
00085    AST_FEATURE_FLAG_ONPEER =    (1 << 1),
00086    AST_FEATURE_FLAG_ONSELF =    (1 << 2),
00087    AST_FEATURE_FLAG_BYCALLEE =  (1 << 3),
00088    AST_FEATURE_FLAG_BYCALLER =  (1 << 4),
00089    AST_FEATURE_FLAG_BYBOTH  =   (3 << 3),
00090 };
00091 
00092 static char *parkedcall = "ParkedCall";
00093 
00094 static int parkaddhints = 0;                               /*!< Add parking hints automatically */
00095 static int parkingtime = DEFAULT_PARK_TIME;                /*!< No more than 45 seconds parked before you do something with them */
00096 static char parking_con[AST_MAX_EXTENSION];                /*!< Context for which parking is made accessible */
00097 static char parking_con_dial[AST_MAX_EXTENSION];           /*!< Context for dialback for parking (KLUDGE) */
00098 static char parking_ext[AST_MAX_EXTENSION];                /*!< Extension you type to park the call */
00099 static char pickup_ext[AST_MAX_EXTENSION];                 /*!< Call pickup extension */
00100 static char parkmohclass[MAX_MUSICCLASS];                  /*!< Music class used for parking */
00101 static int parking_start;                                  /*!< First available extension for parking */
00102 static int parking_stop;                                   /*!< Last available extension for parking */
00103 
00104 static int parkedcalltransfers;                            /*!< Who can REDIRECT after picking up a parked a call */
00105 static int parkedcallreparking;                            /*!< Who can PARKCALL after picking up a parked call */
00106 static int parkedcallhangup;                               /*!< Who can DISCONNECT after picking up a parked call */
00107 static int parkedcallrecording;                            /*!< Who can AUTOMON after picking up a parked call */
00108 
00109 static char courtesytone[256];                             /*!< Courtesy tone */
00110 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
00111 static char xfersound[256];                                /*!< Call transfer sound */
00112 static char xferfailsound[256];                            /*!< Call transfer failure sound */
00113 
00114 static int parking_offset;
00115 static int parkfindnext;
00116 
00117 static int adsipark;
00118 
00119 static int transferdigittimeout;
00120 static int featuredigittimeout;
00121 
00122 static int atxfernoanswertimeout;
00123 
00124 static char *registrar = "res_features";        /*!< Registrar for operations */
00125 
00126 /* module and CLI command definitions */
00127 static char *synopsis = "Answer a parked call";
00128 
00129 static char *descrip = "ParkedCall(exten):"
00130 "Used to connect to a parked call.  This application is always\n"
00131 "registered internally and does not need to be explicitly added\n"
00132 "into the dialplan, although you should include the 'parkedcalls'\n"
00133 "context.\n";
00134 
00135 static char *parkcall = PARK_APP_NAME;
00136 
00137 static char *synopsis2 = "Park yourself";
00138 
00139 static char *descrip2 = "Park():"
00140 "Used to park yourself (typically in combination with a supervised\n"
00141 "transfer to know the parking space). This application is always\n"
00142 "registered internally and does not need to be explicitly added\n"
00143 "into the dialplan, although you should include the 'parkedcalls'\n"
00144 "context (or the context specified in features.conf).\n\n"
00145 "If you set the PARKINGEXTEN variable to an extension in your\n"
00146 "parking context, park() will park the call on that extension, unless\n"
00147 "it already exists. In that case, execution will continue at next\n"
00148 "priority.\n" ;
00149 
00150 static struct ast_app *monitor_app = NULL;
00151 static int monitor_ok = 1;
00152 
00153 struct parkeduser {
00154    struct ast_channel *chan;                   /*!< Parking channel */
00155    struct timeval start;                       /*!< Time the parking started */
00156    int parkingnum;                             /*!< Parking lot */
00157    char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
00158    char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
00159    char exten[AST_MAX_EXTENSION];
00160    int priority;
00161    int parkingtime;                            /*!< Maximum length in parking lot before return */
00162    int notquiteyet;
00163    char peername[1024];
00164    unsigned char moh_trys;
00165    struct parkeduser *next;
00166 };
00167 
00168 static struct parkeduser *parkinglot;
00169 
00170 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
00171 
00172 static pthread_t parking_thread;
00173 
00174 struct ast_dial_features {
00175    struct ast_flags features_caller;
00176    struct ast_flags features_callee;
00177    int is_caller;
00178 };
00179 
00180 static void *dial_features_duplicate(void *data)
00181 {
00182    struct ast_dial_features *df = data, *df_copy;
00183 
00184    if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
00185       return NULL;
00186    }
00187 
00188    memcpy(df_copy, df, sizeof(*df));
00189 
00190    return df_copy;
00191 }
00192 
00193 static void dial_features_destroy(void *data)
00194 {
00195    struct ast_dial_features *df = data;
00196    if (df) {
00197       ast_free(df);
00198    }
00199 }
00200 
00201 const struct ast_datastore_info dial_features_info = {
00202    .type = "dial-features",
00203    .destroy = dial_features_destroy,
00204    .duplicate = dial_features_duplicate,
00205 };
00206 
00207 char *ast_parking_ext(void)
00208 {
00209    return parking_ext;
00210 }
00211 
00212 char *ast_pickup_ext(void)
00213 {
00214    return pickup_ext;
00215 }
00216 
00217 struct ast_bridge_thread_obj 
00218 {
00219    struct ast_bridge_config bconfig;
00220    struct ast_channel *chan;
00221    struct ast_channel *peer;
00222 };
00223 
00224 /*! \brief store context, priority and extension */
00225 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
00226 {
00227    ast_copy_string(chan->context, context, sizeof(chan->context));
00228    ast_copy_string(chan->exten, ext, sizeof(chan->exten));
00229    chan->priority = pri;
00230 }
00231 
00232 static void check_goto_on_transfer(struct ast_channel *chan) 
00233 {
00234    struct ast_channel *xferchan;
00235    const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
00236    char *x, *goto_on_transfer;
00237    struct ast_frame *f;
00238 
00239    if (ast_strlen_zero(val))
00240       return;
00241 
00242    goto_on_transfer = ast_strdupa(val);
00243 
00244    if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", chan->name)))
00245       return;
00246 
00247    for (x = goto_on_transfer; x && *x; x++) {
00248       if (*x == '^')
00249          *x = '|';
00250    }
00251    /* Make formats okay */
00252    xferchan->readformat = chan->readformat;
00253    xferchan->writeformat = chan->writeformat;
00254    ast_channel_masquerade(xferchan, chan);
00255    ast_parseable_goto(xferchan, goto_on_transfer);
00256    xferchan->_state = AST_STATE_UP;
00257    ast_clear_flag(xferchan, AST_FLAGS_ALL);  
00258    xferchan->_softhangup = 0;
00259    if ((f = ast_read(xferchan))) {
00260       ast_frfree(f);
00261       f = NULL;
00262       ast_pbx_start(xferchan);
00263    } else {
00264       ast_hangup(xferchan);
00265    }
00266 }
00267 
00268 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, const char *language);
00269 
00270 static void *ast_bridge_call_thread(void *data)
00271 {
00272    struct ast_bridge_thread_obj *tobj = data;
00273 
00274    tobj->chan->appl = "Transferred Call";
00275    tobj->chan->data = tobj->peer->name;
00276    tobj->peer->appl = "Transferred Call";
00277    tobj->peer->data = tobj->chan->name;
00278 
00279    ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
00280    ast_hangup(tobj->chan);
00281    ast_hangup(tobj->peer);
00282    bzero(tobj, sizeof(*tobj)); /*! \todo XXX for safety */
00283    free(tobj);
00284    return NULL;
00285 }
00286 
00287 static void ast_bridge_call_thread_launch(void *data) 
00288 {
00289    pthread_t thread;
00290    pthread_attr_t attr;
00291    struct sched_param sched;
00292 
00293    pthread_attr_init(&attr);
00294    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00295    ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
00296    pthread_attr_destroy(&attr);
00297    memset(&sched, 0, sizeof(sched));
00298    pthread_setschedparam(thread, SCHED_RR, &sched);
00299 }
00300 
00301 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
00302 {
00303    int res;
00304    int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
00305    char tmp[256];
00306    char *message[5] = {NULL, NULL, NULL, NULL, NULL};
00307 
00308    snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
00309    message[0] = tmp;
00310    res = ast_adsi_load_session(chan, NULL, 0, 1);
00311    if (res == -1)
00312       return res;
00313    return ast_adsi_print(chan, message, justify, 1);
00314 }
00315 
00316 /*! \brief Notify metermaids that we've changed an extension */
00317 static void notify_metermaids(char *exten, char *context)
00318 {
00319    if (option_debug > 3)
00320       ast_log(LOG_DEBUG, "Notification of state change to metermaids %s@%s\n", exten, context);
00321 
00322    /* Send notification to devicestate subsystem */
00323    ast_device_state_changed("park:%s@%s", exten, context);
00324    return;
00325 }
00326 
00327 /*! \brief metermaids callback from devicestate.c */
00328 static int metermaidstate(const char *data)
00329 {
00330    int res = AST_DEVICE_INVALID;
00331    char *context = ast_strdupa(data);
00332    char *exten;
00333 
00334    exten = strsep(&context, "@");
00335    if (!context)
00336       return res;
00337    
00338    if (option_debug > 3)
00339       ast_log(LOG_DEBUG, "Checking state of exten %s in context %s\n", exten, context);
00340 
00341    res = ast_exists_extension(NULL, context, exten, 1, NULL);
00342 
00343    if (!res)
00344       return AST_DEVICE_NOT_INUSE;
00345    else
00346       return AST_DEVICE_INUSE;
00347 }
00348 
00349 static struct parkeduser *park_space_reserve(struct ast_channel *chan)
00350 {
00351    struct parkeduser *pu, *cur;
00352    int i, parking_space = -1, parking_range;
00353    const char *parkingexten;
00354 
00355    /* Allocate memory for parking data */
00356    if (!(pu = ast_calloc(1, sizeof(*pu)))) 
00357       return NULL;
00358 
00359    /* Lock parking lot */
00360    ast_mutex_lock(&parking_lock);
00361    /* Check for channel variable PARKINGEXTEN */
00362    parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
00363    if (!ast_strlen_zero(parkingexten)) {
00364       /*!\note The API forces us to specify a numeric parking slot, even
00365        * though the architecture would tend to support non-numeric extensions
00366        * (as are possible with SIP, for example).  Hence, we enforce that
00367        * limitation here.  If extout was not numeric, we could permit
00368        * arbitrary non-numeric extensions.
00369        */
00370       if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space < 0) {
00371          ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
00372          ast_mutex_unlock(&parking_lock);
00373          free(pu);
00374          return NULL;
00375       }
00376       snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
00377 
00378       if (ast_exists_extension(NULL, parking_con, pu->parkingexten, 1, NULL)) {
00379          ast_mutex_unlock(&parking_lock);
00380          ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
00381          free(pu);
00382          return NULL;
00383       }
00384    } else {
00385       /* Select parking space within range */
00386       parking_range = parking_stop - parking_start+1;
00387       for (i = 0; i < parking_range; i++) {
00388          parking_space = (i + parking_offset) % parking_range + parking_start;
00389          cur = parkinglot;
00390          while(cur) {
00391             if (cur->parkingnum == parking_space) 
00392                break;
00393             cur = cur->next;
00394          }
00395          if (!cur)
00396             break;
00397       }
00398 
00399       if (!(i < parking_range)) {
00400          ast_log(LOG_WARNING, "No more parking spaces\n");
00401          ast_mutex_unlock(&parking_lock);
00402          free(pu);
00403          return NULL;
00404       }
00405       /* Set pointer for next parking */
00406       if (parkfindnext) 
00407          parking_offset = parking_space - parking_start + 1;
00408       snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
00409    }
00410    
00411    pu->notquiteyet = 1;
00412    pu->parkingnum = parking_space;
00413    pu->next = parkinglot;
00414    parkinglot = pu;
00415    ast_mutex_unlock(&parking_lock);
00416 
00417    return pu;
00418 }
00419 
00420 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)
00421 {
00422    struct ast_context *con;
00423    int parkingnum_copy;
00424    const char *event_from;
00425 
00426    /* Get a valid space if not already done */
00427    if (pu == NULL)
00428       pu = park_space_reserve(chan);
00429    if (pu == NULL)
00430       return 1; /* Continue execution if possible */
00431 
00432    snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", pu->parkingnum);
00433    
00434    chan->appl = "Parked Call";
00435    chan->data = NULL; 
00436 
00437    pu->chan = chan;
00438    
00439    /* Put the parked channel on hold if we have two different channels */
00440    if (chan != peer) {
00441       ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
00442          S_OR(parkmohclass, NULL),
00443          !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
00444    }
00445    
00446    pu->start = ast_tvnow();
00447    pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
00448    if (extout)
00449       *extout = pu->parkingnum;
00450 
00451    if (peer) { 
00452       /* This is so ugly that it hurts, but implementing get_base_channel() on local channels
00453          could have ugly side effects.  We could have transferer<->local,1<->local,2<->parking
00454          and we need the callback name to be that of transferer.  Since local,1/2 have the same
00455          name we can be tricky and just grab the bridged channel from the other side of the local
00456       */
00457       if (!strcasecmp(peer->tech->type, "Local")) {
00458          struct ast_channel *tmpchan, *base_peer;
00459          char other_side[AST_CHANNEL_NAME];
00460          char *c;
00461          ast_copy_string(other_side, S_OR(orig_chan_name, peer->name), sizeof(other_side));
00462          if ((c = strrchr(other_side, ','))) {
00463             *++c = '1';
00464          }
00465          if ((tmpchan = ast_get_channel_by_name_locked(other_side))) {
00466             if ((base_peer = ast_bridged_channel(tmpchan))) {
00467                ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
00468             }
00469             ast_channel_unlock(tmpchan);
00470          }
00471       } else {
00472          ast_copy_string(pu->peername, S_OR(orig_chan_name, peer->name), sizeof(pu->peername));
00473       }
00474    }
00475 
00476    /* Remember what had been dialed, so that if the parking
00477       expires, we try to come back to the same place */
00478    ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
00479    ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
00480    pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
00481    parkingnum_copy = pu->parkingnum;
00482 
00483    /* If parking a channel directly (peer == chan), don't quite yet get parking running on it.
00484      * All parking lot entires are put into the parking lot with notquiteyet on. */
00485    if (peer != chan) 
00486       pu->notquiteyet = 0;
00487 
00488    if (option_verbose > 1) 
00489       ast_verbose(VERBOSE_PREFIX_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));
00490 
00491    if (peer) {
00492       event_from = peer->name;
00493    } else {
00494       event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
00495    }
00496 
00497    manager_event(EVENT_FLAG_CALL, "ParkedCall",
00498       "Exten: %s\r\n"
00499       "Channel: %s\r\n"
00500       "From: %s\r\n"
00501       "Timeout: %ld\r\n"
00502       "CallerID: %s\r\n"
00503       "CallerIDName: %s\r\n",
00504       pu->parkingexten, pu->chan->name, event_from ? event_from : "",
00505       (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
00506       S_OR(pu->chan->cid.cid_num, "<unknown>"),
00507       S_OR(pu->chan->cid.cid_name, "<unknown>")
00508       );
00509 
00510    if (peer && adsipark && ast_adsi_available(peer)) {
00511       adsi_announce_park(peer, pu->parkingexten);  /* Only supports parking numbers */
00512       ast_adsi_unload_session(peer);
00513    }
00514 
00515    con = ast_context_find(parking_con);
00516    if (!con) 
00517       con = ast_context_create(NULL, parking_con, registrar);
00518    if (!con)   /* Still no context? Bad */
00519       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
00520    if (con) {
00521       if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free_ptr, registrar)) {
00522          notify_metermaids(pu->parkingexten, parking_con);
00523       }
00524    }
00525 
00526    /* Wake up the (presumably select()ing) thread */
00527    pthread_kill(parking_thread, SIGURG);
00528 
00529    /* Only say number if it's a number and the channel hasn't been masqueraded away */
00530    if (peer && (ast_strlen_zero(orig_chan_name) || !strcasecmp(peer->name, orig_chan_name))) {
00531       /* Make sure we don't start saying digits to the channel being parked */
00532       ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
00533       /* Tell the peer channel the number of the parking space */
00534       ast_say_digits(peer, parkingnum_copy, "", peer->language);
00535       ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
00536    }
00537 
00538    if (peer == chan) { /* pu->notquiteyet = 1 */
00539       /* Wake up parking thread if we're really done */
00540       ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
00541          S_OR(parkmohclass, NULL),
00542          !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
00543       pu->notquiteyet = 0;
00544       pthread_kill(parking_thread, SIGURG);
00545    }
00546    return 0;
00547 }
00548 
00549 /*! \brief Park a call 
00550    \note We put the user in the parking list, then wake up the parking thread to be sure it looks
00551    after these channels too */
00552 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
00553 {
00554    return park_call_full(chan, peer, timeout, extout, NULL, NULL);
00555 }
00556 
00557 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)
00558 {
00559    struct ast_channel *chan;
00560    struct ast_frame *f;
00561    struct parkeduser *pu;
00562    int park_status;
00563 
00564    if ((pu = park_space_reserve(rchan)) == NULL) {
00565       if (peer)
00566          ast_stream_and_wait(peer, "beeperr", peer->language, "");
00567       return FEATURE_RETURN_PARKFAILED;
00568    }
00569 
00570    /* Make a new, fake channel that we'll use to masquerade in the real one */
00571    if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
00572       ast_log(LOG_WARNING, "Unable to create parked channel\n");
00573       return -1;
00574    }
00575 
00576    /* Make formats okay */
00577    chan->readformat = rchan->readformat;
00578    chan->writeformat = rchan->writeformat;
00579    ast_channel_masquerade(chan, rchan);
00580 
00581    /* Setup the extensions and such */
00582    set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
00583 
00584    /* Make the masq execute */
00585    if ((f = ast_read(chan))) {
00586       ast_frfree(f);
00587    }
00588 
00589    if (peer == rchan) {
00590       peer = chan;
00591    }
00592 
00593    if (!play_announcement || !orig_chan_name) {
00594       orig_chan_name = ast_strdupa(chan->name);
00595    }
00596 
00597    park_status = park_call_full(chan, peer, timeout, extout, orig_chan_name, pu);
00598    if (park_status == 1) {
00599       /* would be nice to play: "invalid parking extension" */
00600       ast_hangup(chan);
00601       return -1;
00602    }
00603 
00604    return 0;
00605 }
00606 
00607 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
00608 {
00609    return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
00610 }
00611 
00612 static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, const char *orig_chan_name)
00613 {
00614    return masq_park_call(rchan, peer, timeout, extout, 1, orig_chan_name);
00615 }
00616 
00617 /*! \brief
00618  * set caller and callee according to the direction
00619  */
00620 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
00621    struct ast_channel *peer, struct ast_channel *chan, int sense)
00622 {
00623    if (sense == FEATURE_SENSE_PEER) {
00624       *caller = peer;
00625       *callee = chan;
00626    } else {
00627       *callee = peer;
00628       *caller = chan;
00629    }
00630 }
00631 
00632 /*! \brief support routing for one touch call parking */
00633 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00634 {
00635    struct ast_channel *parker;
00636    struct ast_channel *parkee;
00637    int res = 0;
00638    struct ast_module_user *u;
00639    const char *orig_chan_name;
00640 
00641    u = ast_module_user_add(chan);
00642 
00643    set_peers(&parker, &parkee, peer, chan, sense);
00644    orig_chan_name = ast_strdupa(parker->name);
00645    /* we used to set chan's exten and priority to "s" and 1
00646       here, but this generates (in some cases) an invalid
00647       extension, and if "s" exists, could errantly
00648       cause execution of extensions you don't expect It
00649       makes more sense to let nature take its course
00650       when chan finishes, and let the pbx do its thing
00651       and hang up when the park is over.
00652    */
00653    if (chan->_state != AST_STATE_UP)
00654       res = ast_answer(chan);
00655    if (!res)
00656       res = ast_safe_sleep(chan, 1000);
00657 
00658    if (!res) { /* one direction used to call park_call.... */
00659       res = masq_park_call_announce(parkee, parker, 0, NULL, orig_chan_name);
00660       /* PBX should hangup zombie channel if a masquerade actually occurred (res=0) */
00661    }
00662 
00663    ast_module_user_remove(u);
00664    return res;
00665 }
00666 
00667 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00668 {
00669    char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
00670    int x = 0;
00671    size_t len;
00672    struct ast_channel *caller_chan, *callee_chan;
00673 
00674    if (!monitor_ok) {
00675       ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
00676       return -1;
00677    }
00678 
00679    if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
00680       monitor_ok = 0;
00681       ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
00682       return -1;
00683    }
00684 
00685    set_peers(&caller_chan, &callee_chan, peer, chan, sense);
00686 
00687    if (!ast_strlen_zero(courtesytone)) {
00688       if (ast_autoservice_start(callee_chan))
00689          return -1;
00690       if (ast_stream_and_wait(caller_chan, courtesytone, caller_chan->language, "")) {
00691          ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
00692          ast_autoservice_stop(callee_chan);
00693          return -1;
00694       }
00695       if (ast_autoservice_stop(callee_chan))
00696          return -1;
00697    }
00698    
00699    if (callee_chan->monitor) {
00700       if (option_verbose > 3)
00701          ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
00702       ast_monitor_stop(callee_chan, 1);
00703       return FEATURE_RETURN_SUCCESS;
00704    }
00705 
00706    if (caller_chan && callee_chan) {
00707       const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
00708       const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
00709 
00710       if (!touch_format)
00711          touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
00712 
00713       if (!touch_monitor)
00714          touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
00715    
00716       if (touch_monitor) {
00717          len = strlen(touch_monitor) + 50;
00718          args = alloca(len);
00719          touch_filename = alloca(len);
00720          snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
00721          snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
00722       } else {
00723          caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
00724          callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
00725          len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
00726          args = alloca(len);
00727          touch_filename = alloca(len);
00728          snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
00729          snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
00730       }
00731 
00732       for( x = 0; x < strlen(args); x++) {
00733          if (args[x] == '/')
00734             args[x] = '-';
00735       }
00736       
00737       if (option_verbose > 3)
00738          ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
00739 
00740       pbx_exec(callee_chan, monitor_app, args);
00741       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
00742       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
00743    
00744       return FEATURE_RETURN_SUCCESS;
00745    }
00746    
00747    ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");  
00748    return -1;
00749 }
00750 
00751 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00752 {
00753    if (option_verbose > 3)
00754       ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
00755    return FEATURE_RETURN_HANGUP;
00756 }
00757 
00758 static int finishup(struct ast_channel *chan)
00759 {
00760         ast_indicate(chan, AST_CONTROL_UNHOLD);
00761   
00762         return ast_autoservice_stop(chan);
00763 }
00764 
00765 /*! \brief Find the context for the transfer */
00766 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
00767 {
00768         const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
00769         if (ast_strlen_zero(s))
00770                 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
00771         if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
00772                 s = transferer->macrocontext;
00773         if (ast_strlen_zero(s))
00774                 s = transferer->context;
00775         return s;  
00776 }
00777 
00778 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00779 {
00780    struct ast_channel *transferer;
00781    struct ast_channel *transferee;
00782    const char *transferer_real_context;
00783    char xferto[256];
00784    int res;
00785    const char *orig_chan_name;
00786    int parkstatus = 0;
00787 
00788    set_peers(&transferer, &transferee, peer, chan, sense);
00789    orig_chan_name = ast_strdupa(transferer->name);
00790    transferer_real_context = real_ctx(transferer, transferee);
00791    /* Start autoservice on chan while we talk to the originator */
00792    ast_autoservice_start(transferee);
00793    ast_indicate(transferee, AST_CONTROL_HOLD);
00794 
00795    memset(xferto, 0, sizeof(xferto));
00796 
00797    /* Transfer */
00798    res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
00799    if (res < 0) {
00800       finishup(transferee);
00801       return -1; /* error ? */
00802    }
00803    if (res > 0)   /* If they've typed a digit already, handle it */
00804       xferto[0] = (char) res;
00805 
00806    ast_stopstream(transferer);
00807    res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
00808    if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
00809       finishup(transferee);
00810       return res;
00811    }
00812    if (!strcmp(xferto, ast_parking_ext())) {
00813       res = finishup(transferee);
00814       if (res)
00815          res = -1;
00816       else if (!(parkstatus = masq_park_call_announce(transferee, transferer, 0, NULL, orig_chan_name))) {  /* success */
00817          /* We return non-zero, but tell the PBX not to hang the channel when
00818             the thread dies -- We have to be careful now though.  We are responsible for 
00819             hanging up the channel, else it will never be hung up! */
00820          return 0;
00821       } else {
00822          ast_log(LOG_WARNING, "Unable to park call %s, parkstatus=%d\n", transferee->name, parkstatus);
00823       }
00824       /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
00825    } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
00826       pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
00827       pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
00828       res=finishup(transferee);
00829       if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
00830          transferer->cdr=ast_cdr_alloc();
00831          if (transferer->cdr) {
00832             ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
00833             ast_cdr_start(transferer->cdr);
00834          }
00835       }
00836       if (transferer->cdr) {
00837          struct ast_cdr *swap = transferer->cdr;
00838          /* swap cdrs-- it will save us some time & work */
00839          transferer->cdr = transferee->cdr;
00840          transferee->cdr = swap;
00841       }
00842       if (!transferee->pbx) {
00843          /* Doh!  Use our handy async_goto functions */
00844          if (option_verbose > 2) 
00845             ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
00846                         ,transferee->name, xferto, transferer_real_context);
00847          if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
00848             ast_log(LOG_WARNING, "Async goto failed :-(\n");
00849          res = -1;
00850       } else {
00851          /* Set the channel's new extension, since it exists, using transferer context */
00852          ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
00853          set_c_e_p(transferee, transferer_real_context, xferto, 0);
00854       }
00855       check_goto_on_transfer(transferer);
00856       return res;
00857    } else {
00858       if (option_verbose > 2) 
00859          ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
00860    }
00861    if (parkstatus != FEATURE_RETURN_PARKFAILED && ast_stream_and_wait(transferer, xferfailsound, transferer->language, AST_DIGIT_ANY) < 0 ) {
00862       finishup(transferee);
00863       return -1;
00864    }
00865    ast_stopstream(transferer);
00866    res = finishup(transferee);
00867    if (res) {
00868       if (option_verbose > 1)
00869          ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
00870       return res;
00871    }
00872    return FEATURE_RETURN_SUCCESS;
00873 }
00874 
00875 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
00876 {
00877    if (ast_channel_make_compatible(c, newchan) < 0) {
00878       ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
00879          c->name, newchan->name);
00880       ast_hangup(newchan);
00881       return -1;
00882    }
00883    return 0;
00884 }
00885 
00886 /*!
00887  * \brief Attended transfer implementation
00888  * \param chan transfered user
00889  * \param peer person transfering call
00890  * \param config
00891  * \param sense feature options
00892  * 
00893  * \param toExt
00894  * \param toCont
00895  * This is the actual implementation of attended transfer, it can be activated as a regular feature or through the AMI.
00896  * "toExt" is the extension to transfer to (default: ask for it on the transferer channel)
00897  * "toCont" is the context to transfer to (default: the one in which the transferer is)
00898  *
00899  * \return -1 on failure
00900 */
00901 static int do_atxfer(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config,int sense,const char *toExt,const char *toCont)
00902 {
00903    struct ast_channel *transferer;
00904    struct ast_channel *transferee;
00905    const char *transferer_real_context;
00906    const char *transfer_context;
00907    char xferto[256] = "";
00908    int res;
00909    int outstate=0;
00910    struct ast_channel *newchan;
00911    struct ast_channel *xferchan;
00912    struct ast_bridge_thread_obj *tobj;
00913    struct ast_bridge_config bconfig;
00914    struct ast_frame *f;
00915    int l;
00916    struct ast_datastore *features_datastore;
00917    struct ast_dial_features *dialfeatures = NULL;
00918 
00919    if (option_debug)
00920       ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
00921    set_peers(&transferer, &transferee, peer, chan, sense);
00922    transferer_real_context = real_ctx(transferer, transferee);
00923    transfer_context = S_OR(toCont, transferer_real_context);
00924 
00925    /* Start autoservice on chan while we talk to the originator */
00926    ast_autoservice_start(transferee);
00927    ast_indicate(transferee, AST_CONTROL_HOLD);
00928 
00929    if (!ast_strlen_zero(toExt)) {
00930       ast_copy_string(xferto, toExt, sizeof(xferto));
00931    } else {
00932       /* Ask for extension to transfer to on the transferer channel */
00933       res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
00934       if (res < 0) {
00935          finishup(transferee);
00936          return res;
00937       }
00938       if (res > 0) /* If they've typed a digit already, handle it */
00939          xferto[0] = (char) res;
00940 
00941       /* this is specific of atxfer */
00942       res = ast_app_dtget(transferer, transfer_context, xferto, sizeof(xferto), 100, transferdigittimeout);
00943       if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
00944          finishup(transferee);
00945          return res;
00946       }
00947       if (res == 0) {
00948          ast_log(LOG_WARNING, "Did not read data.\n");
00949          finishup(transferee);
00950          if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
00951             return -1;
00952          return FEATURE_RETURN_SUCCESS;
00953       }
00954    }
00955 
00956    /* valid extension, res == 1 */
00957    if (!ast_exists_extension(transferer, transfer_context, xferto, 1, transferer->cid.cid_num)) {
00958       ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transfer_context);
00959       finishup(transferee);
00960       if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
00961          return -1;
00962       return FEATURE_RETURN_SUCCESS;
00963    }
00964 
00965    /* If we are attended transfering to parking, just use builtin_parkcall instead of trying to track all of
00966     * the different variables for handling this properly with a builtin_atxfer */
00967    if (!strcmp(xferto, ast_parking_ext())) {
00968       finishup(transferee);
00969       return builtin_parkcall(chan, peer, config, NULL, sense, NULL);
00970    }
00971 
00972    l = strlen(xferto);
00973    snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transfer_context); /* append context */
00974    newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats),
00975       xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, transferer->language);
00976    ast_indicate(transferer, -1);
00977    if (!newchan) {
00978       finishup(transferee);
00979       /* any reason besides user requested cancel and busy triggers the failed sound */
00980       if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
00981             ast_stream_and_wait(transferer, xferfailsound, transferer->language, ""))
00982          return -1;
00983       return FEATURE_RETURN_SUCCESS;
00984    }
00985 
00986    if (check_compat(transferer, newchan)) {
00987       /* we do mean transferee here, NOT transferer */
00988       finishup(transferee);
00989       return -1;
00990    }
00991    memset(&bconfig,0,sizeof(struct ast_bridge_config));
00992    ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
00993    ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
00994    res = ast_bridge_call(transferer, newchan, &bconfig);
00995    if (newchan->_softhangup || !transferer->_softhangup) {
00996       ast_hangup(newchan);
00997       if (ast_stream_and_wait(transferer, xfersound, transferer->language, ""))
00998          ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
00999       finishup(transferee);
01000       transferer->_softhangup = 0;
01001       return FEATURE_RETURN_SUCCESS;
01002    }
01003 
01004    if (check_compat(transferee, newchan)) {
01005       finishup(transferee);
01006       return -1;
01007    }
01008 
01009    ast_indicate(transferee, AST_CONTROL_UNHOLD);
01010 
01011    if ((ast_autoservice_stop(transferee) < 0)
01012       || (ast_waitfordigit(transferee, 100) < 0)
01013       || (ast_waitfordigit(newchan, 100) < 0) 
01014       || ast_check_hangup(transferee) 
01015       || ast_check_hangup(newchan)) {
01016       ast_hangup(newchan);
01017       return -1;
01018    }
01019 
01020    xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
01021    if (!xferchan) {
01022       ast_hangup(newchan);
01023       return -1;
01024    }
01025    /* Make formats okay */
01026    xferchan->visible_indication = transferer->visible_indication;
01027    xferchan->readformat = transferee->readformat;
01028    xferchan->writeformat = transferee->writeformat;
01029    ast_channel_masquerade(xferchan, transferee);
01030    ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
01031    xferchan->_state = AST_STATE_UP;
01032    ast_clear_flag(xferchan, AST_FLAGS_ALL);  
01033    xferchan->_softhangup = 0;
01034 
01035    if ((f = ast_read(xferchan)))
01036       ast_frfree(f);
01037 
01038    newchan->_state = AST_STATE_UP;
01039    ast_clear_flag(newchan, AST_FLAGS_ALL);   
01040    newchan->_softhangup = 0;
01041 
01042    tobj = ast_calloc(1, sizeof(struct ast_bridge_thread_obj));
01043    if (!tobj) {
01044       ast_hangup(xferchan);
01045       ast_hangup(newchan);
01046       return -1;
01047    }
01048 
01049    ast_channel_lock(newchan);
01050    if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
01051       dialfeatures = features_datastore->data;
01052    }
01053    ast_channel_unlock(newchan);
01054 
01055    if (dialfeatures) {
01056       /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
01057          I don't currently understand, the abilities of newchan seem to be stored on the caller side */
01058       ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
01059    }
01060 
01061    ast_channel_lock(xferchan);
01062    if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
01063       dialfeatures = features_datastore->data;
01064    }
01065    ast_channel_unlock(xferchan);
01066 
01067    if (dialfeatures) {
01068       ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
01069    }
01070 
01071    tobj->chan = newchan;
01072    tobj->peer = xferchan;
01073    tobj->bconfig = *config;
01074 
01075    if (tobj->bconfig.end_bridge_callback_data_fixup) {
01076       tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
01077    }
01078 
01079    if (ast_stream_and_wait(newchan, xfersound, newchan->language, ""))
01080       ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
01081    ast_bridge_call_thread_launch(tobj);
01082    return -1;  /* XXX meaning the channel is bridged ? */
01083 }
01084 
01085 
01086 /*!
01087  * \brief Attended transfer ()
01088  * \param chan
01089  * \param peer
01090  * \param config
01091  * \param code
01092  * \param sense
01093  * \param data
01094  * Get extension to transfer to, if you cannot generate channel (or find extension)
01095  * return to host channel. After called channel answered wait for hangup of transferer,
01096  * bridge call between transfer peer (taking them off hold) to attended transfer channel.
01097  * \return -1 means what failure/success both?
01098 */
01099 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01100 {
01101    return do_atxfer(chan, peer, config, sense, NULL, NULL);
01102 }
01103 
01104 /* add atxfer and automon as undefined so you can only use em if you configure them */
01105 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
01106 
01107 AST_RWLOCK_DEFINE_STATIC(features_lock);
01108 
01109 static struct ast_call_feature builtin_features[] = 
01110  {
01111    { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01112    { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01113    { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01114    { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01115    { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01116 };
01117 
01118 
01119 static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
01120 
01121 /*! \brief register new feature into feature_list*/
01122 void ast_register_feature(struct ast_call_feature *feature)
01123 {
01124    if (!feature) {
01125       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
01126          return;
01127    }
01128   
01129    AST_RWLIST_WRLOCK(&feature_list);
01130    AST_RWLIST_INSERT_HEAD(&feature_list, feature, feature_entry);
01131    AST_RWLIST_UNLOCK(&feature_list);
01132 
01133    if (option_verbose >= 2) {
01134       ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
01135    }
01136 }
01137 
01138 /*! \brief unregister feature from feature_list */
01139 void ast_unregister_feature(struct ast_call_feature *feature)
01140 {
01141    if (!feature)
01142       return;
01143 
01144    AST_RWLIST_WRLOCK(&feature_list);
01145    AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
01146    AST_RWLIST_UNLOCK(&feature_list);
01147    
01148    free(feature);
01149 }
01150 
01151 /*! \brief Remove all features in the list */
01152 static void ast_unregister_features(void)
01153 {
01154    struct ast_call_feature *feature;
01155 
01156    AST_RWLIST_WRLOCK(&feature_list);
01157    while ((feature = AST_LIST_REMOVE_HEAD(&feature_list, feature_entry))) {
01158       free(feature);
01159    }
01160    AST_RWLIST_UNLOCK(&feature_list);
01161 }
01162 
01163 /*! \brief find a feature by name */
01164 static struct ast_call_feature *find_dynamic_feature(const char *name)
01165 {
01166    struct ast_call_feature *tmp;
01167 
01168    AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
01169       if (!strcasecmp(tmp->sname, name)) {
01170          break;
01171       }
01172    }
01173 
01174    return tmp;
01175 }
01176 
01177 /*! \brief exec an app by feature */
01178 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01179 {
01180    struct ast_app *app;
01181    struct ast_call_feature *feature = data;
01182    struct ast_channel *work, *idle;
01183    int res;
01184 
01185    if (!feature) { /* shouldn't ever happen! */
01186       ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
01187       return -1; 
01188    }
01189 
01190    if (sense == FEATURE_SENSE_CHAN) {
01191       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
01192          return FEATURE_RETURN_KEEPTRYING;
01193       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
01194          work = chan;
01195          idle = peer;
01196       } else {
01197          work = peer;
01198          idle = chan;
01199       }
01200    } else {
01201       if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
01202          return FEATURE_RETURN_KEEPTRYING;
01203       if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
01204          work = peer;
01205          idle = chan;
01206       } else {
01207          work = chan;
01208          idle = peer;
01209       }
01210    }
01211 
01212    if (!(app = pbx_findapp(feature->app))) {
01213       ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
01214       return -2;
01215    }
01216 
01217    ast_autoservice_start(idle);
01218    
01219    if (!ast_strlen_zero(feature->moh_class))
01220       ast_moh_start(idle, feature->moh_class, NULL);
01221 
01222    res = pbx_exec(work, app, feature->app_args);
01223 
01224    if (!ast_strlen_zero(feature->moh_class))
01225       ast_moh_stop(idle);
01226 
01227    ast_autoservice_stop(idle);
01228 
01229    if (res)
01230       return FEATURE_RETURN_SUCCESSBREAK;
01231    
01232    return FEATURE_RETURN_SUCCESS;   /*! \todo XXX should probably return res */
01233 }
01234 
01235 static void unmap_features(void)
01236 {
01237    int x;
01238 
01239    ast_rwlock_wrlock(&features_lock);
01240    for (x = 0; x < FEATURES_COUNT; x++)
01241       strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
01242    ast_rwlock_unlock(&features_lock);
01243 }
01244 
01245 static int remap_feature(const char *name, const char *value)
01246 {
01247    int x, res = -1;
01248 
01249    ast_rwlock_wrlock(&features_lock);
01250    for (x = 0; x < FEATURES_COUNT; x++) {
01251       if (strcasecmp(builtin_features[x].sname, name))
01252          continue;
01253 
01254       ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
01255       res = 0;
01256       break;
01257    }
01258    ast_rwlock_unlock(&features_lock);
01259 
01260    return res;
01261 }
01262 
01263 /*!
01264  * \brief Helper function for feature_interpret and ast_feature_detect
01265  * \param chan,peer,config,code,sense,dynamic_features char buf,feature flags,operation,feature
01266  *
01267  * Lock features list, browse for code, unlock list
01268  * If a feature is found and the operation variable is set, that feature's
01269  * operation is executed.  The first feature found is copied to the feature parameter.
01270  * \retval res on success.
01271  * \retval -1 on failure.
01272 */
01273 static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
01274    struct ast_bridge_config *config, char *code, int sense, char *dynamic_features_buf,
01275    struct ast_flags *features, int operation, struct ast_call_feature *feature)
01276 {
01277    int x;
01278    struct ast_call_feature *tmpfeature;
01279    char *tmp, *tok;
01280    int res = FEATURE_RETURN_PASSDIGITS;
01281    int feature_detected = 0;
01282 
01283    if (!(peer && chan && config) && operation) {
01284       return -1; /* can not run feature operation */
01285    }
01286 
01287    ast_rwlock_rdlock(&features_lock);
01288    for (x = 0; x < FEATURES_COUNT; x++) {
01289       if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
01290           !ast_strlen_zero(builtin_features[x].exten)) {
01291          /* Feature is up for consideration */
01292          if (!strcmp(builtin_features[x].exten, code)) {
01293             if (option_debug > 2) {
01294                ast_log(LOG_DEBUG, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
01295             }
01296             if (operation) {
01297                res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
01298             }
01299             memcpy(feature, &builtin_features[x], sizeof(feature));
01300             feature_detected = 1;
01301             break;
01302          } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
01303             if (res == FEATURE_RETURN_PASSDIGITS)
01304                res = FEATURE_RETURN_STOREDIGITS;
01305          }
01306       }
01307    }
01308    ast_rwlock_unlock(&features_lock);
01309 
01310    if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
01311       return res;
01312    }
01313 
01314    tmp = dynamic_features_buf;
01315 
01316    while ((tok = strsep(&tmp, "#"))) {
01317       AST_RWLIST_RDLOCK(&feature_list);
01318       if (!(tmpfeature = find_dynamic_feature(tok))) {
01319          AST_RWLIST_UNLOCK(&feature_list);
01320          continue;
01321       }
01322 
01323       /* Feature is up for consideration */
01324       if (!strcmp(tmpfeature->exten, code)) {
01325          if (option_debug > 2) {
01326             ast_log(LOG_NOTICE, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
01327          }
01328          if (operation) {
01329             res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
01330          }
01331          memcpy(feature, tmpfeature, sizeof(feature));
01332          if (res != FEATURE_RETURN_KEEPTRYING) {
01333             AST_RWLIST_UNLOCK(&feature_list);
01334             break;
01335          }
01336          res = FEATURE_RETURN_PASSDIGITS;
01337       } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
01338          res = FEATURE_RETURN_STOREDIGITS;
01339 
01340       AST_RWLIST_UNLOCK(&feature_list);
01341    }
01342 
01343    return res;
01344 }
01345 
01346 /*!
01347  * \brief Check the dynamic features
01348  * \param chan,peer,config,code,sense
01349  *
01350  * \retval res on success.
01351  * \retval -1 on failure.
01352 */
01353 
01354 static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense) {
01355 
01356    char dynamic_features_buf[128];
01357    const char *peer_dynamic_features, *chan_dynamic_features;
01358    struct ast_flags features;
01359    struct ast_call_feature feature;
01360    if (sense == FEATURE_SENSE_CHAN) {
01361       ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
01362    }
01363    else {
01364       ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
01365    }
01366 
01367    ast_channel_lock(peer);
01368    peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
01369    ast_channel_unlock(peer);
01370 
01371    ast_channel_lock(chan);
01372    chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
01373    ast_channel_unlock(chan);
01374 
01375    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,""));
01376 
01377    if (option_debug > 2) {
01378       ast_log(LOG_DEBUG, "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);
01379    }
01380 
01381    return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, 1, &feature);
01382 }
01383 
01384 
01385 int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, char *code, struct ast_call_feature *feature) {
01386 
01387    return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature);
01388 }
01389 
01390 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
01391 {
01392    int x;
01393 
01394    ast_clear_flag(config, AST_FLAGS_ALL);
01395 
01396    ast_rwlock_rdlock(&features_lock);
01397    for (x = 0; x < FEATURES_COUNT; x++) {
01398       if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
01399          continue;
01400 
01401       if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
01402          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
01403 
01404       if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
01405          ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
01406    }
01407    ast_rwlock_unlock(&features_lock);
01408 
01409    if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
01410       const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
01411 
01412       if (dynamic_features) {
01413          char *tmp = ast_strdupa(dynamic_features);
01414          char *tok;
01415          struct ast_call_feature *feature;
01416 
01417          /* while we have a feature */
01418          while ((tok = strsep(&tmp, "#"))) {
01419             AST_RWLIST_RDLOCK(&feature_list);
01420             if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
01421                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
01422                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
01423                if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
01424                   ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
01425             }
01426             AST_RWLIST_UNLOCK(&feature_list);
01427          }
01428       }
01429    }
01430 }
01431 
01432 /*! \todo XXX Check - this is very similar to the code in channel.c */
01433 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, const char *language)
01434 {
01435    int state = 0;
01436    int cause = 0;
01437    int to;
01438    struct ast_channel *chan;
01439    struct ast_channel *monitor_chans[2];
01440    struct ast_channel *active_channel;
01441    int res = 0, ready = 0;
01442    
01443    if ((chan = ast_request(type, format, data, &cause))) {
01444       ast_set_callerid(chan, cid_num, cid_name, cid_num);
01445       ast_string_field_set(chan, language, language);
01446       ast_channel_inherit_variables(caller, chan); 
01447       pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
01448          
01449       if (!ast_call(chan, data, timeout)) {
01450          struct timeval started;
01451          int x, len = 0;
01452          char *disconnect_code = NULL, *dialed_code = NULL;
01453 
01454          ast_indicate(caller, AST_CONTROL_RINGING);
01455          /* support dialing of the featuremap disconnect code while performing an attended tranfer */
01456          ast_rwlock_rdlock(&features_lock);
01457          for (x = 0; x < FEATURES_COUNT; x++) {
01458             if (strcasecmp(builtin_features[x].sname, "disconnect"))
01459                continue;
01460 
01461             disconnect_code = builtin_features[x].exten;
01462             len = strlen(disconnect_code) + 1;
01463             dialed_code = alloca(len);
01464             memset(dialed_code, 0, len);
01465             break;
01466          }
01467          ast_rwlock_unlock(&features_lock);
01468          x = 0;
01469          started = ast_tvnow();
01470          to = timeout;
01471          while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
01472             struct ast_frame *f = NULL;
01473 
01474             monitor_chans[0] = caller;
01475             monitor_chans[1] = chan;
01476             active_channel = ast_waitfor_n(monitor_chans, 2, &to);
01477 
01478             /* see if the timeout has been violated */
01479             if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
01480                state = AST_CONTROL_UNHOLD;
01481                ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
01482                break; /*doh! timeout*/
01483             }
01484 
01485             if (!active_channel)
01486                continue;
01487 
01488             if (chan && (chan == active_channel)) {
01489                if (!ast_strlen_zero(chan->call_forward)) {
01490                   if (!(chan = ast_call_forward(caller, chan, &to, format, NULL, outstate))) {
01491                      return NULL;
01492                   }
01493                   continue;
01494                }
01495                f = ast_read(chan);
01496                if (f == NULL) { /*doh! where'd he go?*/
01497                   state = AST_CONTROL_HANGUP;
01498                   res = 0;
01499                   break;
01500                }
01501                
01502                if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
01503                   if (f->subclass == AST_CONTROL_RINGING) {
01504                      state = f->subclass;
01505                      if (option_verbose > 2)
01506                         ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
01507                      ast_indicate(caller, AST_CONTROL_RINGING);
01508                   } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01509                      state = f->subclass;
01510                      if (option_verbose > 2)
01511                         ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", chan->name);
01512                      ast_indicate(caller, AST_CONTROL_BUSY);
01513                      ast_frfree(f);
01514                      f = NULL;
01515                      break;
01516                   } else if (f->subclass == AST_CONTROL_ANSWER) {
01517                      /* This is what we are hoping for */
01518                      state = f->subclass;
01519                      ast_frfree(f);
01520                      f = NULL;
01521                      ready=1;
01522                      break;
01523                   } else if (f->subclass != -1) {
01524                      ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
01525                   }
01526                   /* else who cares */
01527                }
01528 
01529             } else if (caller && (active_channel == caller)) {
01530                f = ast_read(caller);
01531                if (f == NULL) { /*doh! where'd he go?*/
01532                   if (caller->_softhangup && !chan->_softhangup) {
01533                      /* make this a blind transfer */
01534                      ready = 1;
01535                      break;
01536                   }
01537                   state = AST_CONTROL_HANGUP;
01538                   res = 0;
01539                   break;
01540                }
01541                
01542                if (f->frametype == AST_FRAME_DTMF) {
01543                   dialed_code[x++] = f->subclass;
01544                   dialed_code[x] = '\0';
01545                   if (strlen(dialed_code) == len) {
01546                      x = 0;
01547                   } else if (x && strncmp(dialed_code, disconnect_code, x)) {
01548                      x = 0;
01549                      dialed_code[x] = '\0';
01550                   }
01551                   if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
01552                      /* Caller Canceled the call */
01553                      state = AST_CONTROL_UNHOLD;
01554                      ast_frfree(f);
01555                      f = NULL;
01556                      break;
01557                   }
01558                }
01559             }
01560             if (f)
01561                ast_frfree(f);
01562          } /* end while */
01563       } else
01564          ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
01565    } else {
01566       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01567       switch(cause) {
01568       case AST_CAUSE_BUSY:
01569          state = AST_CONTROL_BUSY;
01570          break;
01571       case AST_CAUSE_CONGESTION:
01572          state = AST_CONTROL_CONGESTION;
01573          break;
01574       }
01575    }
01576    
01577    ast_indicate(caller, -1);
01578    if (chan && ready) {
01579       if (chan->_state == AST_STATE_UP) 
01580          state = AST_CONTROL_ANSWER;
01581       res = 0;
01582    } else if(chan) {
01583       res = -1;
01584       ast_hangup(chan);
01585       chan = NULL;
01586    } else {
01587       res = -1;
01588    }
01589    
01590    if (outstate)
01591       *outstate = state;
01592 
01593    return chan;
01594 }
01595 
01596 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
01597 {
01598    struct ast_cdr *cdr_orig = cdr;
01599    while (cdr) {
01600       if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
01601          return cdr;
01602       cdr = cdr->next;
01603    }
01604    return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
01605 }
01606 
01607 static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
01608 {
01609    const char *feature;
01610 
01611    if (ast_strlen_zero(features)) {
01612       return;
01613    }
01614 
01615    for (feature = features; *feature; feature++) {
01616       switch (*feature) {
01617       case 'T' :
01618       case 't' :
01619          ast_set_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
01620          break;
01621       case 'K' :
01622       case 'k' :
01623          ast_set_flag(&(config->features_caller), AST_FEATURE_PARKCALL);
01624          break;
01625       case 'H' :
01626       case 'h' :
01627          ast_set_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
01628          break;
01629       case 'W' :
01630       case 'w' :
01631          ast_set_flag(&(config->features_caller), AST_FEATURE_AUTOMON);
01632          break;
01633       default :
01634          ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
01635       }
01636    }
01637 }
01638 
01639 static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
01640 {
01641    struct ast_datastore *ds_callee_features = NULL, *ds_caller_features = NULL;
01642    struct ast_dial_features *callee_features = NULL, *caller_features = NULL;
01643 
01644    ast_channel_lock(caller);
01645    ds_caller_features = ast_channel_datastore_find(caller, &dial_features_info, NULL);
01646    ast_channel_unlock(caller);
01647    if (!ds_caller_features) {
01648       if (!(ds_caller_features = ast_channel_datastore_alloc(&dial_features_info, NULL))) {
01649          ast_log(LOG_WARNING, "Unable to create channel datastore for caller features. Aborting!\n");
01650          return;
01651       }
01652       if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
01653          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
01654          ast_channel_datastore_free(ds_caller_features);
01655          return;
01656       }
01657       ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
01658       caller_features->is_caller = 1;
01659       ast_copy_flags(&(caller_features->features_callee), &(config->features_callee), AST_FLAGS_ALL);
01660       ast_copy_flags(&(caller_features->features_caller), &(config->features_caller), AST_FLAGS_ALL);
01661       ds_caller_features->data = caller_features;
01662       ast_channel_lock(caller);
01663       ast_channel_datastore_add(caller, ds_caller_features);
01664       ast_channel_unlock(caller);
01665    } else {
01666       /* If we don't return here, then when we do a builtin_atxfer we will copy the disconnect
01667        * flags over from the atxfer to the caller */
01668       return;
01669    }
01670 
01671    ast_channel_lock(callee);
01672    ds_callee_features = ast_channel_datastore_find(callee, &dial_features_info, NULL);
01673    ast_channel_unlock(callee);
01674    if (!ds_callee_features) {
01675       if (!(ds_callee_features = ast_channel_datastore_alloc(&dial_features_info, NULL))) {
01676          ast_log(LOG_WARNING, "Unable to create channel datastore for callee features. Aborting!\n");
01677          return;
01678       }
01679       if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
01680          ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
01681          ast_channel_datastore_free(ds_callee_features);
01682          return;
01683       }
01684       ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
01685       callee_features->is_caller = 0;
01686       ast_copy_flags(&(callee_features->features_callee), &(config->features_caller), AST_FLAGS_ALL);
01687       ast_copy_flags(&(callee_features->features_caller), &(config->features_callee), AST_FLAGS_ALL);
01688       ds_callee_features->data = callee_features;
01689       ast_channel_lock(callee);
01690       ast_channel_datastore_add(callee, ds_callee_features);
01691       ast_channel_unlock(callee);
01692    }
01693 
01694    return;
01695 }
01696 
01697 static void cmd_atxfer(struct ast_channel *a, struct ast_channel *b, struct ast_bridge_config *conf, struct ast_channel *who, char *xferto)
01698 {
01699    int sense = (a == who) ? FEATURE_SENSE_CHAN : FEATURE_SENSE_PEER;
01700    char *context = strchr(xferto, '@');;
01701    if (context)
01702       *context++ = '\0';
01703    do_atxfer(a, b, conf, sense, xferto, context);
01704 }
01705 
01706 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
01707 {
01708    /* Copy voice back and forth between the two channels.  Give the peer
01709       the ability to transfer calls with '#<extension' syntax. */
01710    struct ast_frame *f;
01711    struct ast_channel *who;
01712    char chan_featurecode[FEATURE_MAX_LEN + 1]="";
01713    char peer_featurecode[FEATURE_MAX_LEN + 1]="";
01714    char orig_channame[AST_MAX_EXTENSION];
01715    char orig_peername[AST_MAX_EXTENSION];
01716 
01717    int res;
01718    int diff;
01719    int hasfeatures=0;
01720    int hadfeatures=0;
01721    int autoloopflag;
01722    struct ast_option_header *aoh;
01723    struct ast_bridge_config backup_config;
01724    struct ast_cdr *bridge_cdr = NULL;
01725    struct ast_cdr *orig_peer_cdr = NULL;
01726    struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */
01727    struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
01728    struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
01729    struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
01730 
01731    memset(&backup_config, 0, sizeof(backup_config));
01732 
01733    config->start_time = ast_tvnow();
01734 
01735    if (chan && peer) {
01736       pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
01737       pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
01738    } else if (chan) {
01739       pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
01740    }
01741 
01742    set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
01743    add_features_datastores(chan, peer, config);
01744 
01745    /* This is an interesting case.  One example is if a ringing channel gets redirected to
01746     * an extension that picks up a parked call.  This will make sure that the call taken
01747     * out of parking gets told that the channel it just got bridged to is still ringing. */
01748    if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
01749       ast_indicate(peer, AST_CONTROL_RINGING);
01750    }
01751 
01752    if (monitor_ok) {
01753       const char *monitor_exec;
01754       struct ast_channel *src = NULL;
01755       if (!monitor_app) { 
01756          if (!(monitor_app = pbx_findapp("Monitor")))
01757             monitor_ok=0;
01758       }
01759       if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
01760          src = chan;
01761       else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
01762          src = peer;
01763       if (monitor_app && src) {
01764          char *tmp = ast_strdupa(monitor_exec);
01765          pbx_exec(src, monitor_app, tmp);
01766       }
01767    }
01768 
01769    set_config_flags(chan, peer, config);
01770    config->firstpass = 1;
01771 
01772    /* Answer if need be */
01773    if (ast_answer(chan))
01774       return -1;
01775 
01776    ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
01777    ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
01778    orig_peer_cdr = peer_cdr;
01779    
01780    if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
01781          
01782       if (chan_cdr) {
01783          ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
01784          ast_cdr_update(chan);
01785          bridge_cdr = ast_cdr_dup(chan_cdr);
01786          /* rip any forked CDR's off of the chan_cdr and attach
01787           * them to the bridge_cdr instead */
01788          bridge_cdr->next = chan_cdr->next;
01789          chan_cdr->next = NULL;
01790          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
01791          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
01792       } else {
01793          /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
01794          bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
01795          ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
01796          ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
01797          ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
01798          ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
01799          ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
01800          ast_cdr_setcid(bridge_cdr, chan);
01801          bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NOANSWER;
01802          bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
01803          ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
01804          /* Destination information */
01805          ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
01806          ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
01807          if (peer_cdr) {
01808             bridge_cdr->start = peer_cdr->start;
01809             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
01810          } else {
01811             ast_cdr_start(bridge_cdr);
01812          }
01813       }
01814       /* peer_cdr->answer will be set when a macro runs on the peer;
01815          in that case, the bridge answer will be delayed while the
01816          macro plays on the peer channel. The peer answered the call
01817          before the macro started playing. To the phone system,
01818          this is billable time for the call, even tho the caller
01819          hears nothing but ringing while the macro does its thing. */
01820 
01821       /* Another case where the peer cdr's time will be set, is when
01822          A self-parks by pickup up phone and dialing 700, then B
01823          picks up A by dialing its parking slot; there may be more 
01824          practical paths that get the same result, tho... in which
01825          case you get the previous answer time from the Park... which
01826          is before the bridge's start time, so I added in the 
01827          tvcmp check to the if below */
01828 
01829       if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer->cdr->answer, bridge_cdr->start) >= 0) {
01830          ast_cdr_setanswer(bridge_cdr, peer_cdr->answer);
01831          ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition);
01832          if (chan_cdr) {
01833             ast_cdr_setanswer(chan_cdr, peer_cdr->answer);
01834             ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition);
01835          }
01836       } else {
01837          ast_cdr_answer(bridge_cdr);
01838          if (chan_cdr) {
01839             ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
01840          }
01841       }
01842       if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
01843          if (chan_cdr) {
01844             ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
01845          }
01846          if (peer_cdr) {
01847             ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
01848          }
01849       }
01850    }
01851 
01852    for (;;) {
01853       struct ast_channel *other; /* used later */
01854 
01855       res = ast_channel_bridge(chan, peer, config, &f, &who);
01856       
01857       /* When frame is not set, we are probably involved in a situation
01858          where we've timed out.
01859          When frame is set, we'll come thru this code twice; once for DTMF_BEGIN
01860          and also for DTMF_END. If we flow into the following 'if' for both, then 
01861          our wait times are cut in half, as both will subtract from the
01862          feature_timer. Not good!
01863       */
01864       if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
01865          /* Update time limit for next pass */
01866          diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
01867          if (res == AST_BRIDGE_RETRY) {
01868             /* The feature fully timed out but has not been updated. Skip
01869              * the potential round error from the diff calculation and
01870              * explicitly set to expired. */
01871             config->feature_timer = -1;
01872          } else {
01873             config->feature_timer -= diff;
01874          }
01875 
01876          if (hasfeatures) {
01877             /* Running on backup config, meaning a feature might be being
01878                activated, but that's no excuse to keep things going 
01879                indefinitely! */
01880             if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
01881                if (option_debug)
01882                   ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
01883                config->feature_timer = 0;
01884                who = chan;
01885                if (f)
01886                   ast_frfree(f);
01887                f = NULL;
01888                res = 0;
01889             } else if (config->feature_timer <= 0) {
01890                /* Not *really* out of time, just out of time for
01891                   digits to come in for features. */
01892                if (option_debug)
01893                   ast_log(LOG_DEBUG, "Timed out for feature!\n");
01894                if (!ast_strlen_zero(peer_featurecode)) {
01895                   ast_dtmf_stream(chan, peer, peer_featurecode, 0);
01896                   memset(peer_featurecode, 0, sizeof(peer_featurecode));
01897                }
01898                if (!ast_strlen_zero(chan_featurecode)) {
01899                   ast_dtmf_stream(peer, chan, chan_featurecode, 0);
01900                   memset(chan_featurecode, 0, sizeof(chan_featurecode));
01901                }
01902                if (f)
01903                   ast_frfree(f);
01904                hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01905                if (!hasfeatures) {
01906                   /* Restore original (possibly time modified) bridge config */
01907                   memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01908                   memset(&backup_config, 0, sizeof(backup_config));
01909                }
01910                hadfeatures = hasfeatures;
01911                /* Continue as we were */
01912                continue;
01913             } else if (!f) {
01914                /* The bridge returned without a frame and there is a feature in progress.
01915                 * However, we don't think the feature has quite yet timed out, so just
01916                 * go back into the bridge. */
01917                continue;
01918             }
01919          } else {
01920             if (config->feature_timer <=0) {
01921                /* We ran out of time */
01922                config->feature_timer = 0;
01923                who = chan;
01924                if (f)
01925                   ast_frfree(f);
01926                f = NULL;
01927                res = 0;
01928             }
01929          }
01930       }
01931       if (res < 0) {
01932          if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
01933             ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
01934          goto before_you_go;
01935       }
01936       
01937       if (!f || (f->frametype == AST_FRAME_CONTROL &&
01938             (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 
01939                f->subclass == AST_CONTROL_CONGESTION ) ) ) {
01940          res = -1;
01941          break;
01942       }
01943       /* many things should be sent to the 'other' channel */
01944       other = (who == chan) ? peer : chan;
01945       if (f->frametype == AST_FRAME_CONTROL) {
01946          switch (f->subclass) {
01947          case AST_CONTROL_RINGING:
01948          case AST_CONTROL_FLASH:
01949          case -1:
01950             ast_indicate(other, f->subclass);
01951             break;
01952          case AST_CONTROL_HOLD:
01953          case AST_CONTROL_UNHOLD:
01954             ast_indicate_data(other, f->subclass, f->data, f->datalen);
01955             break;
01956          case AST_CONTROL_OPTION:
01957             aoh = f->data;
01958             /* Forward option Requests */
01959             if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
01960                ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 
01961                   f->datalen - sizeof(struct ast_option_header), 0);
01962             }
01963             break;
01964          case AST_CONTROL_ATXFERCMD:
01965             cmd_atxfer(chan, peer, config, who, f->data);
01966             break;
01967          }
01968       } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
01969          /* eat it */
01970       } else if (f->frametype == AST_FRAME_DTMF) {
01971          char *featurecode;
01972          int sense;
01973 
01974          hadfeatures = hasfeatures;
01975          /* This cannot overrun because the longest feature is one shorter than our buffer */
01976          if (who == chan) {
01977             sense = FEATURE_SENSE_CHAN;
01978             featurecode = chan_featurecode;
01979          } else  {
01980             sense = FEATURE_SENSE_PEER;
01981             featurecode = peer_featurecode;
01982          }
01983          /*! append the event to featurecode. we rely on the string being zero-filled, and
01984           * not overflowing it. 
01985           * \todo XXX how do we guarantee the latter ?
01986           */
01987          featurecode[strlen(featurecode)] = f->subclass;
01988          /* Get rid of the frame before we start doing "stuff" with the channels */
01989          ast_frfree(f);
01990          f = NULL;
01991          config->feature_timer = backup_config.feature_timer;
01992          res = feature_interpret(chan, peer, config, featurecode, sense);
01993          switch(res) {
01994          case FEATURE_RETURN_PASSDIGITS:
01995             ast_dtmf_stream(other, who, featurecode, 0);
01996             /* Fall through */
01997          case FEATURE_RETURN_SUCCESS:
01998             memset(featurecode, 0, sizeof(chan_featurecode));
01999             break;
02000          }
02001          if (res >= FEATURE_RETURN_PASSDIGITS) {
02002             res = 0;
02003          } else 
02004             break;
02005          hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
02006          if (hadfeatures && !hasfeatures) {
02007             /* Restore backup */
02008             memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
02009             memset(&backup_config, 0, sizeof(struct ast_bridge_config));
02010          } else if (hasfeatures) {
02011             if (!hadfeatures) {
02012                /* Backup configuration */
02013                memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
02014                /* Setup temporary config options */
02015                config->play_warning = 0;
02016                ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
02017                ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
02018                config->warning_freq = 0;
02019                config->warning_sound = NULL;
02020                config->end_sound = NULL;
02021                config->start_sound = NULL;
02022                config->firstpass = 0;
02023             }
02024             config->start_time = ast_tvnow();
02025             config->feature_timer = featuredigittimeout;
02026             if (option_debug)
02027                ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
02028          }
02029       }
02030       if (f)
02031          ast_frfree(f);
02032 
02033    }
02034   before_you_go:
02035 
02036    if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) {
02037       ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
02038       if (bridge_cdr) {
02039          ast_cdr_discard(bridge_cdr);
02040          /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */
02041       }
02042       return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */
02043    }
02044 
02045    if (config->end_bridge_callback) {
02046       config->end_bridge_callback(config->end_bridge_callback_data);
02047    }
02048 
02049    if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && 
02050        ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
02051       struct ast_cdr *swapper = NULL;
02052       char savelastapp[AST_MAX_EXTENSION];
02053       char savelastdata[AST_MAX_EXTENSION];
02054       char save_exten[AST_MAX_EXTENSION];
02055       int  save_prio, spawn_error = 0;
02056       
02057       autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
02058       ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
02059       if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
02060          ast_cdr_end(bridge_cdr);
02061       }
02062       /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
02063          dialplan code operate on it */
02064       ast_channel_lock(chan);
02065       if (bridge_cdr) {
02066          swapper = chan->cdr;
02067          ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
02068          ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
02069          chan->cdr = bridge_cdr;
02070       }
02071       ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
02072       ast_copy_string(chan->exten, "h", sizeof(chan->exten));
02073       save_prio = chan->priority;
02074       chan->priority = 1;
02075       ast_channel_unlock(chan);
02076       while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
02077          if ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) {
02078             /* Something bad happened, or a hangup has been requested. */
02079             if (option_debug)
02080                ast_log(LOG_DEBUG, "Spawn h extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
02081             if (option_verbose > 1)
02082                ast_verbose( VERBOSE_PREFIX_2 "Spawn h extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
02083             break;
02084          }
02085          chan->priority++;
02086       }
02087       /* swap it back */
02088       ast_channel_lock(chan);
02089       ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
02090       chan->priority = save_prio;
02091       if (bridge_cdr) {
02092          if (chan->cdr == bridge_cdr) {
02093             chan->cdr = swapper;
02094          } else {
02095             bridge_cdr = NULL;
02096          }
02097       }
02098       if (chan->priority != 1 || !spawn_error) {
02099          ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
02100       }
02101       ast_channel_unlock(chan);
02102       /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
02103       if (bridge_cdr) {
02104          ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
02105          ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
02106       }
02107       ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
02108    }
02109    
02110    /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
02111    new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
02112    if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) {
02113       ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
02114    }
02115 
02116    /* we can post the bridge CDR at this point */
02117    if (bridge_cdr) {
02118       ast_cdr_end(bridge_cdr);
02119       ast_cdr_detach(bridge_cdr);
02120    }
02121    
02122    /* do a specialized reset on the beginning channel
02123       CDR's, if they still exist, so as not to mess up
02124       issues in future bridges;
02125       
02126       Here are the rules of the game:
02127       1. The chan and peer channel pointers will not change
02128          during the life of the bridge.
02129       2. But, in transfers, the channel names will change.
02130          between the time the bridge is started, and the
02131          time the channel ends. 
02132          Usually, when a channel changes names, it will
02133          also change CDR pointers.
02134       3. Usually, only one of the two channels (chan or peer)
02135          will change names.
02136       4. Usually, if a channel changes names during a bridge,
02137          it is because of a transfer. Usually, in these situations,
02138          it is normal to see 2 bridges running simultaneously, and
02139          it is not unusual to see the two channels that change
02140          swapped between bridges.
02141       5. After a bridge occurs, we have 2 or 3 channels' CDRs
02142          to attend to; if the chan or peer changed names,
02143          we have the before and after attached CDR's.
02144    */
02145    
02146    if (new_chan_cdr) {
02147       struct ast_channel *chan_ptr = NULL;
02148       
02149       if (strcasecmp(orig_channame, chan->name) != 0) { 
02150          /* old channel */
02151          chan_ptr = ast_get_channel_by_name_locked(orig_channame);
02152          if (chan_ptr) {
02153             if (!ast_bridged_channel(chan_ptr)) {
02154                struct ast_cdr *cur;
02155                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
02156                   if (cur == chan_cdr) {
02157                      break;
02158                   }
02159                }
02160                if (cur)
02161                   ast_cdr_specialized_reset(chan_cdr,0);
02162             }
02163             ast_channel_unlock(chan_ptr);
02164          }
02165          /* new channel */
02166          ast_cdr_specialized_reset(new_chan_cdr,0);
02167       } else {
02168          ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr  */
02169       }
02170    }
02171 
02172    {
02173       struct ast_channel *chan_ptr = NULL;
02174       new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
02175       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))
02176          ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
02177       if (strcasecmp(orig_peername, peer->name) != 0) { 
02178          /* old channel */
02179          chan_ptr = ast_get_channel_by_name_locked(orig_peername);
02180          if (chan_ptr) {
02181             if (!ast_bridged_channel(chan_ptr)) {
02182                struct ast_cdr *cur;
02183                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
02184                   if (cur == peer_cdr) {
02185                      break;
02186                   }
02187                }
02188                if (cur)
02189                   ast_cdr_specialized_reset(peer_cdr,0);
02190             }
02191             ast_channel_unlock(chan_ptr);
02192          }
02193          /* new channel */
02194          ast_cdr_specialized_reset(new_peer_cdr,0);
02195       } else {
02196          ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr  */
02197       }
02198    }
02199    
02200    return res;
02201 }
02202 
02203 static void post_manager_event(const char *s, char *parkingexten, struct ast_channel *chan)
02204 {
02205    manager_event(EVENT_FLAG_CALL, s,
02206       "Exten: %s\r\n"
02207       "Channel: %s\r\n"
02208       "CallerID: %s\r\n"
02209       "CallerIDName: %s\r\n\r\n",
02210       parkingexten, 
02211       chan->name,
02212       S_OR(chan->cid.cid_num, "<unknown>"),
02213       S_OR(chan->cid.cid_name, "<unknown>")
02214       );
02215 }
02216 
02217 static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
02218 {
02219    int i = 0;
02220    enum {
02221       OPT_CALLEE_REDIRECT   = 't',
02222       OPT_CALLER_REDIRECT   = 'T',
02223       OPT_CALLEE_AUTOMON    = 'w',
02224       OPT_CALLER_AUTOMON    = 'W',
02225       OPT_CALLEE_DISCONNECT = 'h',
02226       OPT_CALLER_DISCONNECT = 'H',
02227       OPT_CALLEE_PARKCALL   = 'k',
02228       OPT_CALLER_PARKCALL   = 'K',
02229    };
02230 
02231    memset(options, 0, len);
02232    if (ast_test_flag(features_caller, AST_FEATURE_REDIRECT) && i < len) {
02233       options[i++] = OPT_CALLER_REDIRECT;
02234    }
02235    if (ast_test_flag(features_caller, AST_FEATURE_AUTOMON) && i < len) {
02236       options[i++] = OPT_CALLER_AUTOMON;
02237    }
02238    if (ast_test_flag(features_caller, AST_FEATURE_DISCONNECT) && i < len) {
02239       options[i++] = OPT_CALLER_DISCONNECT;
02240    }
02241    if (ast_test_flag(features_caller, AST_FEATURE_PARKCALL) && i < len) {
02242       options[i++] = OPT_CALLER_PARKCALL;
02243    }
02244 
02245    if (ast_test_flag(features_callee, AST_FEATURE_REDIRECT) && i < len) {
02246       options[i++] = OPT_CALLEE_REDIRECT;
02247    }
02248    if (ast_test_flag(features_callee, AST_FEATURE_AUTOMON) && i < len) {
02249       options[i++] = OPT_CALLEE_AUTOMON;
02250    }
02251    if (ast_test_flag(features_callee, AST_FEATURE_DISCONNECT) && i < len) {
02252       options[i++] = OPT_CALLEE_DISCONNECT;
02253    }
02254    if (ast_test_flag(features_callee, AST_FEATURE_PARKCALL) && i < len) {
02255       options[i++] = OPT_CALLEE_PARKCALL;
02256    }
02257 
02258    return options;
02259 }
02260 
02261 /*! \brief Take care of parked calls and unpark them if needed */
02262 static void *do_parking_thread(void *ignore)
02263 {
02264    fd_set rfds, efds;   /* results from previous select, to be preserved across loops. */
02265    FD_ZERO(&rfds);
02266    FD_ZERO(&efds);
02267 
02268    for (;;) {
02269       struct parkeduser *pu, *pl, *pt = NULL;
02270       int ms = -1;   /* select timeout, uninitialized */
02271       int max = -1;  /* max fd, none there yet */
02272       fd_set nrfds, nefds; /* args for the next select */
02273       FD_ZERO(&nrfds);
02274       FD_ZERO(&nefds);
02275 
02276       ast_mutex_lock(&parking_lock);
02277       pl = NULL;
02278       pu = parkinglot;
02279       /* navigate the list with prev-cur pointers to support removals */
02280       while (pu) {
02281          struct ast_channel *chan = pu->chan;   /* shorthand */
02282          int tms;        /* timeout for this item */
02283          int x;          /* fd index in channel */
02284          struct ast_context *con;
02285 
02286          if (pu->notquiteyet) { /* Pretend this one isn't here yet */
02287             pl = pu;
02288             pu = pu->next;
02289             continue;
02290          }
02291          tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
02292          if (tms > pu->parkingtime) {
02293             ast_indicate(chan, AST_CONTROL_UNHOLD);
02294             /* Get chan, exten from derived kludge */
02295             if (pu->peername[0]) {
02296                char *peername = ast_strdupa(pu->peername);
02297                char *cp = strrchr(peername, '-');
02298                if (cp) 
02299                   *cp = 0;
02300                con = ast_context_find(parking_con_dial);
02301                if (!con) {
02302                   con = ast_context_create(NULL, parking_con_dial, registrar);
02303                   if (!con)
02304                      ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
02305                }
02306                if (con) {
02307                   char returnexten[AST_MAX_EXTENSION];
02308                   struct ast_datastore *features_datastore;
02309                   struct ast_dial_features *dialfeatures = NULL;
02310 
02311                   ast_channel_lock(chan);
02312 
02313                   if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
02314                      dialfeatures = features_datastore->data;
02315 
02316                   ast_channel_unlock(chan);
02317 
02318                   if (!strncmp(peername, "Parked/", 7)) {
02319                      peername += 7;
02320                   }
02321 
02322                   if (dialfeatures) {
02323                      char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
02324                      snprintf(returnexten, sizeof(returnexten), "%s|30|%s", peername, callback_dialoptions(&(dialfeatures->features_callee), &(dialfeatures->features_caller), buf, sizeof(buf)));
02325                   } else { /* Existing default */
02326                      ast_log(LOG_WARNING, "Dialfeatures not found on %s, using default!\n", chan->name);
02327                      snprintf(returnexten, sizeof(returnexten), "%s|30|t", peername);
02328                   }
02329 
02330                   ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free_ptr, registrar);
02331                }
02332                set_c_e_p(chan, parking_con_dial, peername, 1);
02333             } else {
02334                /* They've been waiting too long, send them back to where they came.  Theoretically they
02335                   should have their original extensions and such, but we copy to be on the safe side */
02336                set_c_e_p(chan, pu->context, pu->exten, pu->priority);
02337             }
02338 
02339             post_manager_event("ParkedCallTimeOut", pu->parkingexten, chan);
02340 
02341             if (option_verbose > 1) 
02342                ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
02343             /* Start up the PBX, or hang them up */
02344             if (ast_pbx_start(chan))  {
02345                ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
02346                ast_hangup(chan);
02347             }
02348             /* And take them out of the parking lot */
02349             if (pl) 
02350                pl->next = pu->next;
02351             else
02352                parkinglot = pu->next;
02353             pt = pu;
02354             pu = pu->next;
02355             con = ast_context_find(parking_con);
02356             if (con) {
02357                if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
02358                   ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
02359                else
02360                   notify_metermaids(pt->parkingexten, parking_con);
02361             } else
02362                ast_log(LOG_WARNING, "Whoa, no parking context?\n");
02363             free(pt);
02364          } else { /* still within parking time, process descriptors */
02365             for (x = 0; x < AST_MAX_FDS; x++) {
02366                struct ast_frame *f;
02367 
02368                if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
02369                   continue;   /* nothing on this descriptor */
02370 
02371                if (FD_ISSET(chan->fds[x], &efds))
02372                   ast_set_flag(chan, AST_FLAG_EXCEPTION);
02373                else
02374                   ast_clear_flag(chan, AST_FLAG_EXCEPTION);
02375                chan->fdno = x;
02376 
02377                /* See if they need servicing */
02378                f = ast_read(chan);
02379                if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass ==  AST_CONTROL_HANGUP)) {
02380                   if (f)
02381                      ast_frfree(f);
02382                   post_manager_event("ParkedCallGiveUp", pu->parkingexten, chan);
02383 
02384                   /* There's a problem, hang them up*/
02385                   if (option_verbose > 1) 
02386                      ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
02387                   ast_hangup(chan);
02388                   /* And take them out of the parking lot */
02389                   if (pl) 
02390                      pl->next = pu->next;
02391                   else
02392                      parkinglot = pu->next;
02393                   pt = pu;
02394                   pu = pu->next;
02395                   con = ast_context_find(parking_con);
02396                   if (con) {
02397                      if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
02398                         ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
02399                      else {
02400                         notify_metermaids(pt->parkingexten, parking_con);
02401                      }
02402                   } else
02403                      ast_log(LOG_WARNING, "Whoa, no parking context?\n");
02404                   free(pt);
02405                   break;
02406                } else {
02407                   /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
02408                   ast_frfree(f);
02409                   if (pu->moh_trys < 3 && !chan->generatordata) {
02410                      if (option_debug)
02411                         ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source.  Restarting.\n");
02412                      ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
02413                         S_OR(parkmohclass, NULL),
02414                         !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
02415                      pu->moh_trys++;
02416                   }
02417                   goto std;   /*! \todo XXX Ick: jumping into an else statement??? XXX */
02418                }
02419 
02420             } /* end for */
02421             if (x >= AST_MAX_FDS) {
02422 std:              for (x=0; x<AST_MAX_FDS; x++) {  /* mark fds for next round */
02423                   if (chan->fds[x] > -1) {
02424                      FD_SET(chan->fds[x], &nrfds);
02425                      FD_SET(chan->fds[x], &nefds);
02426                      if (chan->fds[x] > max)
02427                         max = chan->fds[x];
02428                   }
02429                }
02430                /* Keep track of our shortest wait */
02431                if (tms < ms || ms < 0)
02432                   ms = tms;
02433                pl = pu;
02434                pu = pu->next;
02435             }
02436          }
02437       } /* end while */
02438       ast_mutex_unlock(&parking_lock);
02439       rfds = nrfds;
02440       efds = nefds;
02441       {
02442          struct timeval tv = ast_samp2tv(ms, 1000);
02443          /* Wait for something to happen */
02444          ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
02445       }
02446       pthread_testcancel();
02447    }
02448    return NULL;   /* Never reached */
02449 }
02450 
02451 /*! \brief Park a call */
02452 static int park_call_exec(struct ast_channel *chan, void *data)
02453 {
02454    /* Cache the original channel name in case we get masqueraded in the middle
02455     * of a park--it is still theoretically possible for a transfer to happen before
02456     * we get here, but it is _really_ unlikely */
02457    char *orig_chan_name = ast_strdupa(chan->name);
02458    char orig_exten[AST_MAX_EXTENSION];
02459    int orig_priority = chan->priority;
02460 
02461    /* Data is unused at the moment but could contain a parking
02462       lot context eventually */
02463    int res = 0;
02464    struct ast_module_user *u;
02465 
02466    u = ast_module_user_add(chan);
02467 
02468    ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
02469 
02470    /* Setup the exten/priority to be s/1 since we don't know
02471       where this call should return */
02472    strcpy(chan->exten, "s");
02473    chan->priority = 1;
02474    /* Answer if call is not up */
02475    if (chan->_state != AST_STATE_UP)
02476       res = ast_answer(chan);
02477    /* Sleep to allow VoIP streams to settle down */
02478    if (!res)
02479       res = ast_safe_sleep(chan, 1000);
02480    /* Park the call */
02481    if (!res) {
02482       res = masq_park_call_announce(chan, chan, 0, NULL, orig_chan_name);
02483       /* Continue on in the dialplan */
02484       if (res == 1) {
02485          ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
02486          chan->priority = orig_priority;
02487          res = 0;
02488       } else if (!res) {
02489          res = 1;
02490       }
02491    }
02492 
02493    ast_module_user_remove(u);
02494 
02495    return res;
02496 }
02497 
02498 /*! \brief Pickup parked call */
02499 static int park_exec(struct ast_channel *chan, void *data)
02500 {
02501    int res = 0;
02502    struct ast_module_user *u;
02503    struct ast_channel *peer=NULL;
02504    struct parkeduser *pu, *pl=NULL;
02505    struct ast_context *con;
02506 
02507    int park;
02508    struct ast_bridge_config config;
02509 
02510    if (!data) {
02511       ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
02512       return -1;
02513    }
02514 
02515    u = ast_module_user_add(chan);
02516 
02517    park = atoi((char *)data);
02518    ast_mutex_lock(&parking_lock);
02519    pu = parkinglot;
02520    while(pu) {
02521       if (pu->parkingnum == park) {
02522          if (pu->chan->pbx) { /* do not allow call to be picked up until the PBX thread is finished */
02523             ast_mutex_unlock(&parking_lock);
02524             ast_module_user_remove(u);
02525             return -1;
02526          }
02527          if (pl)
02528             pl->next = pu->next;
02529          else
02530             parkinglot = pu->next;
02531          break;
02532       }
02533       pl = pu;
02534       pu = pu->next;
02535    }
02536    ast_mutex_unlock(&parking_lock);
02537    if (pu) {
02538       peer = pu->chan;
02539       con = ast_context_find(parking_con);
02540       if (con) {
02541          if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
02542             ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
02543          else
02544             notify_metermaids(pu->parkingexten, parking_con);
02545       } else
02546          ast_log(LOG_WARNING, "Whoa, no parking context?\n");
02547 
02548       manager_event(EVENT_FLAG_CALL, "UnParkedCall",
02549          "Exten: %s\r\n"
02550          "Channel: %s\r\n"
02551          "From: %s\r\n"
02552          "CallerID: %s\r\n"
02553          "CallerIDName: %s\r\n",
02554          pu->parkingexten, pu->chan->name, chan->name,
02555          S_OR(pu->chan->cid.cid_num, "<unknown>"),
02556          S_OR(pu->chan->cid.cid_name, "<unknown>")
02557          );
02558 
02559       free(pu);
02560    }
02561    /* JK02: it helps to answer the channel if not already up */
02562    if (chan->_state != AST_STATE_UP)
02563       ast_answer(chan);
02564 
02565    if (peer) {
02566       struct ast_datastore *features_datastore;
02567       struct ast_dial_features *dialfeatures = NULL;
02568 
02569       /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
02570 
02571       if (!ast_strlen_zero(courtesytone)) {
02572          int error = 0;
02573          ast_indicate(peer, AST_CONTROL_UNHOLD);
02574          if (parkedplay == 0) {
02575             error = ast_stream_and_wait(chan, courtesytone, chan->language, "");
02576          } else if (parkedplay == 1) {
02577             error = ast_stream_and_wait(peer, courtesytone, chan->language, "");
02578          } else if (parkedplay == 2) {
02579             if (!ast_streamfile(chan, courtesytone, chan->language) &&
02580                   !ast_streamfile(peer, courtesytone, chan->language)) {
02581                /*! \todo XXX we would like to wait on both! */
02582                res = ast_waitstream(chan, "");
02583                if (res >= 0)
02584                   res = ast_waitstream(peer, "");
02585                if (res < 0)
02586                   error = 1;
02587             }
02588                         }
02589          if (error) {
02590             ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
02591             ast_hangup(peer);
02592             ast_module_user_remove(u);
02593             return -1;
02594          }
02595       } else
02596          ast_indicate(peer, AST_CONTROL_UNHOLD);
02597 
02598       res = ast_channel_make_compatible(chan, peer);
02599       if (res < 0) {
02600          ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
02601          ast_hangup(peer);
02602          ast_module_user_remove(u);
02603          return -1;
02604       }
02605       /* This runs sorta backwards, since we give the incoming channel control, as if it
02606          were the person called. */
02607       if (option_verbose > 2)
02608          ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
02609 
02610       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
02611       ast_cdr_setdestchan(chan->cdr, peer->name);
02612       memset(&config, 0, sizeof(struct ast_bridge_config));
02613 
02614       /* Get datastore for peer and apply it's features to the callee side of the bridge config */
02615       ast_channel_lock(peer);
02616       if ((features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL))) {
02617          dialfeatures = features_datastore->data;
02618       }
02619       ast_channel_unlock(peer);
02620 
02621       if (dialfeatures) {
02622          ast_copy_flags(&(config.features_callee), dialfeatures->is_caller ? &(dialfeatures->features_caller) : &(dialfeatures->features_callee), AST_FLAGS_ALL);
02623       }
02624 
02625       if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
02626          ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02627       }
02628       if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
02629          ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02630       }
02631       if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
02632          ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
02633       }
02634       if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
02635          ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
02636       }
02637       if ((parkedcallhangup == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
02638          ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
02639       }
02640       if ((parkedcallhangup == AST_FEATURE_FLAG_BYCALLER) || (parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
02641          ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
02642       }
02643       if ((parkedcallrecording == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
02644          ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
02645       }
02646       if ((parkedcallrecording == AST_FEATURE_FLAG_BYCALLER) || (parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
02647          ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
02648       }
02649       res = ast_bridge_call(chan, peer, &config);
02650 
02651       pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
02652       ast_cdr_setdestchan(chan->cdr, peer->name);
02653 
02654       /* Simulate the PBX hanging up */
02655       ast_hangup(peer);
02656       ast_module_user_remove(u);
02657       return -1;
02658    } else {
02659       /*! \todo XXX Play a message XXX */
02660       if (ast_stream_and_wait(chan, "pbx-invalidpark", chan->language, ""))
02661          ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
02662       if (option_verbose > 2) 
02663          ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
02664       res = -1;
02665    }
02666 
02667    ast_module_user_remove(u);
02668 
02669    return -1;
02670 }
02671 
02672 static int handle_showfeatures(int fd, int argc, char *argv[])
02673 {
02674    int i;
02675    struct ast_call_feature *feature;
02676    char format[] = "%-25s %-7s %-7s\n";
02677 
02678    ast_cli(fd, format, "Builtin Feature", "Default", "Current");
02679    ast_cli(fd, format, "---------------", "-------", "-------");
02680 
02681    ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());      /* default hardcoded above, so we'll hardcode it here */
02682 
02683    ast_rwlock_rdlock(&features_lock);
02684    for (i = 0; i < FEATURES_COUNT; i++)
02685       ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
02686    ast_rwlock_unlock(&features_lock);
02687 
02688    ast_cli(fd, "\n");
02689    ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
02690    ast_cli(fd, format, "---------------", "-------", "-------");
02691    if (AST_RWLIST_EMPTY(&feature_list)) {
02692       ast_cli(fd, "(none)\n");
02693    } else {
02694       AST_RWLIST_RDLOCK(&feature_list);
02695       AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
02696          ast_cli(fd, format, feature->sname, "no def", feature->exten);
02697       }
02698       AST_RWLIST_UNLOCK(&feature_list);
02699    }
02700    ast_cli(fd, "\nCall parking\n");
02701    ast_cli(fd, "------------\n");
02702    ast_cli(fd,"%-20s:   %s\n", "Parking extension", parking_ext);
02703    ast_cli(fd,"%-20s:   %s\n", "Parking context", parking_con);
02704    ast_cli(fd,"%-20s:   %d-%d\n", "Parked call extensions", parking_start, parking_stop);
02705    ast_cli(fd,"\n");
02706    
02707    return RESULT_SUCCESS;
02708 }
02709 
02710 static char showfeatures_help[] =
02711 "Usage: feature list\n"
02712 "       Lists currently configured features.\n";
02713 
02714 static int handle_parkedcalls(int fd, int argc, char *argv[])
02715 {
02716    struct parkeduser *cur;
02717    int numparked = 0;
02718 
02719    ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
02720       , "Context", "Extension", "Pri", "Timeout");
02721 
02722    ast_mutex_lock(&parking_lock);
02723 
02724    for (cur = parkinglot; cur; cur = cur->next) {
02725       ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
02726          ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
02727          ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
02728 
02729       numparked++;
02730    }
02731    ast_mutex_unlock(&parking_lock);
02732    ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
02733 
02734 
02735    return RESULT_SUCCESS;
02736 }
02737 
02738 static char showparked_help[] =
02739 "Usage: show parkedcalls\n"
02740 "       Lists currently parked calls.\n";
02741 
02742 static struct ast_cli_entry cli_show_features_deprecated = {
02743    { "show", "features", NULL },
02744    handle_showfeatures, NULL,
02745    NULL };
02746 
02747 static struct ast_cli_entry cli_features[] = {
02748    { { "feature", "show", NULL },
02749    handle_showfeatures, "Lists configured features",
02750    showfeatures_help, NULL, &cli_show_features_deprecated },
02751 
02752    { { "show", "parkedcalls", NULL },
02753    handle_parkedcalls, "Lists parked calls",
02754    showparked_help },
02755 };
02756 
02757 /*! \brief Dump lot status */
02758 static int manager_parking_status( struct mansession *s, const struct message *m)
02759 {
02760    struct parkeduser *cur;
02761    const char *id = astman_get_header(m, "ActionID");
02762    char idText[256] = "";
02763 
02764    if (!ast_strlen_zero(id))
02765       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02766 
02767    astman_send_ack(s, m, "Parked calls will follow");
02768 
02769    ast_mutex_lock(&parking_lock);
02770 
02771    for (cur = parkinglot; cur; cur = cur->next) {
02772       astman_append(s, "Event: ParkedCall\r\n"
02773          "Exten: %d\r\n"
02774          "Channel: %s\r\n"
02775          "From: %s\r\n"
02776          "Timeout: %ld\r\n"
02777          "CallerID: %s\r\n"
02778          "CallerIDName: %s\r\n"
02779          "%s"
02780          "\r\n",
02781          cur->parkingnum, cur->chan->name, cur->peername,
02782          (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
02783          S_OR(cur->chan->cid.cid_num, ""),   /* XXX in other places it is <unknown> */
02784          S_OR(cur->chan->cid.cid_name, ""),
02785          idText);
02786    }
02787 
02788    astman_append(s,
02789       "Event: ParkedCallsComplete\r\n"
02790       "%s"
02791       "\r\n",idText);
02792 
02793    ast_mutex_unlock(&parking_lock);
02794 
02795    return RESULT_SUCCESS;
02796 }
02797 
02798 static char mandescr_park[] =
02799 "Description: Park a channel.\n"
02800 "Variables: (Names marked with * are required)\n"
02801 "  *Channel: Channel name to park\n"
02802 "  *Channel2: Channel to announce park info to (and return to if timeout)\n"
02803 "  Timeout: Number of milliseconds to wait before callback.\n";  
02804 
02805 static int manager_park(struct mansession *s, const struct message *m)
02806 {
02807    const char *channel = astman_get_header(m, "Channel");
02808    const char *channel2 = astman_get_header(m, "Channel2");
02809    const char *timeout = astman_get_header(m, "Timeout");
02810    char buf[BUFSIZ];
02811    int to = 0;
02812    int res = 0;
02813    int parkExt = 0;
02814    struct ast_channel *ch1, *ch2;
02815 
02816    if (ast_strlen_zero(channel)) {
02817       astman_send_error(s, m, "Channel not specified");
02818       return 0;
02819    }
02820 
02821    if (ast_strlen_zero(channel2)) {
02822       astman_send_error(s, m, "Channel2 not specified");
02823       return 0;
02824    }
02825 
02826    ch1 = ast_get_channel_by_name_locked(channel);
02827    if (!ch1) {
02828       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
02829       astman_send_error(s, m, buf);
02830       return 0;
02831    }
02832 
02833    ch2 = ast_get_channel_by_name_locked(channel2);
02834    if (!ch2) {
02835       snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
02836       astman_send_error(s, m, buf);
02837       ast_channel_unlock(ch1);
02838       return 0;
02839    }
02840 
02841    if (!ast_strlen_zero(timeout)) {
02842       sscanf(timeout, "%30d", &to);
02843    }
02844 
02845    res = ast_masq_park_call(ch1, ch2, to, &parkExt);
02846    if (!res) {
02847       ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
02848       astman_send_ack(s, m, "Park successful");
02849    } else {
02850       astman_send_error(s, m, "Park failure");
02851    }
02852 
02853    ast_channel_unlock(ch1);
02854    ast_channel_unlock(ch2);
02855 
02856    return 0;
02857 }
02858 
02859 
02860 int ast_pickup_call(struct ast_channel *chan)
02861 {
02862    struct ast_channel *cur = NULL;
02863    int res = -1;
02864 
02865    while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
02866       if (!cur->pbx && 
02867          (cur != chan) &&
02868          (chan->pickupgroup & cur->callgroup) &&
02869          ((cur->_state == AST_STATE_RINGING) ||
02870           (cur->_state == AST_STATE_RING))) {
02871             break;
02872       }
02873       ast_channel_unlock(cur);
02874    }
02875    if (cur) {
02876       if (option_debug)
02877          ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
02878       res = ast_answer(chan);
02879       if (res)
02880          ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
02881       res = ast_queue_control(chan, AST_CONTROL_ANSWER);
02882       if (res)
02883          ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
02884       res = ast_channel_masquerade(cur, chan);
02885       if (res)
02886          ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);     /* Done */
02887       ast_channel_unlock(cur);
02888    } else   {
02889       if (option_debug)
02890          ast_log(LOG_DEBUG, "No call pickup possible...\n");
02891    }
02892    return res;
02893 }
02894 
02895 /*! \brief Add parking hints for all defined parking lots */
02896 static void park_add_hints(char *context, int start, int stop)
02897 {
02898    int numext;
02899    char device[AST_MAX_EXTENSION];
02900    char exten[10];
02901 
02902    for (numext = start; numext <= stop; numext++) {
02903       snprintf(exten, sizeof(exten), "%d", numext);
02904       snprintf(device, sizeof(device), "park:%s@%s", exten, context);
02905       ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
02906    }
02907 }
02908 
02909 
02910 static int load_config(void) 
02911 {
02912    int start = 0, end = 0;
02913    int res;
02914    struct ast_context *con = NULL;
02915    struct ast_config *cfg = NULL;
02916    struct ast_variable *var = NULL;
02917    char old_parking_ext[AST_MAX_EXTENSION];
02918    char old_parking_con[AST_MAX_EXTENSION] = "";
02919 
02920    if (!ast_strlen_zero(parking_con)) {
02921       strcpy(old_parking_ext, parking_ext);
02922       strcpy(old_parking_con, parking_con);
02923    } 
02924 
02925    /* Reset to defaults */
02926    strcpy(parking_con, "parkedcalls");
02927    strcpy(parking_con_dial, "park-dial");
02928    strcpy(parking_ext, "700");
02929    strcpy(pickup_ext, "*8");
02930    strcpy(parkmohclass, "default");
02931    courtesytone[0] = '\0';
02932    strcpy(xfersound, "beep");
02933    strcpy(xferfailsound, "pbx-invalid");
02934    parking_start = 701;
02935    parking_stop = 750;
02936    parkfindnext = 0;
02937    adsipark = 0;
02938    parkaddhints = 0;
02939    parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
02940    parkedcallreparking = 0;
02941    parkedcallhangup = 0;
02942    parkedcallrecording = 0;
02943 
02944    transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
02945    featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
02946    atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
02947 
02948    cfg = ast_config_load("features.conf");
02949    if (!cfg) {
02950       ast_log(LOG_WARNING,"Could not load features.conf\n");
02951       return AST_MODULE_LOAD_DECLINE;
02952    }
02953    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
02954       if (!strcasecmp(var->name, "parkext")) {
02955          ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
02956       } else if (!strcasecmp(var->name, "context")) {
02957          ast_copy_string(parking_con, var->value, sizeof(parking_con));
02958       } else if (!strcasecmp(var->name, "parkingtime")) {
02959          if ((sscanf(var->value, "%30d", &parkingtime) != 1) || (parkingtime < 1)) {
02960             ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
02961             parkingtime = DEFAULT_PARK_TIME;
02962          } else
02963             parkingtime = parkingtime * 1000;
02964       } else if (!strcasecmp(var->name, "parkpos")) {
02965          if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
02966             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);
02967          } else {
02968             parking_start = start;
02969             parking_stop = end;
02970          }
02971       } else if (!strcasecmp(var->name, "findslot")) {
02972          parkfindnext = (!strcasecmp(var->value, "next"));
02973       } else if (!strcasecmp(var->name, "parkinghints")) {
02974          parkaddhints = ast_true(var->value);
02975       } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
02976          if (!strcasecmp(var->value, "no"))
02977             parkedcalltransfers = 0;
02978          else if (!strcasecmp(var->value, "caller"))
02979             parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
02980          else if (!strcasecmp(var->value, "callee"))
02981             parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
02982          else if (!strcasecmp(var->value, "both"))
02983             parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
02984       } else if (!strcasecmp(var->name, "parkedcallreparking")) {
02985          if (!strcasecmp(var->value, "no"))
02986             parkedcallreparking = 0;
02987          else if (!strcasecmp(var->value, "caller"))
02988             parkedcallreparking = AST_FEATURE_FLAG_BYCALLER;
02989          else if (!strcasecmp(var->value, "callee"))
02990             parkedcallreparking = AST_FEATURE_FLAG_BYCALLEE;
02991          else if (!strcasecmp(var->value, "both"))
02992             parkedcallreparking = AST_FEATURE_FLAG_BYBOTH;
02993       } else if (!strcasecmp(var->name, "parkedcallhangup")) {
02994          if (!strcasecmp(var->value, "no"))
02995             parkedcallhangup = 0;
02996          else if (!strcasecmp(var->value, "caller"))
02997             parkedcallhangup = AST_FEATURE_FLAG_BYCALLER;
02998          else if (!strcasecmp(var->value, "callee"))
02999             parkedcallhangup = AST_FEATURE_FLAG_BYCALLEE;
03000          else if (!strcasecmp(var->value, "both"))
03001             parkedcallhangup = AST_FEATURE_FLAG_BYBOTH;
03002       } else if (!strcasecmp(var->name, "parkedcallrecording")) {
03003          if (!strcasecmp(var->value, "no"))
03004             parkedcallrecording = 0;
03005          else if (!strcasecmp(var->value, "caller"))
03006             parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
03007          else if (!strcasecmp(var->value, "callee"))
03008             parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
03009          else if (!strcasecmp(var->value, "both"))
03010             parkedcallrecording = AST_FEATURE_FLAG_BYBOTH;
03011       } else if (!strcasecmp(var->name, "adsipark")) {
03012          adsipark = ast_true(var->value);
03013       } else if (!strcasecmp(var->name, "transferdigittimeout")) {
03014          if ((sscanf(var->value, "%30d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
03015             ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
03016             transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
03017          } else
03018             transferdigittimeout = transferdigittimeout * 1000;
03019       } else if (!strcasecmp(var->name, "featuredigittimeout")) {
03020          if ((sscanf(var->value, "%30d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
03021             ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
03022             featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
03023          }
03024       } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
03025          if ((sscanf(var->value, "%30d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
03026             ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
03027             atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
03028          } else
03029             atxfernoanswertimeout = atxfernoanswertimeout * 1000;
03030       } else if (!strcasecmp(var->name, "courtesytone")) {
03031          ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
03032       }  else if (!strcasecmp(var->name, "parkedplay")) {
03033          if (!strcasecmp(var->value, "both"))
03034             parkedplay = 2;
03035          else if (!strcasecmp(var->value, "parked"))
03036             parkedplay = 1;
03037          else
03038             parkedplay = 0;
03039       } else if (!strcasecmp(var->name, "xfersound")) {
03040          ast_copy_string(xfersound, var->value, sizeof(xfersound));
03041       } else if (!strcasecmp(var->name, "xferfailsound")) {
03042          ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
03043       } else if (!strcasecmp(var->name, "pickupexten")) {
03044          ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
03045       } else if (!strcasecmp(var->name, "parkedmusicclass")) {
03046          ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
03047       }
03048    }
03049 
03050    unmap_features();
03051    for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
03052       if (remap_feature(var->name, var->value))
03053          ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
03054    }
03055 
03056    /* Map a key combination to an application*/
03057    ast_unregister_features();
03058    for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
03059       char *tmp_val = ast_strdupa(var->value);
03060       char *exten, *activateon, *activatedby, *app, *app_args, *moh_class; 
03061       struct ast_call_feature *feature;
03062 
03063       /* strsep() sets the argument to NULL if match not found, and it
03064        * is safe to use it with a NULL argument, so we don't check
03065        * between calls.
03066        */
03067       exten = strsep(&tmp_val,",");
03068       activatedby = strsep(&tmp_val,",");
03069       app = strsep(&tmp_val,",");
03070       app_args = strsep(&tmp_val,",");
03071       moh_class = strsep(&tmp_val,",");
03072 
03073       activateon = strsep(&activatedby, "/");   
03074 
03075       /*! \todo XXX var_name or app_args ? */
03076       if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
03077          ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
03078             app, exten, activateon, var->name);
03079          continue;
03080       }
03081 
03082       AST_RWLIST_RDLOCK(&feature_list);
03083       if ((feature = find_dynamic_feature(var->name))) {
03084          AST_RWLIST_UNLOCK(&feature_list);
03085          ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
03086          continue;
03087       }
03088       AST_RWLIST_UNLOCK(&feature_list);
03089             
03090       if (!(feature = ast_calloc(1, sizeof(*feature))))
03091          continue;               
03092 
03093       ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
03094       ast_copy_string(feature->app, app, FEATURE_APP_LEN);
03095       ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
03096       
03097       if (app_args) 
03098          ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
03099 
03100       if (moh_class)
03101          ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
03102          
03103       ast_copy_string(feature->exten, exten, sizeof(feature->exten));
03104       feature->operation = feature_exec_app;
03105       ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
03106 
03107       /* Allow caller and calle to be specified for backwards compatability */
03108       if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
03109          ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
03110       else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
03111          ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
03112       else {
03113          ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
03114             " must be 'self', or 'peer'\n", var->name);
03115          continue;
03116       }
03117 
03118       if (ast_strlen_zero(activatedby))
03119          ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
03120       else if (!strcasecmp(activatedby, "caller"))
03121          ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
03122       else if (!strcasecmp(activatedby, "callee"))
03123          ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
03124       else if (!strcasecmp(activatedby, "both"))
03125          ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
03126       else {
03127          ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
03128             " must be 'caller', or 'callee', or 'both'\n", var->name);
03129          continue;
03130       }
03131 
03132       ast_register_feature(feature);
03133          
03134       if (option_verbose >= 1)
03135          ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);  
03136    }   
03137    ast_config_destroy(cfg);
03138 
03139    /* Remove the old parking extension */
03140    if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
03141       if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
03142             notify_metermaids(old_parking_ext, old_parking_con);
03143       if (option_debug)
03144          ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
03145    }
03146    
03147    if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
03148       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
03149       return -1;
03150    }
03151    res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
03152    if (parkaddhints)
03153       park_add_hints(parking_con, parking_start, parking_stop);
03154    if (!res)
03155       notify_metermaids(ast_parking_ext(), parking_con);
03156    return res;
03157 
03158 }
03159 
03160 static int reload(void)
03161 {
03162    return load_config();
03163 }
03164 
03165 static int load_module(void)
03166 {
03167    int res;
03168    
03169    memset(parking_ext, 0, sizeof(parking_ext));
03170    memset(parking_con, 0, sizeof(parking_con));
03171 
03172    if ((res = load_config()))
03173       return res;
03174    ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
03175    ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
03176    res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
03177    if (!res)
03178       res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
03179    if (!res) {
03180       ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
03181       ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
03182          "Park a channel", mandescr_park); 
03183    }
03184 
03185    res |= ast_devstate_prov_add("Park", metermaidstate);
03186 
03187    return res;
03188 }
03189 
03190 
03191 static int unload_module(void)
03192 {
03193    ast_module_user_hangup_all();
03194 
03195    ast_manager_unregister("ParkedCalls");
03196    ast_manager_unregister("Park");
03197    ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
03198    ast_unregister_application(parkcall);
03199    ast_devstate_prov_del("Park");
03200    return ast_unregister_application(parkedcall);
03201 }
03202 
03203 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
03204       .load = load_module,
03205       .unload = unload_module,
03206       .reload = reload,
03207           );

Generated on Fri Sep 11 13:45:01 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7