#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_RETURN_HANGUP -1 |
#define | FEATURE_RETURN_KEEPTRYING 24 |
#define | FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER |
#define | FEATURE_RETURN_PARKFAILED 25 |
#define | FEATURE_RETURN_PASSDIGITS 21 |
#define | FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE |
#define | FEATURE_RETURN_STOREDIGITS 22 |
#define | FEATURE_RETURN_SUCCESS 23 |
#define | FEATURE_RETURN_SUCCESSBREAK 0 |
#define | FEATURE_SENSE_CHAN (1 << 0) |
#define | FEATURE_SENSE_PEER (1 << 1) |
#define | FEATURE_SNAME_LEN 32 |
#define | PARK_APP_NAME "Park" |
Typedefs | |
typedef int(*) | ast_feature_operation (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data) |
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_feature_detect (struct ast_channel *chan, struct ast_flags *features, char *code, struct ast_call_feature *feature) |
detect a feature before bridging | |
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_RETURN_HANGUP -1 |
#define FEATURE_RETURN_KEEPTRYING 24 |
Definition at line 45 of file features.h.
Referenced by feature_exec_app(), and feature_interpret_helper().
#define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER |
Definition at line 41 of file features.h.
#define FEATURE_RETURN_PARKFAILED 25 |
Definition at line 46 of file features.h.
Referenced by builtin_blindtransfer(), and masq_park_call().
#define FEATURE_RETURN_PASSDIGITS 21 |
Definition at line 42 of file features.h.
Referenced by ast_bridge_call(), and feature_interpret_helper().
#define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE |
Definition at line 40 of file features.h.
#define FEATURE_RETURN_STOREDIGITS 22 |
Definition at line 43 of file features.h.
Referenced by detect_disconnect(), and feature_interpret_helper().
#define FEATURE_RETURN_SUCCESS 23 |
Definition at line 44 of file features.h.
Referenced by ast_bridge_call(), builtin_automonitor(), builtin_blindtransfer(), do_atxfer(), and feature_exec_app().
#define FEATURE_RETURN_SUCCESSBREAK 0 |
#define FEATURE_SENSE_CHAN (1 << 0) |
Definition at line 48 of file features.h.
Referenced by ast_bridge_call(), cmd_atxfer(), feature_exec_app(), and feature_interpret().
#define FEATURE_SENSE_PEER (1 << 1) |
Definition at line 49 of file features.h.
Referenced by ast_bridge_call(), cmd_atxfer(), and set_peers().
#define FEATURE_SNAME_LEN 32 |
Definition at line 32 of file features.h.
#define PARK_APP_NAME "Park" |
typedef int(*) ast_feature_operation(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data) |
Definition at line 51 of file features.h.
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 1744 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_NOANSWER, ast_cdr_setanswer(), ast_cdr_setcid(), ast_cdr_setdisposition(), 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_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_tvcmp(), 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_interpret(), 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, S_OR, 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(), and park_exec().
01745 { 01746 /* Copy voice back and forth between the two channels. Give the peer 01747 the ability to transfer calls with '#<extension' syntax. */ 01748 struct ast_frame *f; 01749 struct ast_channel *who; 01750 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 01751 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 01752 char orig_channame[AST_MAX_EXTENSION]; 01753 char orig_peername[AST_MAX_EXTENSION]; 01754 01755 int res; 01756 int diff; 01757 int hasfeatures=0; 01758 int hadfeatures=0; 01759 int autoloopflag; 01760 struct ast_option_header *aoh; 01761 struct ast_bridge_config backup_config; 01762 struct ast_cdr *bridge_cdr = NULL; 01763 struct ast_cdr *orig_peer_cdr = NULL; 01764 struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */ 01765 struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */ 01766 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 01767 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 01768 01769 memset(&backup_config, 0, sizeof(backup_config)); 01770 01771 config->start_time = ast_tvnow(); 01772 01773 if (chan && peer) { 01774 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01775 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01776 } else if (chan) { 01777 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01778 } 01779 01780 set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES")); 01781 add_features_datastores(chan, peer, config); 01782 01783 /* This is an interesting case. One example is if a ringing channel gets redirected to 01784 * an extension that picks up a parked call. This will make sure that the call taken 01785 * out of parking gets told that the channel it just got bridged to is still ringing. */ 01786 if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) { 01787 ast_indicate(peer, AST_CONTROL_RINGING); 01788 } 01789 01790 if (monitor_ok) { 01791 const char *monitor_exec; 01792 struct ast_channel *src = NULL; 01793 if (!monitor_app) { 01794 if (!(monitor_app = pbx_findapp("Monitor"))) 01795 monitor_ok=0; 01796 } 01797 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01798 src = chan; 01799 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01800 src = peer; 01801 if (monitor_app && src) { 01802 char *tmp = ast_strdupa(monitor_exec); 01803 pbx_exec(src, monitor_app, tmp); 01804 } 01805 } 01806 01807 set_config_flags(chan, peer, config); 01808 config->firstpass = 1; 01809 01810 /* Answer if need be */ 01811 if (ast_answer(chan)) 01812 return -1; 01813 01814 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame)); 01815 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername)); 01816 orig_peer_cdr = peer_cdr; 01817 01818 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) { 01819 01820 if (chan_cdr) { 01821 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); 01822 ast_cdr_update(chan); 01823 bridge_cdr = ast_cdr_dup(chan_cdr); 01824 /* rip any forked CDR's off of the chan_cdr and attach 01825 * them to the bridge_cdr instead */ 01826 bridge_cdr->next = chan_cdr->next; 01827 chan_cdr->next = NULL; 01828 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 01829 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 01830 if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) { 01831 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 01832 } 01833 } else { 01834 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */ 01835 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */ 01836 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel)); 01837 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel)); 01838 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid)); 01839 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 01840 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 01841 ast_cdr_setcid(bridge_cdr, chan); 01842 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 01843 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags; 01844 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode)); 01845 /* Destination information */ 01846 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst)); 01847 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext)); 01848 if (peer_cdr) { 01849 bridge_cdr->start = peer_cdr->start; 01850 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 01851 } else { 01852 ast_cdr_start(bridge_cdr); 01853 } 01854 } 01855 /* peer_cdr->answer will be set when a macro runs on the peer; 01856 in that case, the bridge answer will be delayed while the 01857 macro plays on the peer channel. The peer answered the call 01858 before the macro started playing. To the phone system, 01859 this is billable time for the call, even tho the caller 01860 hears nothing but ringing while the macro does its thing. */ 01861 01862 /* Another case where the peer cdr's time will be set, is when 01863 A self-parks by pickup up phone and dialing 700, then B 01864 picks up A by dialing its parking slot; there may be more 01865 practical paths that get the same result, tho... in which 01866 case you get the previous answer time from the Park... which 01867 is before the bridge's start time, so I added in the 01868 tvcmp check to the if below */ 01869 01870 if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) { 01871 ast_cdr_setanswer(bridge_cdr, peer_cdr->answer); 01872 ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition); 01873 if (chan_cdr) { 01874 ast_cdr_setanswer(chan_cdr, peer_cdr->answer); 01875 ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition); 01876 } 01877 } else { 01878 ast_cdr_answer(bridge_cdr); 01879 if (chan_cdr) { 01880 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */ 01881 } 01882 } 01883 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) { 01884 if (chan_cdr) { 01885 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED); 01886 } 01887 if (peer_cdr) { 01888 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED); 01889 } 01890 } 01891 } 01892 01893 for (;;) { 01894 struct ast_channel *other; /* used later */ 01895 01896 res = ast_channel_bridge(chan, peer, config, &f, &who); 01897 01898 /* When frame is not set, we are probably involved in a situation 01899 where we've timed out. 01900 When frame is set, we'll come thru this code twice; once for DTMF_BEGIN 01901 and also for DTMF_END. If we flow into the following 'if' for both, then 01902 our wait times are cut in half, as both will subtract from the 01903 feature_timer. Not good! 01904 */ 01905 if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) { 01906 /* Update time limit for next pass */ 01907 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 01908 if (res == AST_BRIDGE_RETRY) { 01909 /* The feature fully timed out but has not been updated. Skip 01910 * the potential round error from the diff calculation and 01911 * explicitly set to expired. */ 01912 config->feature_timer = -1; 01913 } else { 01914 config->feature_timer -= diff; 01915 } 01916 01917 if (hasfeatures) { 01918 /* Running on backup config, meaning a feature might be being 01919 activated, but that's no excuse to keep things going 01920 indefinitely! */ 01921 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01922 if (option_debug) 01923 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01924 config->feature_timer = 0; 01925 who = chan; 01926 if (f) 01927 ast_frfree(f); 01928 f = NULL; 01929 res = 0; 01930 } else if (config->feature_timer <= 0) { 01931 /* Not *really* out of time, just out of time for 01932 digits to come in for features. */ 01933 if (option_debug) 01934 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01935 if (!ast_strlen_zero(peer_featurecode)) { 01936 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01937 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01938 } 01939 if (!ast_strlen_zero(chan_featurecode)) { 01940 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01941 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01942 } 01943 if (f) 01944 ast_frfree(f); 01945 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01946 if (!hasfeatures) { 01947 /* Restore original (possibly time modified) bridge config */ 01948 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01949 memset(&backup_config, 0, sizeof(backup_config)); 01950 } 01951 hadfeatures = hasfeatures; 01952 /* Continue as we were */ 01953 continue; 01954 } else if (!f) { 01955 /* The bridge returned without a frame and there is a feature in progress. 01956 * However, we don't think the feature has quite yet timed out, so just 01957 * go back into the bridge. */ 01958 continue; 01959 } 01960 } else { 01961 if (config->feature_timer <=0) { 01962 /* We ran out of time */ 01963 config->feature_timer = 0; 01964 who = chan; 01965 if (f) 01966 ast_frfree(f); 01967 f = NULL; 01968 res = 0; 01969 } 01970 } 01971 } 01972 if (res < 0) { 01973 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) 01974 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01975 goto before_you_go; 01976 } 01977 01978 if (!f || (f->frametype == AST_FRAME_CONTROL && 01979 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 01980 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 01981 res = -1; 01982 break; 01983 } 01984 /* many things should be sent to the 'other' channel */ 01985 other = (who == chan) ? peer : chan; 01986 if (f->frametype == AST_FRAME_CONTROL) { 01987 switch (f->subclass) { 01988 case AST_CONTROL_RINGING: 01989 case AST_CONTROL_FLASH: 01990 case -1: 01991 ast_indicate(other, f->subclass); 01992 break; 01993 case AST_CONTROL_HOLD: 01994 case AST_CONTROL_UNHOLD: 01995 ast_indicate_data(other, f->subclass, f->data, f->datalen); 01996 break; 01997 case AST_CONTROL_OPTION: 01998 aoh = f->data; 01999 /* Forward option Requests */ 02000 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 02001 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 02002 f->datalen - sizeof(struct ast_option_header), 0); 02003 } 02004 break; 02005 case AST_CONTROL_ATXFERCMD: 02006 cmd_atxfer(chan, peer, config, who, f->data); 02007 break; 02008 } 02009 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 02010 /* eat it */ 02011 } else if (f->frametype == AST_FRAME_DTMF) { 02012 char *featurecode; 02013 int sense; 02014 02015 hadfeatures = hasfeatures; 02016 /* This cannot overrun because the longest feature is one shorter than our buffer */ 02017 if (who == chan) { 02018 sense = FEATURE_SENSE_CHAN; 02019 featurecode = chan_featurecode; 02020 } else { 02021 sense = FEATURE_SENSE_PEER; 02022 featurecode = peer_featurecode; 02023 } 02024 /*! append the event to featurecode. we rely on the string being zero-filled, and 02025 * not overflowing it. 02026 * \todo XXX how do we guarantee the latter ? 02027 */ 02028 featurecode[strlen(featurecode)] = f->subclass; 02029 /* Get rid of the frame before we start doing "stuff" with the channels */ 02030 ast_frfree(f); 02031 f = NULL; 02032 config->feature_timer = backup_config.feature_timer; 02033 res = feature_interpret(chan, peer, config, featurecode, sense); 02034 switch(res) { 02035 case FEATURE_RETURN_PASSDIGITS: 02036 ast_dtmf_stream(other, who, featurecode, 0); 02037 /* Fall through */ 02038 case FEATURE_RETURN_SUCCESS: 02039 memset(featurecode, 0, sizeof(chan_featurecode)); 02040 break; 02041 } 02042 if (res >= FEATURE_RETURN_PASSDIGITS) { 02043 res = 0; 02044 } else 02045 break; 02046 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 02047 if (hadfeatures && !hasfeatures) { 02048 /* Restore backup */ 02049 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 02050 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 02051 } else if (hasfeatures) { 02052 if (!hadfeatures) { 02053 /* Backup configuration */ 02054 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 02055 /* Setup temporary config options */ 02056 config->play_warning = 0; 02057 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 02058 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 02059 config->warning_freq = 0; 02060 config->warning_sound = NULL; 02061 config->end_sound = NULL; 02062 config->start_sound = NULL; 02063 config->firstpass = 0; 02064 } 02065 config->start_time = ast_tvnow(); 02066 config->feature_timer = featuredigittimeout; 02067 if (option_debug) 02068 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 02069 } 02070 } 02071 if (f) 02072 ast_frfree(f); 02073 02074 } 02075 before_you_go: 02076 02077 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) { 02078 ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */ 02079 if (bridge_cdr) { 02080 ast_cdr_discard(bridge_cdr); 02081 /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */ 02082 } 02083 return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */ 02084 } 02085 02086 if (config->end_bridge_callback) { 02087 config->end_bridge_callback(config->end_bridge_callback_data); 02088 } 02089 02090 if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && 02091 ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) { 02092 struct ast_cdr *swapper = NULL; 02093 char savelastapp[AST_MAX_EXTENSION]; 02094 char savelastdata[AST_MAX_EXTENSION]; 02095 char save_exten[AST_MAX_EXTENSION]; 02096 int save_prio, spawn_error = 0; 02097 02098 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); 02099 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); 02100 if (bridge_cdr && ast_opt_end_cdr_before_h_exten) { 02101 ast_cdr_end(bridge_cdr); 02102 } 02103 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge 02104 dialplan code operate on it */ 02105 ast_channel_lock(chan); 02106 if (bridge_cdr) { 02107 swapper = chan->cdr; 02108 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp)); 02109 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata)); 02110 chan->cdr = bridge_cdr; 02111 } 02112 ast_copy_string(save_exten, chan->exten, sizeof(save_exten)); 02113 ast_copy_string(chan->exten, "h", sizeof(chan->exten)); 02114 save_prio = chan->priority; 02115 chan->priority = 1; 02116 ast_channel_unlock(chan); 02117 while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 02118 if ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) { 02119 /* Something bad happened, or a hangup has been requested. */ 02120 if (option_debug) 02121 ast_log(LOG_DEBUG, "Spawn h extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 02122 if (option_verbose > 1) 02123 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); 02124 break; 02125 } 02126 chan->priority++; 02127 } 02128 /* swap it back */ 02129 ast_channel_lock(chan); 02130 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten)); 02131 chan->priority = save_prio; 02132 if (bridge_cdr) { 02133 if (chan->cdr == bridge_cdr) { 02134 chan->cdr = swapper; 02135 } else { 02136 bridge_cdr = NULL; 02137 } 02138 } 02139 if (chan->priority != 1 || !spawn_error) { 02140 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN); 02141 } 02142 ast_channel_unlock(chan); 02143 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */ 02144 if (bridge_cdr) { 02145 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp)); 02146 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata)); 02147 } 02148 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02149 } 02150 02151 /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */ 02152 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 02153 if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) { 02154 ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED); 02155 } 02156 02157 /* we can post the bridge CDR at this point */ 02158 if (bridge_cdr) { 02159 ast_cdr_end(bridge_cdr); 02160 ast_cdr_detach(bridge_cdr); 02161 } 02162 02163 /* do a specialized reset on the beginning channel 02164 CDR's, if they still exist, so as not to mess up 02165 issues in future bridges; 02166 02167 Here are the rules of the game: 02168 1. The chan and peer channel pointers will not change 02169 during the life of the bridge. 02170 2. But, in transfers, the channel names will change. 02171 between the time the bridge is started, and the 02172 time the channel ends. 02173 Usually, when a channel changes names, it will 02174 also change CDR pointers. 02175 3. Usually, only one of the two channels (chan or peer) 02176 will change names. 02177 4. Usually, if a channel changes names during a bridge, 02178 it is because of a transfer. Usually, in these situations, 02179 it is normal to see 2 bridges running simultaneously, and 02180 it is not unusual to see the two channels that change 02181 swapped between bridges. 02182 5. After a bridge occurs, we have 2 or 3 channels' CDRs 02183 to attend to; if the chan or peer changed names, 02184 we have the before and after attached CDR's. 02185 */ 02186 02187 if (new_chan_cdr) { 02188 struct ast_channel *chan_ptr = NULL; 02189 02190 if (strcasecmp(orig_channame, chan->name) != 0) { 02191 /* old channel */ 02192 chan_ptr = ast_get_channel_by_name_locked(orig_channame); 02193 if (chan_ptr) { 02194 if (!ast_bridged_channel(chan_ptr)) { 02195 struct ast_cdr *cur; 02196 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02197 if (cur == chan_cdr) { 02198 break; 02199 } 02200 } 02201 if (cur) 02202 ast_cdr_specialized_reset(chan_cdr,0); 02203 } 02204 ast_channel_unlock(chan_ptr); 02205 } 02206 /* new channel */ 02207 ast_cdr_specialized_reset(new_chan_cdr,0); 02208 } else { 02209 ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */ 02210 } 02211 } 02212 02213 { 02214 struct ast_channel *chan_ptr = NULL; 02215 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 02216 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)) 02217 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */ 02218 if (strcasecmp(orig_peername, peer->name) != 0) { 02219 /* old channel */ 02220 chan_ptr = ast_get_channel_by_name_locked(orig_peername); 02221 if (chan_ptr) { 02222 if (!ast_bridged_channel(chan_ptr)) { 02223 struct ast_cdr *cur; 02224 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02225 if (cur == peer_cdr) { 02226 break; 02227 } 02228 } 02229 if (cur) 02230 ast_cdr_specialized_reset(peer_cdr,0); 02231 } 02232 ast_channel_unlock(chan_ptr); 02233 } 02234 /* new channel */ 02235 ast_cdr_specialized_reset(new_peer_cdr,0); 02236 } else { 02237 ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */ 02238 } 02239 } 02240 02241 return res; 02242 }
int ast_feature_detect | ( | struct ast_channel * | chan, | |
struct ast_flags * | features, | |||
char * | code, | |||
struct ast_call_feature * | feature | |||
) |
detect a feature before bridging
chan | ||
ast_flags | ptr | |
char | ptr of input code |
ast_call_feature | ptr to be set if found |
Definition at line 1419 of file res_features.c.
References feature_interpret_helper().
Referenced by detect_disconnect().
01419 { 01420 01421 return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature); 01422 }
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 608 of file res_features.c.
References masq_park_call().
Referenced by handle_exec(), manager_park(), mgcp_ss(), parkandannounce_exec(), and ss_thread().
00609 { 00610 return masq_park_call(rchan, peer, timeout, extout, 0, NULL); 00611 }
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 2901 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().
02902 { 02903 struct ast_channel *cur = NULL; 02904 int res = -1; 02905 02906 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 02907 if (!cur->pbx && 02908 (cur != chan) && 02909 (chan->pickupgroup & cur->callgroup) && 02910 ((cur->_state == AST_STATE_RINGING) || 02911 (cur->_state == AST_STATE_RING))) { 02912 break; 02913 } 02914 ast_channel_unlock(cur); 02915 } 02916 if (cur) { 02917 if (option_debug) 02918 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 02919 res = ast_answer(chan); 02920 if (res) 02921 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 02922 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 02923 if (res) 02924 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 02925 res = ast_channel_masquerade(cur, chan); 02926 if (res) 02927 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 02928 ast_channel_unlock(cur); 02929 } else { 02930 if (option_debug) 02931 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 02932 } 02933 return res; 02934 }
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 1156 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.
01157 { 01158 if (!feature) { 01159 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 01160 return; 01161 } 01162 01163 AST_RWLIST_WRLOCK(&feature_list); 01164 AST_RWLIST_INSERT_HEAD(&feature_list, feature, feature_entry); 01165 AST_RWLIST_UNLOCK(&feature_list); 01166 01167 if (option_verbose >= 2) { 01168 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 01169 } 01170 }
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 1173 of file res_features.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_call_feature::feature_entry, and free.
01174 { 01175 if (!feature) 01176 return; 01177 01178 AST_RWLIST_WRLOCK(&feature_list); 01179 AST_RWLIST_REMOVE(&feature_list, feature, feature_entry); 01180 AST_RWLIST_UNLOCK(&feature_list); 01181 01182 free(feature); 01183 }