#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 1647 of file res_features.c.
References ast_channel::_state, ast_cdr::accountcode, ast_channel::accountcode, add_features_datastores(), ast_cdr::amaflags, ast_channel::amaflags, ast_cdr::answer, ast_channel::appl, ast_answer(), AST_BRIDGE_RETRY, ast_bridged_channel(), ast_cdr_alloc(), ast_cdr_answer(), AST_CDR_ANSWERED, ast_cdr_detach(), ast_cdr_discard(), 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_DONT, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, 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_bridge_features_on_config(), 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().
01648 { 01649 /* Copy voice back and forth between the two channels. Give the peer 01650 the ability to transfer calls with '#<extension' syntax. */ 01651 struct ast_frame *f; 01652 struct ast_channel *who; 01653 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 01654 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 01655 char orig_channame[AST_MAX_EXTENSION]; 01656 char orig_peername[AST_MAX_EXTENSION]; 01657 01658 int res; 01659 int diff; 01660 int hasfeatures=0; 01661 int hadfeatures=0; 01662 int autoloopflag; 01663 struct ast_option_header *aoh; 01664 struct ast_bridge_config backup_config; 01665 struct ast_cdr *bridge_cdr = NULL; 01666 struct ast_cdr *orig_peer_cdr = NULL; 01667 struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 01668 struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 01669 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 01670 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 01671 01672 memset(&backup_config, 0, sizeof(backup_config)); 01673 01674 config->start_time = ast_tvnow(); 01675 01676 if (chan && peer) { 01677 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01678 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01679 } else if (chan) { 01680 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01681 } 01682 01683 set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES")); 01684 add_features_datastores(chan, peer, config); 01685 01686 /* This is an interesting case. One example is if a ringing channel gets redirected to 01687 * an extension that picks up a parked call. This will make sure that the call taken 01688 * out of parking gets told that the channel it just got bridged to is still ringing. */ 01689 if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) { 01690 ast_indicate(peer, AST_CONTROL_RINGING); 01691 } 01692 01693 if (monitor_ok) { 01694 const char *monitor_exec; 01695 struct ast_channel *src = NULL; 01696 if (!monitor_app) { 01697 if (!(monitor_app = pbx_findapp("Monitor"))) 01698 monitor_ok=0; 01699 } 01700 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01701 src = chan; 01702 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01703 src = peer; 01704 if (monitor_app && src) { 01705 char *tmp = ast_strdupa(monitor_exec); 01706 pbx_exec(src, monitor_app, tmp); 01707 } 01708 } 01709 01710 set_config_flags(chan, peer, config); 01711 config->firstpass = 1; 01712 01713 /* Answer if need be */ 01714 if (ast_answer(chan)) 01715 return -1; 01716 01717 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame)); 01718 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername)); 01719 orig_peer_cdr = peer_cdr; 01720 01721 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) { 01722 01723 if (chan_cdr) { 01724 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); 01725 ast_cdr_update(chan); 01726 bridge_cdr = ast_cdr_dup(chan_cdr); 01727 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp)); 01728 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata)); 01729 } else { 01730 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */ 01731 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */ 01732 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel)); 01733 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel)); 01734 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid)); 01735 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp)); 01736 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata)); 01737 ast_cdr_setcid(bridge_cdr, chan); 01738 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL; 01739 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags; 01740 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode)); 01741 /* Destination information */ 01742 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst)); 01743 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext)); 01744 if (peer_cdr) { 01745 bridge_cdr->start = peer_cdr->start; 01746 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 01747 } else { 01748 ast_cdr_start(bridge_cdr); 01749 } 01750 } 01751 /* peer_cdr->answer will be set when a macro runs on the peer; 01752 in that case, the bridge answer will be delayed while the 01753 macro plays on the peer channel. The peer answered the call 01754 before the macro started playing. To the phone system, 01755 this is billable time for the call, even tho the caller 01756 hears nothing but ringing while the macro does its thing. */ 01757 if (peer_cdr && !ast_tvzero(peer_cdr->answer)) { 01758 bridge_cdr->answer = peer_cdr->answer; 01759 chan_cdr->answer = peer_cdr->answer; 01760 bridge_cdr->disposition = peer_cdr->disposition; 01761 chan_cdr->disposition = peer_cdr->disposition; 01762 } else { 01763 ast_cdr_answer(bridge_cdr); 01764 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */ 01765 } 01766 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) { 01767 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED); 01768 if (peer_cdr) { 01769 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED); 01770 } 01771 } 01772 } 01773 01774 for (;;) { 01775 struct ast_channel *other; /* used later */ 01776 01777 res = ast_channel_bridge(chan, peer, config, &f, &who); 01778 01779 /* When frame is not set, we are probably involved in a situation 01780 where we've timed out. 01781 When frame is set, we'll come thru this code twice; once for DTMF_BEGIN 01782 and also for DTMF_END. If we flow into the following 'if' for both, then 01783 our wait times are cut in half, as both will subtract from the 01784 feature_timer. Not good! 01785 */ 01786 if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) { 01787 /* Update time limit for next pass */ 01788 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 01789 if (res == AST_BRIDGE_RETRY) { 01790 /* The feature fully timed out but has not been updated. Skip 01791 * the potential round error from the diff calculation and 01792 * explicitly set to expired. */ 01793 config->feature_timer = -1; 01794 } else { 01795 config->feature_timer -= diff; 01796 } 01797 01798 if (hasfeatures) { 01799 /* Running on backup config, meaning a feature might be being 01800 activated, but that's no excuse to keep things going 01801 indefinitely! */ 01802 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01803 if (option_debug) 01804 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01805 config->feature_timer = 0; 01806 who = chan; 01807 if (f) 01808 ast_frfree(f); 01809 f = NULL; 01810 res = 0; 01811 } else if (config->feature_timer <= 0) { 01812 /* Not *really* out of time, just out of time for 01813 digits to come in for features. */ 01814 if (option_debug) 01815 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01816 if (!ast_strlen_zero(peer_featurecode)) { 01817 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01818 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01819 } 01820 if (!ast_strlen_zero(chan_featurecode)) { 01821 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01822 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01823 } 01824 if (f) 01825 ast_frfree(f); 01826 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01827 if (!hasfeatures) { 01828 /* Restore original (possibly time modified) bridge config */ 01829 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01830 memset(&backup_config, 0, sizeof(backup_config)); 01831 } 01832 hadfeatures = hasfeatures; 01833 /* Continue as we were */ 01834 continue; 01835 } else if (!f) { 01836 /* The bridge returned without a frame and there is a feature in progress. 01837 * However, we don't think the feature has quite yet timed out, so just 01838 * go back into the bridge. */ 01839 continue; 01840 } 01841 } else { 01842 if (config->feature_timer <=0) { 01843 /* We ran out of time */ 01844 config->feature_timer = 0; 01845 who = chan; 01846 if (f) 01847 ast_frfree(f); 01848 f = NULL; 01849 res = 0; 01850 } 01851 } 01852 } 01853 if (res < 0) { 01854 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) 01855 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01856 goto before_you_go; 01857 } 01858 01859 if (!f || (f->frametype == AST_FRAME_CONTROL && 01860 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 01861 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 01862 res = -1; 01863 break; 01864 } 01865 /* many things should be sent to the 'other' channel */ 01866 other = (who == chan) ? peer : chan; 01867 if (f->frametype == AST_FRAME_CONTROL) { 01868 switch (f->subclass) { 01869 case AST_CONTROL_RINGING: 01870 case AST_CONTROL_FLASH: 01871 case -1: 01872 ast_indicate(other, f->subclass); 01873 break; 01874 case AST_CONTROL_HOLD: 01875 case AST_CONTROL_UNHOLD: 01876 ast_indicate_data(other, f->subclass, f->data, f->datalen); 01877 break; 01878 case AST_CONTROL_OPTION: 01879 aoh = f->data; 01880 /* Forward option Requests */ 01881 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 01882 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 01883 f->datalen - sizeof(struct ast_option_header), 0); 01884 } 01885 break; 01886 case AST_CONTROL_ATXFERCMD: 01887 cmd_atxfer(chan, peer, config, who, f->data); 01888 break; 01889 } 01890 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 01891 /* eat it */ 01892 } else if (f->frametype == AST_FRAME_DTMF) { 01893 char *featurecode; 01894 int sense; 01895 01896 hadfeatures = hasfeatures; 01897 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01898 if (who == chan) { 01899 sense = FEATURE_SENSE_CHAN; 01900 featurecode = chan_featurecode; 01901 } else { 01902 sense = FEATURE_SENSE_PEER; 01903 featurecode = peer_featurecode; 01904 } 01905 /*! append the event to featurecode. we rely on the string being zero-filled, and 01906 * not overflowing it. 01907 * \todo XXX how do we guarantee the latter ? 01908 */ 01909 featurecode[strlen(featurecode)] = f->subclass; 01910 /* Get rid of the frame before we start doing "stuff" with the channels */ 01911 ast_frfree(f); 01912 f = NULL; 01913 config->feature_timer = backup_config.feature_timer; 01914 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01915 switch(res) { 01916 case FEATURE_RETURN_PASSDIGITS: 01917 ast_dtmf_stream(other, who, featurecode, 0); 01918 /* Fall through */ 01919 case FEATURE_RETURN_SUCCESS: 01920 memset(featurecode, 0, sizeof(chan_featurecode)); 01921 break; 01922 } 01923 if (res >= FEATURE_RETURN_PASSDIGITS) { 01924 res = 0; 01925 } else 01926 break; 01927 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01928 if (hadfeatures && !hasfeatures) { 01929 /* Restore backup */ 01930 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01931 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01932 } else if (hasfeatures) { 01933 if (!hadfeatures) { 01934 /* Backup configuration */ 01935 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01936 /* Setup temporary config options */ 01937 config->play_warning = 0; 01938 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01939 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01940 config->warning_freq = 0; 01941 config->warning_sound = NULL; 01942 config->end_sound = NULL; 01943 config->start_sound = NULL; 01944 config->firstpass = 0; 01945 } 01946 config->start_time = ast_tvnow(); 01947 config->feature_timer = featuredigittimeout; 01948 if (option_debug) 01949 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01950 } 01951 } 01952 if (f) 01953 ast_frfree(f); 01954 01955 } 01956 before_you_go: 01957 01958 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) { 01959 ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */ 01960 if (bridge_cdr) { 01961 ast_cdr_discard(bridge_cdr); 01962 /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */ 01963 } 01964 return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */ 01965 } 01966 01967 if (config->end_bridge_callback) { 01968 config->end_bridge_callback(config->end_bridge_callback_data); 01969 } 01970 01971 if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && 01972 ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) { 01973 struct ast_cdr *swapper = NULL; 01974 char savelastapp[AST_MAX_EXTENSION]; 01975 char savelastdata[AST_MAX_EXTENSION]; 01976 char save_exten[AST_MAX_EXTENSION]; 01977 int save_prio; 01978 01979 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); 01980 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); 01981 if (bridge_cdr && ast_opt_end_cdr_before_h_exten) { 01982 ast_cdr_end(bridge_cdr); 01983 } 01984 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge 01985 dialplan code operate on it */ 01986 ast_channel_lock(chan); 01987 if (bridge_cdr) { 01988 swapper = chan->cdr; 01989 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp)); 01990 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata)); 01991 chan->cdr = bridge_cdr; 01992 } 01993 ast_copy_string(save_exten, chan->exten, sizeof(save_exten)); 01994 ast_copy_string(chan->exten, "h", sizeof(chan->exten)); 01995 save_prio = chan->priority; 01996 chan->priority = 1; 01997 ast_channel_unlock(chan); 01998 while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 01999 if (ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 02000 /* Something bad happened, or a hangup has been requested. */ 02001 if (option_debug) 02002 ast_log(LOG_DEBUG, "Spawn h extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 02003 if (option_verbose > 1) 02004 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); 02005 break; 02006 } 02007 chan->priority++; 02008 } 02009 /* swap it back */ 02010 ast_channel_lock(chan); 02011 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten)); 02012 chan->priority = save_prio; 02013 if (bridge_cdr) { 02014 if (chan->cdr == bridge_cdr) { 02015 chan->cdr = swapper; 02016 } else { 02017 bridge_cdr = NULL; 02018 } 02019 } 02020 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN); 02021 ast_channel_unlock(chan); 02022 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */ 02023 if (bridge_cdr) { 02024 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp)); 02025 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata)); 02026 } 02027 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02028 } 02029 02030 /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */ 02031 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 02032 if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) { 02033 ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED); 02034 } 02035 02036 /* we can post the bridge CDR at this point */ 02037 if (bridge_cdr) { 02038 ast_cdr_end(bridge_cdr); 02039 ast_cdr_detach(bridge_cdr); 02040 } 02041 02042 /* do a specialized reset on the beginning channel 02043 CDR's, if they still exist, so as not to mess up 02044 issues in future bridges; 02045 02046 Here are the rules of the game: 02047 1. The chan and peer channel pointers will not change 02048 during the life of the bridge. 02049 2. But, in transfers, the channel names will change. 02050 between the time the bridge is started, and the 02051 time the channel ends. 02052 Usually, when a channel changes names, it will 02053 also change CDR pointers. 02054 3. Usually, only one of the two channels (chan or peer) 02055 will change names. 02056 4. Usually, if a channel changes names during a bridge, 02057 it is because of a transfer. Usually, in these situations, 02058 it is normal to see 2 bridges running simultaneously, and 02059 it is not unusual to see the two channels that change 02060 swapped between bridges. 02061 5. After a bridge occurs, we have 2 or 3 channels' CDRs 02062 to attend to; if the chan or peer changed names, 02063 we have the before and after attached CDR's. 02064 */ 02065 02066 if (new_chan_cdr) { 02067 struct ast_channel *chan_ptr = NULL; 02068 02069 if (strcasecmp(orig_channame, chan->name) != 0) { 02070 /* old channel */ 02071 chan_ptr = ast_get_channel_by_name_locked(orig_channame); 02072 if (chan_ptr) { 02073 if (!ast_bridged_channel(chan_ptr)) { 02074 struct ast_cdr *cur; 02075 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02076 if (cur == chan_cdr) { 02077 break; 02078 } 02079 } 02080 if (cur) 02081 ast_cdr_specialized_reset(chan_cdr,0); 02082 } 02083 ast_channel_unlock(chan_ptr); 02084 } 02085 /* new channel */ 02086 ast_cdr_specialized_reset(new_chan_cdr,0); 02087 } else { 02088 ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */ 02089 } 02090 } 02091 02092 { 02093 struct ast_channel *chan_ptr = NULL; 02094 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 02095 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)) 02096 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */ 02097 if (strcasecmp(orig_peername, peer->name) != 0) { 02098 /* old channel */ 02099 chan_ptr = ast_get_channel_by_name_locked(orig_peername); 02100 if (chan_ptr) { 02101 if (!ast_bridged_channel(chan_ptr)) { 02102 struct ast_cdr *cur; 02103 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02104 if (cur == peer_cdr) { 02105 break; 02106 } 02107 } 02108 if (cur) 02109 ast_cdr_specialized_reset(peer_cdr,0); 02110 } 02111 ast_channel_unlock(chan_ptr); 02112 } 02113 /* new channel */ 02114 ast_cdr_specialized_reset(new_peer_cdr,0); 02115 } else { 02116 ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */ 02117 } 02118 } 02119 02120 return res; 02121 }
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 607 of file res_features.c.
References masq_park_call().
Referenced by handle_exec(), manager_park(), mgcp_ss(), parkandannounce_exec(), and ss_thread().
00608 { 00609 return masq_park_call(rchan, peer, timeout, extout, 0, NULL); 00610 }
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 552 of file res_features.c.
References park_call_full().
Referenced by iax_park_thread(), and sip_park_thread().
00553 { 00554 return park_call_full(chan, peer, timeout, extout, NULL, NULL); 00555 }
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 207 of file res_features.c.
Referenced by builtin_blindtransfer(), do_atxfer(), dp_lookup(), handle_request_refer(), mgcp_ss(), socket_process(), and ss_thread().
00208 { 00209 return parking_ext; 00210 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 2780 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().
02781 { 02782 struct ast_channel *cur = NULL; 02783 int res = -1; 02784 02785 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 02786 if (!cur->pbx && 02787 (cur != chan) && 02788 (chan->pickupgroup & cur->callgroup) && 02789 ((cur->_state == AST_STATE_RINGING) || 02790 (cur->_state == AST_STATE_RING))) { 02791 break; 02792 } 02793 ast_channel_unlock(cur); 02794 } 02795 if (cur) { 02796 if (option_debug) 02797 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 02798 res = ast_answer(chan); 02799 if (res) 02800 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 02801 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 02802 if (res) 02803 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 02804 res = ast_channel_masquerade(cur, chan); 02805 if (res) 02806 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 02807 ast_channel_unlock(cur); 02808 } else { 02809 if (option_debug) 02810 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 02811 } 02812 return res; 02813 }
char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 212 of file res_features.c.
Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().
00213 { 00214 return pickup_ext; 00215 }
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 1125 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.
01126 { 01127 if (!feature) { 01128 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 01129 return; 01130 } 01131 01132 AST_RWLIST_WRLOCK(&feature_list); 01133 AST_RWLIST_INSERT_HEAD(&feature_list, feature, feature_entry); 01134 AST_RWLIST_UNLOCK(&feature_list); 01135 01136 if (option_verbose >= 2) { 01137 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 01138 } 01139 }
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 1142 of file res_features.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_call_feature::feature_entry, and free.
01143 { 01144 if (!feature) 01145 return; 01146 01147 AST_RWLIST_WRLOCK(&feature_list); 01148 AST_RWLIST_REMOVE(&feature_list, feature, feature_entry); 01149 AST_RWLIST_UNLOCK(&feature_list); 01150 01151 free(feature); 01152 }