#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 |
Definition in file features.h.
#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 |
#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" |
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.
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.
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.
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
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
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 }