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