#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_atxfer(), builtin_automonitor(), builtin_blindtransfer(), feature_exec_app(), and feature_interpret_helper().
#define FEATURE_RETURN_SUCCESSBREAK 0 |
#define FEATURE_SENSE_CHAN (1 << 0) |
Definition at line 48 of file features.h.
Referenced by ast_bridge_call(), feature_exec_app(), and feature_interpret().
#define FEATURE_SENSE_PEER (1 << 1) |
#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 2131 of file res_features.c.
References ast_channel::_state, ast_channel::accountcode, ast_cdr::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_DIALED, AST_CDR_FLAG_MAIN, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NOANSWER, ast_cdr_setaccount(), 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_start_silence_generator(), ast_channel_stop_silence_generator(), ast_channel_unlock, ast_check_hangup(), ast_clear_flag, 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_opt_transmit_silence, AST_OPTION_AUDIO_MODE, AST_OPTION_FLAG_REQUEST, AST_OPTION_RELAXDTMF, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, 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_write(), ast_channel::cdr, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_num, clear_dialed_interfaces(), 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_check(), 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(), builtin_atxfer(), and park_exec().
02132 { 02133 /* Copy voice back and forth between the two channels. Give the peer 02134 the ability to transfer calls with '#<extension' syntax. */ 02135 struct ast_frame *f; 02136 struct ast_channel *who; 02137 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 02138 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 02139 char orig_channame[AST_MAX_EXTENSION]; 02140 char orig_peername[AST_MAX_EXTENSION]; 02141 02142 int res; 02143 int diff; 02144 int hasfeatures=0; 02145 int hadfeatures=0; 02146 int autoloopflag; 02147 int sendingdtmfdigit = 0; 02148 struct ast_option_header *aoh; 02149 struct ast_bridge_config backup_config; 02150 struct ast_cdr *bridge_cdr = NULL; 02151 struct ast_cdr *orig_peer_cdr = NULL; 02152 struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */ 02153 struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */ 02154 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 02155 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 02156 struct ast_silence_generator *silgen = NULL; 02157 02158 memset(&backup_config, 0, sizeof(backup_config)); 02159 02160 config->start_time = ast_tvnow(); 02161 02162 if (chan && peer) { 02163 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 02164 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 02165 } else if (chan) { 02166 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 02167 } 02168 02169 set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES")); 02170 add_features_datastores(chan, peer, config); 02171 02172 /* This is an interesting case. One example is if a ringing channel gets redirected to 02173 * an extension that picks up a parked call. This will make sure that the call taken 02174 * out of parking gets told that the channel it just got bridged to is still ringing. */ 02175 if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) { 02176 ast_indicate(peer, AST_CONTROL_RINGING); 02177 } 02178 02179 if (monitor_ok) { 02180 const char *monitor_exec; 02181 struct ast_channel *src = NULL; 02182 if (!monitor_app) { 02183 if (!(monitor_app = pbx_findapp("Monitor"))) 02184 monitor_ok=0; 02185 } 02186 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 02187 src = chan; 02188 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 02189 src = peer; 02190 if (monitor_app && src) { 02191 char *tmp = ast_strdupa(monitor_exec); 02192 pbx_exec(src, monitor_app, tmp); 02193 } 02194 } 02195 02196 set_config_flags(chan, peer, config); 02197 config->firstpass = 1; 02198 02199 /* Answer if need be */ 02200 if (ast_answer(chan)) 02201 return -1; 02202 02203 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame)); 02204 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername)); 02205 orig_peer_cdr = peer_cdr; 02206 02207 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) { 02208 02209 if (chan_cdr) { 02210 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); 02211 ast_cdr_update(chan); 02212 bridge_cdr = ast_cdr_dup(chan_cdr); 02213 /* rip any forked CDR's off of the chan_cdr and attach 02214 * them to the bridge_cdr instead */ 02215 bridge_cdr->next = chan_cdr->next; 02216 chan_cdr->next = NULL; 02217 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 02218 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 02219 if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) { 02220 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 02221 } 02222 ast_cdr_setaccount(peer, chan->accountcode); 02223 } else { 02224 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */ 02225 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */ 02226 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel)); 02227 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel)); 02228 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid)); 02229 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 02230 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 02231 ast_cdr_setcid(bridge_cdr, chan); 02232 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 02233 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags; 02234 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode)); 02235 /* Destination information */ 02236 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst)); 02237 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext)); 02238 if (peer_cdr) { 02239 bridge_cdr->start = peer_cdr->start; 02240 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 02241 } else { 02242 ast_cdr_start(bridge_cdr); 02243 } 02244 } 02245 /* peer_cdr->answer will be set when a macro runs on the peer; 02246 in that case, the bridge answer will be delayed while the 02247 macro plays on the peer channel. The peer answered the call 02248 before the macro started playing. To the phone system, 02249 this is billable time for the call, even tho the caller 02250 hears nothing but ringing while the macro does its thing. */ 02251 02252 /* Another case where the peer cdr's time will be set, is when 02253 A self-parks by pickup up phone and dialing 700, then B 02254 picks up A by dialing its parking slot; there may be more 02255 practical paths that get the same result, tho... in which 02256 case you get the previous answer time from the Park... which 02257 is before the bridge's start time, so I added in the 02258 tvcmp check to the if below */ 02259 02260 if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) { 02261 ast_cdr_setanswer(bridge_cdr, peer_cdr->answer); 02262 ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition); 02263 if (chan_cdr) { 02264 ast_cdr_setanswer(chan_cdr, peer_cdr->answer); 02265 ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition); 02266 } 02267 } else { 02268 ast_cdr_answer(bridge_cdr); 02269 if (chan_cdr) { 02270 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */ 02271 } 02272 } 02273 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) { 02274 if (chan_cdr) { 02275 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED); 02276 } 02277 if (peer_cdr) { 02278 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED); 02279 } 02280 } 02281 /* the DIALED flag may be set if a dialed channel is transfered 02282 * and then bridged to another channel. In order for the 02283 * bridge CDR to be written, the DIALED flag must not be 02284 * present. */ 02285 ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED); 02286 } 02287 02288 /* If we are bridging a call, stop worrying about forwarding loops. We presume that if 02289 * a call is being bridged, that the humans in charge know what they're doing. If they 02290 * don't, well, what can we do about that? */ 02291 clear_dialed_interfaces(chan); 02292 clear_dialed_interfaces(peer); 02293 02294 for (;;) { 02295 struct ast_channel *other; /* used later */ 02296 02297 res = ast_channel_bridge(chan, peer, config, &f, &who); 02298 02299 /* When frame is not set, we are probably involved in a situation 02300 where we've timed out. 02301 When frame is set, we'll come thru this code twice; once for DTMF_BEGIN 02302 and also for DTMF_END. If we flow into the following 'if' for both, then 02303 our wait times are cut in half, as both will subtract from the 02304 feature_timer. Not good! 02305 */ 02306 if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) { 02307 /* Update time limit for next pass */ 02308 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 02309 if (res == AST_BRIDGE_RETRY) { 02310 /* The feature fully timed out but has not been updated. Skip 02311 * the potential round error from the diff calculation and 02312 * explicitly set to expired. */ 02313 config->feature_timer = -1; 02314 } else { 02315 config->feature_timer -= diff; 02316 } 02317 02318 if (hasfeatures) { 02319 /* Running on backup config, meaning a feature might be being 02320 activated, but that's no excuse to keep things going 02321 indefinitely! */ 02322 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 02323 if (option_debug) 02324 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 02325 config->feature_timer = 0; 02326 who = chan; 02327 if (f) 02328 ast_frfree(f); 02329 f = NULL; 02330 res = 0; 02331 } else if (config->feature_timer <= 0) { 02332 /* Not *really* out of time, just out of time for 02333 digits to come in for features. */ 02334 if (option_debug) 02335 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 02336 if (!ast_strlen_zero(peer_featurecode)) { 02337 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 02338 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 02339 } 02340 if (!ast_strlen_zero(chan_featurecode)) { 02341 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 02342 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 02343 } 02344 if (f) 02345 ast_frfree(f); 02346 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 02347 if (!hasfeatures) { 02348 /* Restore original (possibly time modified) bridge config */ 02349 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 02350 memset(&backup_config, 0, sizeof(backup_config)); 02351 } 02352 hadfeatures = hasfeatures; 02353 /* Continue as we were */ 02354 continue; 02355 } else if (!f) { 02356 /* The bridge returned without a frame and there is a feature in progress. 02357 * However, we don't think the feature has quite yet timed out, so just 02358 * go back into the bridge. */ 02359 continue; 02360 } 02361 } else { 02362 if (config->feature_timer <=0) { 02363 /* We ran out of time */ 02364 config->feature_timer = 0; 02365 who = chan; 02366 if (f) 02367 ast_frfree(f); 02368 f = NULL; 02369 res = 0; 02370 } 02371 } 02372 } 02373 if (res < 0) { 02374 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) 02375 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 02376 goto before_you_go; 02377 } 02378 02379 if (!f || (f->frametype == AST_FRAME_CONTROL && 02380 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 02381 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 02382 res = -1; 02383 break; 02384 } 02385 /* many things should be sent to the 'other' channel */ 02386 other = (who == chan) ? peer : chan; 02387 if (f->frametype == AST_FRAME_CONTROL) { 02388 switch (f->subclass) { 02389 case AST_CONTROL_RINGING: 02390 case AST_CONTROL_FLASH: 02391 case -1: 02392 ast_indicate(other, f->subclass); 02393 break; 02394 case AST_CONTROL_HOLD: 02395 case AST_CONTROL_UNHOLD: 02396 ast_indicate_data(other, f->subclass, f->data, f->datalen); 02397 break; 02398 case AST_CONTROL_OPTION: 02399 aoh = f->data; 02400 /* Forward option Requests, but only ones we know are safe 02401 * These are ONLY sent by chan_iax2 and I'm not convinced that 02402 * they are useful. I haven't deleted them entirely because I 02403 * just am not sure of the ramifications of removing them. */ 02404 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 02405 switch (ntohs(aoh->option)) { 02406 case AST_OPTION_TONE_VERIFY: 02407 case AST_OPTION_TDD: 02408 case AST_OPTION_RELAXDTMF: 02409 case AST_OPTION_AUDIO_MODE: 02410 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 02411 f->datalen - sizeof(struct ast_option_header), 0); 02412 } 02413 } 02414 break; 02415 } 02416 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 02417 struct ast_flags *cfg; 02418 char dtmfcode[2] = { f->subclass, }; 02419 size_t featurelen; 02420 02421 if (who == chan) { 02422 featurelen = strlen(chan_featurecode); 02423 cfg = &(config->features_caller); 02424 } else { 02425 featurelen = strlen(peer_featurecode); 02426 cfg = &(config->features_callee); 02427 } 02428 /* Take a peek if this (possibly) matches a feature. If not, just pass this 02429 * DTMF along untouched. If this is not the first digit of a multi-digit code 02430 * then we need to fall through and stream the characters if it matches */ 02431 if (featurelen == 0 02432 && feature_check(chan, cfg, &dtmfcode[0]) == FEATURE_RETURN_PASSDIGITS) { 02433 if (option_debug > 3) { 02434 ast_log(LOG_DEBUG, "Passing DTMF through, since it is not a feature code\n"); 02435 } 02436 ast_write(other, f); 02437 sendingdtmfdigit = 1; 02438 } else { 02439 /* If ast_opt_transmit_silence is set, then we need to make sure we are 02440 * transmitting something while we hold on to the DTMF waiting for a 02441 * feature. */ 02442 if (!silgen && ast_opt_transmit_silence) { 02443 silgen = ast_channel_start_silence_generator(other); 02444 } 02445 if (option_debug > 3) { 02446 ast_log(LOG_DEBUG, "Not passing DTMF through, since it may be a feature code\n"); 02447 } 02448 } 02449 } else if (f->frametype == AST_FRAME_DTMF) { 02450 char *featurecode; 02451 int sense; 02452 02453 hadfeatures = hasfeatures; 02454 /* This cannot overrun because the longest feature is one shorter than our buffer */ 02455 if (who == chan) { 02456 sense = FEATURE_SENSE_CHAN; 02457 featurecode = chan_featurecode; 02458 } else { 02459 sense = FEATURE_SENSE_PEER; 02460 featurecode = peer_featurecode; 02461 } 02462 02463 if (sendingdtmfdigit == 1) { 02464 /* We let the BEGIN go through happily, so let's not bother with the END, 02465 * since we already know it's not something we bother with */ 02466 ast_write(other, f); 02467 sendingdtmfdigit = 0; 02468 } else { 02469 /*! append the event to featurecode. we rely on the string being zero-filled, and 02470 * not overflowing it. 02471 * \todo XXX how do we guarantee the latter ? 02472 */ 02473 featurecode[strlen(featurecode)] = f->subclass; 02474 /* Get rid of the frame before we start doing "stuff" with the channels */ 02475 ast_frfree(f); 02476 f = NULL; 02477 if (silgen) { 02478 ast_channel_stop_silence_generator(other, silgen); 02479 silgen = NULL; 02480 } 02481 config->feature_timer = backup_config.feature_timer; 02482 res = feature_interpret(chan, peer, config, featurecode, sense); 02483 switch(res) { 02484 case FEATURE_RETURN_PASSDIGITS: 02485 ast_dtmf_stream(other, who, featurecode, 0); 02486 /* Fall through */ 02487 case FEATURE_RETURN_SUCCESS: 02488 memset(featurecode, 0, sizeof(chan_featurecode)); 02489 break; 02490 } 02491 if (res >= FEATURE_RETURN_PASSDIGITS) { 02492 res = 0; 02493 } else { 02494 break; 02495 } 02496 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 02497 if (hadfeatures && !hasfeatures) { 02498 /* Restore backup */ 02499 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 02500 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 02501 } else if (hasfeatures) { 02502 if (!hadfeatures) { 02503 /* Backup configuration */ 02504 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 02505 /* Setup temporary config options */ 02506 config->play_warning = 0; 02507 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 02508 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 02509 config->warning_freq = 0; 02510 config->warning_sound = NULL; 02511 config->end_sound = NULL; 02512 config->start_sound = NULL; 02513 config->firstpass = 0; 02514 } 02515 config->start_time = ast_tvnow(); 02516 config->feature_timer = featuredigittimeout; 02517 if (option_debug) { 02518 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 02519 } 02520 } 02521 } 02522 } 02523 if (f) 02524 ast_frfree(f); 02525 02526 } 02527 02528 before_you_go: 02529 /* Just in case something weird happened and we didn't clean up the silence generator... */ 02530 if (silgen) { 02531 ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen); 02532 silgen = NULL; 02533 } 02534 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) { 02535 ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */ 02536 if (bridge_cdr) { 02537 ast_cdr_discard(bridge_cdr); 02538 /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */ 02539 } 02540 return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */ 02541 } 02542 02543 if (config->end_bridge_callback) { 02544 config->end_bridge_callback(config->end_bridge_callback_data); 02545 } 02546 02547 if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && 02548 ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) { 02549 struct ast_cdr *swapper = NULL; 02550 char savelastapp[AST_MAX_EXTENSION]; 02551 char savelastdata[AST_MAX_EXTENSION]; 02552 char save_exten[AST_MAX_EXTENSION]; 02553 int save_prio, spawn_error = 0; 02554 02555 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); 02556 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); 02557 if (bridge_cdr && ast_opt_end_cdr_before_h_exten) { 02558 ast_cdr_end(bridge_cdr); 02559 } 02560 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge 02561 dialplan code operate on it */ 02562 ast_channel_lock(chan); 02563 if (bridge_cdr) { 02564 swapper = chan->cdr; 02565 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp)); 02566 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata)); 02567 chan->cdr = bridge_cdr; 02568 } 02569 ast_copy_string(save_exten, chan->exten, sizeof(save_exten)); 02570 ast_copy_string(chan->exten, "h", sizeof(chan->exten)); 02571 save_prio = chan->priority; 02572 chan->priority = 1; 02573 ast_channel_unlock(chan); 02574 while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 02575 if ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) { 02576 /* Something bad happened, or a hangup has been requested. */ 02577 if (option_debug) 02578 ast_log(LOG_DEBUG, "Spawn h extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 02579 if (option_verbose > 1) 02580 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); 02581 break; 02582 } 02583 chan->priority++; 02584 } 02585 /* swap it back */ 02586 ast_channel_lock(chan); 02587 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten)); 02588 chan->priority = save_prio; 02589 if (bridge_cdr) { 02590 if (chan->cdr == bridge_cdr) { 02591 chan->cdr = swapper; 02592 } else { 02593 bridge_cdr = NULL; 02594 } 02595 } 02596 if (chan->priority != 1 || !spawn_error) { 02597 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN); 02598 } 02599 ast_channel_unlock(chan); 02600 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */ 02601 if (bridge_cdr) { 02602 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp)); 02603 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata)); 02604 } 02605 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02606 } 02607 02608 /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */ 02609 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 02610 if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) { 02611 ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED); 02612 } 02613 02614 /* we can post the bridge CDR at this point */ 02615 if (bridge_cdr) { 02616 ast_cdr_end(bridge_cdr); 02617 ast_cdr_detach(bridge_cdr); 02618 } 02619 02620 /* do a specialized reset on the beginning channel 02621 CDR's, if they still exist, so as not to mess up 02622 issues in future bridges; 02623 02624 Here are the rules of the game: 02625 1. The chan and peer channel pointers will not change 02626 during the life of the bridge. 02627 2. But, in transfers, the channel names will change. 02628 between the time the bridge is started, and the 02629 time the channel ends. 02630 Usually, when a channel changes names, it will 02631 also change CDR pointers. 02632 3. Usually, only one of the two channels (chan or peer) 02633 will change names. 02634 4. Usually, if a channel changes names during a bridge, 02635 it is because of a transfer. Usually, in these situations, 02636 it is normal to see 2 bridges running simultaneously, and 02637 it is not unusual to see the two channels that change 02638 swapped between bridges. 02639 5. After a bridge occurs, we have 2 or 3 channels' CDRs 02640 to attend to; if the chan or peer changed names, 02641 we have the before and after attached CDR's. 02642 */ 02643 02644 if (new_chan_cdr) { 02645 struct ast_channel *chan_ptr = NULL; 02646 02647 if (strcasecmp(orig_channame, chan->name) != 0) { 02648 /* old channel */ 02649 chan_ptr = ast_get_channel_by_name_locked(orig_channame); 02650 if (chan_ptr) { 02651 if (!ast_bridged_channel(chan_ptr)) { 02652 struct ast_cdr *cur; 02653 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02654 if (cur == chan_cdr) { 02655 break; 02656 } 02657 } 02658 if (cur) 02659 ast_cdr_specialized_reset(chan_cdr,0); 02660 } 02661 ast_channel_unlock(chan_ptr); 02662 } 02663 /* new channel */ 02664 ast_cdr_specialized_reset(new_chan_cdr,0); 02665 } else { 02666 ast_cdr_specialized_reset(chan->cdr, 0); /* nothing changed, reset the chan cdr */ 02667 } 02668 } 02669 02670 { 02671 struct ast_channel *chan_ptr = NULL; 02672 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 02673 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)) 02674 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */ 02675 if (strcasecmp(orig_peername, peer->name) != 0) { 02676 /* old channel */ 02677 chan_ptr = ast_get_channel_by_name_locked(orig_peername); 02678 if (chan_ptr) { 02679 if (!ast_bridged_channel(chan_ptr)) { 02680 struct ast_cdr *cur; 02681 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02682 if (cur == peer_cdr) { 02683 break; 02684 } 02685 } 02686 if (cur) 02687 ast_cdr_specialized_reset(peer_cdr,0); 02688 } 02689 ast_channel_unlock(chan_ptr); 02690 } 02691 /* new channel */ 02692 if (new_peer_cdr) { 02693 ast_cdr_specialized_reset(new_peer_cdr, 0); 02694 } 02695 } else { 02696 ast_cdr_specialized_reset(peer->cdr, 0); /* nothing changed, reset the peer cdr */ 02697 } 02698 } 02699 02700 return res; 02701 }
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 1665 of file res_features.c.
References FEATURE_INTERPRET_DETECT, and feature_interpret_helper().
Referenced by detect_disconnect().
01665 { 01666 01667 return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature); 01668 }
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 792 of file res_features.c.
References masq_park_call().
Referenced by handle_exec(), manager_park(), mgcp_ss(), parkandannounce_exec(), and ss_thread().
00793 { 00794 return masq_park_call(rchan, peer, timeout, extout, 0, NULL); 00795 }
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 731 of file res_features.c.
References park_call_full().
Referenced by iax_park_thread(), and sip_park_thread().
00732 { 00733 return park_call_full(chan, peer, timeout, extout, NULL, NULL); 00734 }
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 380 of file res_features.c.
Referenced by builtin_atxfer(), builtin_blindtransfer(), dp_lookup(), handle_request_refer(), mgcp_ss(), socket_process(), and ss_thread().
00381 { 00382 return parking_ext; 00383 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 3449 of file res_features.c.
References ast_channel::_state, ast_channel_unlock, ast_channel_walk_locked(), AST_FLAG_ZOMBIE, ast_log(), AST_STATE_RING, AST_STATE_RINGING, ast_test_flag, ast_channel::callgroup, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::name, option_debug, ast_channel::pbx, pickup_do(), and ast_channel::pickupgroup.
Referenced by cb_events(), handle_request_invite(), mgcp_ss(), and ss_thread().
03450 { 03451 struct ast_channel *cur = NULL; 03452 int res = -1; 03453 03454 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 03455 if (!cur->pbx && 03456 (cur != chan) && 03457 (chan->pickupgroup & cur->callgroup) && 03458 ((cur->_state == AST_STATE_RINGING) || 03459 (cur->_state == AST_STATE_RING)) && 03460 !cur->masq && 03461 !ast_test_flag(cur, AST_FLAG_ZOMBIE)) { 03462 break; 03463 } 03464 ast_channel_unlock(cur); 03465 } 03466 if (cur) { 03467 res = pickup_do(chan, cur); 03468 if (res) { 03469 ast_log(LOG_WARNING, "pickup %s failed by %s\n", cur->name, chan->name); 03470 } 03471 ast_channel_unlock(cur); 03472 } else { 03473 if (option_debug) 03474 ast_log(LOG_DEBUG, "No call pickup possible... for %s\n", chan->name); 03475 } 03476 return res; 03477 }
char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 385 of file res_features.c.
Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().
00386 { 00387 return pickup_ext; 00388 }
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 1391 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.
01392 { 01393 if (!feature) { 01394 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 01395 return; 01396 } 01397 01398 AST_RWLIST_WRLOCK(&feature_list); 01399 AST_RWLIST_INSERT_HEAD(&feature_list, feature, feature_entry); 01400 AST_RWLIST_UNLOCK(&feature_list); 01401 01402 if (option_verbose >= 2) { 01403 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 01404 } 01405 }
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 1408 of file res_features.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_call_feature::feature_entry, and free.
01409 { 01410 if (!feature) 01411 return; 01412 01413 AST_RWLIST_WRLOCK(&feature_list); 01414 AST_RWLIST_REMOVE(&feature_list, feature, feature_entry); 01415 AST_RWLIST_UNLOCK(&feature_list); 01416 01417 free(feature); 01418 }