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