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