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