Sat Nov 1 06:29:04 2008

Asterisk developer's documentation


features.h File Reference

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

This graph shows which files directly or indirectly include this file:

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 29 of file features.h.

#define FEATURE_APP_LEN   64

Definition at line 28 of file features.h.

#define FEATURE_EXTEN_LEN   32

Definition at line 31 of file features.h.

#define FEATURE_MAX_LEN   11

Definition at line 27 of file features.h.

Referenced by ast_bridge_call().

#define FEATURE_MOH_LEN   80

Definition at line 32 of file features.h.

#define FEATURE_SNAME_LEN   32

Definition at line 30 of file features.h.

#define PARK_APP_NAME   "Park"

Definition at line 34 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 1437 of file res_features.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, 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_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OPTION, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, 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_PBX_KEEPALIVE, AST_PBX_NO_HANGUP_PEER_PARKED, ast_set2_flag, ast_set_flag, ast_spawn_extension(), AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verbose(), ast_channel::cdr, ast_cdr::channel, config, ast_option_header::data, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, 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_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(), set_config_flags(), ast_cdr::start, ast_cdr::uniqueid, ast_cdr::userfield, and VERBOSE_PREFIX_2.

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

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

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 529 of file res_features.c.

References masq_park_call().

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

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

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 484 of file res_features.c.

References park_call_full().

Referenced by builtin_blindtransfer(), builtin_parkcall(), iax_park_thread(), and sip_park_thread().

00485 {
00486    return park_call_full(chan, peer, timeout, extout, NULL);
00487 }

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 2446 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, option_debug, ast_channel::pbx, and ast_channel::pickupgroup.

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

02447 {
02448    struct ast_channel *cur = NULL;
02449    int res = -1;
02450 
02451    while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
02452       if (!cur->pbx && 
02453          (cur != chan) &&
02454          (chan->pickupgroup & cur->callgroup) &&
02455          ((cur->_state == AST_STATE_RINGING) ||
02456           (cur->_state == AST_STATE_RING))) {
02457             break;
02458       }
02459       ast_channel_unlock(cur);
02460    }
02461    if (cur) {
02462       if (option_debug)
02463          ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
02464       res = ast_answer(chan);
02465       if (res)
02466          ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
02467       res = ast_queue_control(chan, AST_CONTROL_ANSWER);
02468       if (res)
02469          ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
02470       res = ast_channel_masquerade(cur, chan);
02471       if (res)
02472          ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);     /* Done */
02473       ast_channel_unlock(cur);
02474    } else   {
02475       if (option_debug)
02476          ast_log(LOG_DEBUG, "No call pickup possible...\n");
02477    }
02478    return res;
02479 }

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 1010 of file res_features.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_verbose(), LOG_NOTICE, option_verbose, ast_call_feature::sname, and VERBOSE_PREFIX_2.

01011 {
01012    if (!feature) {
01013       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
01014          return;
01015    }
01016   
01017    AST_LIST_LOCK(&feature_list);
01018    AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
01019    AST_LIST_UNLOCK(&feature_list);
01020 
01021    if (option_verbose >= 2) 
01022       ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
01023 }

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 1026 of file res_features.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.

01027 {
01028    if (!feature)
01029       return;
01030 
01031    AST_LIST_LOCK(&feature_list);
01032    AST_LIST_REMOVE(&feature_list,feature,feature_entry);
01033    AST_LIST_UNLOCK(&feature_list);
01034    free(feature);
01035 }


Generated on Sat Nov 1 06:29:04 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1