Wed Feb 11 12:00:22 2009

Asterisk developer's documentation


features.h File Reference

Call Parking and Pickup API Includes code and algorithms from the Zapata library. More...

#include "asterisk/linkedlists.h"

Go to the source code of this file.

Data Structures

struct  ast_call_feature
 main call feature structure More...

Defines

#define FEATURE_APP_ARGS_LEN   256
#define FEATURE_APP_LEN   64
#define FEATURE_EXTEN_LEN   32
#define FEATURE_MAX_LEN   11
#define FEATURE_MOH_LEN   80
#define FEATURE_SNAME_LEN   32
#define PARK_APP_NAME   "Park"

Functions

int ast_bridge_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
 Bridge a call, optionally allowing redirection.
int ast_masq_park_call (struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout)
 Park a call via a masqueraded channel.
int ast_park_call (struct ast_channel *chan, struct ast_channel *host, int timeout, int *extout)
 Park a call and read back parked location.
char * ast_parking_ext (void)
 Determine system parking extension Returns the call parking extension for drivers that provide special call parking help.
int ast_pickup_call (struct ast_channel *chan)
 Pickup a call.
char * ast_pickup_ext (void)
 Determine system call pickup extension.
void ast_register_feature (struct ast_call_feature *feature)
 register new feature into feature_set
void ast_unregister_feature (struct ast_call_feature *feature)
 unregister feature from feature_set


Detailed Description

Call Parking and Pickup API Includes code and algorithms from the Zapata library.

Definition in file features.h.


Define Documentation

#define FEATURE_APP_ARGS_LEN   256

Definition at line 31 of file features.h.

#define FEATURE_APP_LEN   64

Definition at line 30 of file features.h.

#define FEATURE_EXTEN_LEN   32

Definition at line 33 of file features.h.

#define FEATURE_MAX_LEN   11

Definition at line 29 of file features.h.

Referenced by ast_bridge_call().

#define FEATURE_MOH_LEN   80

Definition at line 34 of file features.h.

#define FEATURE_SNAME_LEN   32

Definition at line 32 of file features.h.

#define PARK_APP_NAME   "Park"

Definition at line 36 of file features.h.

Referenced by handle_exec().


Function Documentation

int ast_bridge_call ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config 
)

Bridge a call, optionally allowing redirection.

append the event to featurecode. we rely on the string being zero-filled, and not overflowing it.

Todo:
XXX how do we guarantee the latter ?

Definition at line 1477 of file res_features.c.

References ast_channel::_state, ast_cdr::accountcode, ast_channel::accountcode, ast_cdr::amaflags, ast_channel::amaflags, ast_cdr::answer, ast_channel::appl, ast_answer(), ast_bridged_channel(), ast_cdr_alloc(), ast_cdr_answer(), AST_CDR_ANSWERED, ast_cdr_detach(), ast_cdr_dup(), ast_cdr_end(), AST_CDR_FLAG_BRIDGED, AST_CDR_FLAG_MAIN, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NULL, ast_cdr_setcid(), ast_cdr_specialized_reset(), ast_cdr_start(), ast_cdr_update(), ast_channel_bridge(), ast_channel_lock, ast_channel_setoption(), ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_ATXFERCMD, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OPTION, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_default_amaflags, ast_dtmf_stream(), ast_exists_extension(), ast_feature_interpret(), AST_FEATURE_NO_H_EXTEN, AST_FEATURE_PLAY_WARNING, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, ast_frfree, ast_get_channel_by_name_locked(), ast_indicate(), ast_indicate_data(), ast_log(), AST_MAX_EXTENSION, ast_opt_end_cdr_before_h_exten, AST_OPTION_FLAG_REQUEST, ast_set2_flag, ast_set_flag, ast_spawn_extension(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_verbose(), ast_channel::cdr, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_num, cmd_atxfer(), config, ast_channel::context, ast_channel::data, ast_option_header::data, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_channel::exten, f, FEATURE_MAX_LEN, FEATURE_RETURN_PASSDIGITS, FEATURE_RETURN_SUCCESS, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_option_header::flag, ast_cdr::lastapp, ast_cdr::lastdata, LOG_DEBUG, LOG_WARNING, monitor_app, ast_channel::name, ast_cdr::next, ast_option_header::option, option_debug, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), pick_unlocked_cdr(), ast_channel::priority, set_config_flags(), ast_cdr::start, ast_cdr::uniqueid, ast_channel::uniqueid, ast_cdr::userfield, VERBOSE_PREFIX_2, and ast_channel::visible_indication.

Referenced by app_exec(), ast_bridge_call_thread(), do_atxfer(), park_exec(), and try_calling().

01478 {
01479    /* Copy voice back and forth between the two channels.  Give the peer
01480       the ability to transfer calls with '#<extension' syntax. */
01481    struct ast_frame *f;
01482    struct ast_channel *who;
01483    char chan_featurecode[FEATURE_MAX_LEN + 1]="";
01484    char peer_featurecode[FEATURE_MAX_LEN + 1]="";
01485    char orig_channame[AST_MAX_EXTENSION];
01486    char orig_peername[AST_MAX_EXTENSION];
01487 
01488    int res;
01489    int diff;
01490    int hasfeatures=0;
01491    int hadfeatures=0;
01492    int autoloopflag;
01493    struct ast_option_header *aoh;
01494    struct ast_bridge_config backup_config;
01495    struct ast_cdr *bridge_cdr = NULL;
01496    struct ast_cdr *orig_peer_cdr = NULL;
01497    struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
01498    struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
01499    struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
01500    struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
01501 
01502    memset(&backup_config, 0, sizeof(backup_config));
01503 
01504    config->start_time = ast_tvnow();
01505 
01506    if (chan && peer) {
01507       pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
01508       pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
01509    } else if (chan) {
01510       pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
01511    }
01512 
01513    /* This is an interesting case.  One example is if a ringing channel gets redirected to
01514     * an extension that picks up a parked call.  This will make sure that the call taken
01515     * out of parking gets told that the channel it just got bridged to is still ringing. */
01516    if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
01517       ast_indicate(peer, AST_CONTROL_RINGING);
01518    }
01519 
01520    if (monitor_ok) {
01521       const char *monitor_exec;
01522       struct ast_channel *src = NULL;
01523       if (!monitor_app) { 
01524          if (!(monitor_app = pbx_findapp("Monitor")))
01525             monitor_ok=0;
01526       }
01527       if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
01528          src = chan;
01529       else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
01530          src = peer;
01531       if (monitor_app && src) {
01532          char *tmp = ast_strdupa(monitor_exec);
01533          pbx_exec(src, monitor_app, tmp);
01534       }
01535    }
01536    
01537    set_config_flags(chan, peer, config);
01538    config->firstpass = 1;
01539 
01540    /* Answer if need be */
01541    if (ast_answer(chan))
01542       return -1;
01543 
01544    ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
01545    ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
01546    orig_peer_cdr = peer_cdr;
01547    
01548    if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
01549          
01550       if (chan_cdr) {
01551          ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
01552          ast_cdr_update(chan);
01553          bridge_cdr = ast_cdr_dup(chan_cdr);
01554          ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
01555          ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
01556       } else {
01557          /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
01558          bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
01559          ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
01560          ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
01561          ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
01562          ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
01563          ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
01564          ast_cdr_setcid(bridge_cdr, chan);
01565          bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
01566          bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
01567          ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
01568          /* Destination information */
01569          ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
01570          ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
01571          if (peer_cdr) {
01572             bridge_cdr->start = peer_cdr->start;
01573             ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
01574          } else {
01575             ast_cdr_start(bridge_cdr);
01576          }
01577       }
01578       /* peer_cdr->answer will be set when a macro runs on the peer;
01579          in that case, the bridge answer will be delayed while the
01580          macro plays on the peer channel. The peer answered the call
01581          before the macro started playing. To the phone system,
01582          this is billable time for the call, even tho the caller
01583          hears nothing but ringing while the macro does its thing. */
01584       if (peer_cdr && !ast_tvzero(peer_cdr->answer)) {
01585          bridge_cdr->answer = peer_cdr->answer;
01586          chan_cdr->answer = peer_cdr->answer;
01587          bridge_cdr->disposition = peer_cdr->disposition;
01588          chan_cdr->disposition = peer_cdr->disposition;
01589       } else {
01590          ast_cdr_answer(bridge_cdr);
01591          ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
01592       }
01593       ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
01594       if (peer_cdr) {
01595          ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
01596       }
01597    }
01598    
01599    for (;;) {
01600       struct ast_channel *other; /* used later */
01601       
01602       res = ast_channel_bridge(chan, peer, config, &f, &who);
01603       
01604       if (config->feature_timer) {
01605          /* Update time limit for next pass */
01606          diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
01607          config->feature_timer -= diff;
01608          if (hasfeatures) {
01609             /* Running on backup config, meaning a feature might be being
01610                activated, but that's no excuse to keep things going 
01611                indefinitely! */
01612             if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
01613                if (option_debug)
01614                   ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
01615                config->feature_timer = 0;
01616                who = chan;
01617                if (f)
01618                   ast_frfree(f);
01619                f = NULL;
01620                res = 0;
01621             } else if (config->feature_timer <= 0) {
01622                /* Not *really* out of time, just out of time for
01623                   digits to come in for features. */
01624                if (option_debug)
01625                   ast_log(LOG_DEBUG, "Timed out for feature!\n");
01626                if (!ast_strlen_zero(peer_featurecode)) {
01627                   ast_dtmf_stream(chan, peer, peer_featurecode, 0);
01628                   memset(peer_featurecode, 0, sizeof(peer_featurecode));
01629                }
01630                if (!ast_strlen_zero(chan_featurecode)) {
01631                   ast_dtmf_stream(peer, chan, chan_featurecode, 0);
01632                   memset(chan_featurecode, 0, sizeof(chan_featurecode));
01633                }
01634                if (f)
01635                   ast_frfree(f);
01636                hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01637                if (!hasfeatures) {
01638                   /* Restore original (possibly time modified) bridge config */
01639                   memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01640                   memset(&backup_config, 0, sizeof(backup_config));
01641                }
01642                hadfeatures = hasfeatures;
01643                /* Continue as we were */
01644                continue;
01645             } else if (!f) {
01646                /* The bridge returned without a frame and there is a feature in progress.
01647                 * However, we don't think the feature has quite yet timed out, so just
01648                 * go back into the bridge. */
01649                continue;
01650             }
01651          } else {
01652             if (config->feature_timer <=0) {
01653                /* We ran out of time */
01654                config->feature_timer = 0;
01655                who = chan;
01656                if (f)
01657                   ast_frfree(f);
01658                f = NULL;
01659                res = 0;
01660             }
01661          }
01662       }
01663       if (res < 0) {
01664          if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
01665             ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
01666          goto before_you_go;
01667       }
01668       
01669       if (!f || (f->frametype == AST_FRAME_CONTROL &&
01670             (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 
01671                f->subclass == AST_CONTROL_CONGESTION ) ) ) {
01672          res = -1;
01673          break;
01674       }
01675       /* many things should be sent to the 'other' channel */
01676       other = (who == chan) ? peer : chan;
01677       if (f->frametype == AST_FRAME_CONTROL) {
01678          switch (f->subclass) {
01679          case AST_CONTROL_RINGING:
01680          case AST_CONTROL_FLASH:
01681          case -1:
01682             ast_indicate(other, f->subclass);
01683             break;
01684          case AST_CONTROL_HOLD:
01685          case AST_CONTROL_UNHOLD:
01686             ast_indicate_data(other, f->subclass, f->data, f->datalen);
01687             break;
01688          case AST_CONTROL_OPTION:
01689             aoh = f->data;
01690             /* Forward option Requests */
01691             if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
01692                ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 
01693                   f->datalen - sizeof(struct ast_option_header), 0);
01694             }
01695             break;
01696          case AST_CONTROL_ATXFERCMD:
01697             cmd_atxfer(chan, peer, config, who, f->data);
01698             break;
01699          }
01700       } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
01701          /* eat it */
01702       } else if (f->frametype == AST_FRAME_DTMF) {
01703          char *featurecode;
01704          int sense;
01705 
01706          hadfeatures = hasfeatures;
01707          /* This cannot overrun because the longest feature is one shorter than our buffer */
01708          if (who == chan) {
01709             sense = FEATURE_SENSE_CHAN;
01710             featurecode = chan_featurecode;
01711          } else  {
01712             sense = FEATURE_SENSE_PEER;
01713             featurecode = peer_featurecode;
01714          }
01715          /*! append the event to featurecode. we rely on the string being zero-filled, and
01716           * not overflowing it. 
01717           * \todo XXX how do we guarantee the latter ?
01718           */
01719          featurecode[strlen(featurecode)] = f->subclass;
01720          /* Get rid of the frame before we start doing "stuff" with the channels */
01721          ast_frfree(f);
01722          f = NULL;
01723          config->feature_timer = backup_config.feature_timer;
01724          res = ast_feature_interpret(chan, peer, config, featurecode, sense);
01725          switch(res) {
01726          case FEATURE_RETURN_PASSDIGITS:
01727             ast_dtmf_stream(other, who, featurecode, 0);
01728             /* Fall through */
01729          case FEATURE_RETURN_SUCCESS:
01730             memset(featurecode, 0, sizeof(chan_featurecode));
01731             break;
01732          }
01733          if (res >= FEATURE_RETURN_PASSDIGITS) {
01734             res = 0;
01735          } else 
01736             break;
01737          hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01738          if (hadfeatures && !hasfeatures) {
01739             /* Restore backup */
01740             memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01741             memset(&backup_config, 0, sizeof(struct ast_bridge_config));
01742          } else if (hasfeatures) {
01743             if (!hadfeatures) {
01744                /* Backup configuration */
01745                memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
01746                /* Setup temporary config options */
01747                config->play_warning = 0;
01748                ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
01749                ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
01750                config->warning_freq = 0;
01751                config->warning_sound = NULL;
01752                config->end_sound = NULL;
01753                config->start_sound = NULL;
01754                config->firstpass = 0;
01755             }
01756             config->start_time = ast_tvnow();
01757             config->feature_timer = featuredigittimeout;
01758             if (option_debug)
01759                ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
01760          }
01761       }
01762       if (f)
01763          ast_frfree(f);
01764 
01765    }
01766   before_you_go:
01767    if (config->end_bridge_callback) {
01768       config->end_bridge_callback(config->end_bridge_callback_data);
01769    }
01770 
01771    autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
01772    ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
01773    if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
01774       struct ast_cdr *swapper = NULL;
01775       char savelastapp[AST_MAX_EXTENSION];
01776       char savelastdata[AST_MAX_EXTENSION];
01777       char save_exten[AST_MAX_EXTENSION];
01778       int  save_prio;
01779       
01780       if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
01781          ast_cdr_end(bridge_cdr);
01782       }
01783       /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
01784          dialplan code operate on it */
01785       ast_channel_lock(chan);
01786       if (bridge_cdr) {
01787          swapper = chan->cdr;
01788          ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
01789          ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
01790          chan->cdr = bridge_cdr;
01791       }
01792       ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
01793       ast_copy_string(chan->exten, "h", sizeof(chan->exten));
01794       save_prio = chan->priority;
01795       chan->priority = 1;
01796       ast_channel_unlock(chan);
01797       while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
01798          if (ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
01799             /* Something bad happened, or a hangup has been requested. */
01800             if (option_debug)
01801                ast_log(LOG_DEBUG, "Spawn h extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
01802             if (option_verbose > 1)
01803                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);
01804             break;
01805          }
01806          chan->priority++;
01807       }
01808       /* swap it back */
01809       ast_channel_lock(chan);
01810       ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
01811       chan->priority = save_prio;
01812       if (bridge_cdr)
01813          chan->cdr = swapper;
01814       ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
01815       ast_channel_unlock(chan);
01816       /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
01817       if (bridge_cdr) {
01818          ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
01819          ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
01820       }
01821    }
01822    ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
01823 
01824    /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
01825    new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
01826    if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) {
01827       ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
01828    }
01829 
01830    /* we can post the bridge CDR at this point */
01831    if (bridge_cdr) {
01832       ast_cdr_end(bridge_cdr);
01833       ast_cdr_detach(bridge_cdr);
01834    }
01835    
01836    /* do a specialized reset on the beginning channel
01837       CDR's, if they still exist, so as not to mess up
01838       issues in future bridges;
01839       
01840       Here are the rules of the game:
01841       1. The chan and peer channel pointers will not change
01842          during the life of the bridge.
01843       2. But, in transfers, the channel names will change.
01844          between the time the bridge is started, and the
01845          time the channel ends. 
01846          Usually, when a channel changes names, it will
01847          also change CDR pointers.
01848       3. Usually, only one of the two channels (chan or peer)
01849          will change names.
01850       4. Usually, if a channel changes names during a bridge,
01851          it is because of a transfer. Usually, in these situations,
01852          it is normal to see 2 bridges running simultaneously, and
01853          it is not unusual to see the two channels that change
01854          swapped between bridges.
01855       5. After a bridge occurs, we have 2 or 3 channels' CDRs
01856          to attend to; if the chan or peer changed names,
01857          we have the before and after attached CDR's.
01858    */
01859    
01860    if (new_chan_cdr) {
01861       struct ast_channel *chan_ptr = NULL;
01862       
01863       if (strcasecmp(orig_channame, chan->name) != 0) { 
01864          /* old channel */
01865          chan_ptr = ast_get_channel_by_name_locked(orig_channame);
01866          if (chan_ptr) {
01867             if (!ast_bridged_channel(chan_ptr)) {
01868                struct ast_cdr *cur;
01869                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
01870                   if (cur == chan_cdr) {
01871                      break;
01872                   }
01873                }
01874                if (cur)
01875                   ast_cdr_specialized_reset(chan_cdr,0);
01876             }
01877             ast_channel_unlock(chan_ptr);
01878          }
01879          /* new channel */
01880          ast_cdr_specialized_reset(new_chan_cdr,0);
01881       } else {
01882          ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr  */
01883       }
01884    }
01885 
01886    {
01887       struct ast_channel *chan_ptr = NULL;
01888       new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
01889       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))
01890          ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
01891       if (strcasecmp(orig_peername, peer->name) != 0) { 
01892          /* old channel */
01893          chan_ptr = ast_get_channel_by_name_locked(orig_peername);
01894          if (chan_ptr) {
01895             if (!ast_bridged_channel(chan_ptr)) {
01896                struct ast_cdr *cur;
01897                for (cur = chan_ptr->cdr; cur; cur = cur->next) {
01898                   if (cur == peer_cdr) {
01899                      break;
01900                   }
01901                }
01902                if (cur)
01903                   ast_cdr_specialized_reset(peer_cdr,0);
01904             }
01905             ast_channel_unlock(chan_ptr);
01906          }
01907          /* new channel */
01908          ast_cdr_specialized_reset(new_peer_cdr,0);
01909       } else {
01910          ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr  */
01911       }
01912    }
01913    return res;
01914 }

int ast_masq_park_call ( struct ast_channel rchan,
struct ast_channel host,
int  timeout,
int *  extout 
)

Park a call via a masqueraded channel.

Parameters:
rchan the real channel to be parked
host the channel to have the parking read to Masquerade the channel rchan into a new, empty channel which is then parked with ast_park_call
timeout is a timeout in milliseconds
extout is a parameter to an int that will hold the parked location, or NULL if you want

Definition at line 530 of file res_features.c.

References masq_park_call().

Referenced by handle_exec(), manager_park(), mgcp_ss(), parkandannounce_exec(), and ss_thread().

00531 {
00532    return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
00533 }

int ast_park_call ( struct ast_channel chan,
struct ast_channel peer,
int  timeout,
int *  extout 
)

Park a call and read back parked location.

Note:
We put the user in the parking list, then wake up the parking thread to be sure it looks after these channels too

Definition at line 482 of file res_features.c.

References park_call_full().

Referenced by iax_park_thread(), and sip_park_thread().

00483 {
00484    return park_call_full(chan, peer, timeout, extout, NULL);
00485 }

char* ast_parking_ext ( void   ) 

Determine system parking extension Returns the call parking extension for drivers that provide special call parking help.

Definition at line 162 of file res_features.c.

Referenced by builtin_blindtransfer(), dp_lookup(), handle_request_refer(), mgcp_ss(), socket_process(), and ss_thread().

00163 {
00164    return parking_ext;
00165 }

int ast_pickup_call ( struct ast_channel chan  ) 

Pickup a call.

Definition at line 2494 of file res_features.c.

References ast_channel::_state, ast_answer(), ast_channel_masquerade(), ast_channel_unlock, ast_channel_walk_locked(), AST_CONTROL_ANSWER, ast_log(), ast_queue_control(), AST_STATE_RING, AST_STATE_RINGING, ast_channel::callgroup, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_debug, ast_channel::pbx, and ast_channel::pickupgroup.

Referenced by cb_events(), handle_request_invite(), mgcp_ss(), and ss_thread().

02495 {
02496    struct ast_channel *cur = NULL;
02497    int res = -1;
02498 
02499    while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
02500       if (!cur->pbx && 
02501          (cur != chan) &&
02502          (chan->pickupgroup & cur->callgroup) &&
02503          ((cur->_state == AST_STATE_RINGING) ||
02504           (cur->_state == AST_STATE_RING))) {
02505             break;
02506       }
02507       ast_channel_unlock(cur);
02508    }
02509    if (cur) {
02510       if (option_debug)
02511          ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
02512       res = ast_answer(chan);
02513       if (res)
02514          ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
02515       res = ast_queue_control(chan, AST_CONTROL_ANSWER);
02516       if (res)
02517          ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
02518       res = ast_channel_masquerade(cur, chan);
02519       if (res)
02520          ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);     /* Done */
02521       ast_channel_unlock(cur);
02522    } else   {
02523       if (option_debug)
02524          ast_log(LOG_DEBUG, "No call pickup possible...\n");
02525    }
02526    return res;
02527 }

char* ast_pickup_ext ( void   ) 

Determine system call pickup extension.

Definition at line 167 of file res_features.c.

Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().

00168 {
00169    return pickup_ext;
00170 }

void ast_register_feature ( struct ast_call_feature feature  ) 

register new feature into feature_set

Parameters:
feature an ast_call_feature object which contains a keysequence and a callback function which is called when this keysequence is pressed during a call.

Definition at line 1047 of file res_features.c.

References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), ast_call_feature::feature_entry, LOG_NOTICE, option_verbose, ast_call_feature::sname, and VERBOSE_PREFIX_2.

01048 {
01049    if (!feature) {
01050       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
01051          return;
01052    }
01053   
01054    AST_RWLIST_WRLOCK(&feature_list);
01055    AST_RWLIST_INSERT_HEAD(&feature_list, feature, feature_entry);
01056    AST_RWLIST_UNLOCK(&feature_list);
01057 
01058    if (option_verbose >= 2) {
01059       ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
01060    }
01061 }

void ast_unregister_feature ( struct ast_call_feature feature  ) 

unregister feature from feature_set

Parameters:
feature the ast_call_feature object which was registered before

Definition at line 1064 of file res_features.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_call_feature::feature_entry, and free.

01065 {
01066    if (!feature)
01067       return;
01068 
01069    AST_RWLIST_WRLOCK(&feature_list);
01070    AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
01071    AST_RWLIST_UNLOCK(&feature_list);
01072    
01073    free(feature);
01074 }


Generated on Wed Feb 11 12:00:22 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7