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