Go to the source code of this file.
Data Structures | |
struct | ast_call_feature |
main call feature structure More... | |
Defines | |
#define | AST_FEATURE_RETURN_HANGUP -1 |
#define | AST_FEATURE_RETURN_KEEPTRYING 24 |
#define | AST_FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER |
#define | AST_FEATURE_RETURN_PARKFAILED 25 |
#define | AST_FEATURE_RETURN_PASSDIGITS 21 |
#define | AST_FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE |
#define | AST_FEATURE_RETURN_STOREDIGITS 22 |
#define | AST_FEATURE_RETURN_SUCCESS 23 |
#define | AST_FEATURE_RETURN_SUCCESSBREAK 0 |
#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_SENSE_CHAN (1 << 0) |
#define | FEATURE_SENSE_PEER (1 << 1) |
#define | FEATURE_SNAME_LEN 32 |
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_features_reload (void) |
Reload call features from features.conf. | |
ast_call_feature * | ast_find_call_feature (const char *name) |
look for a call feature entry by its sname | |
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. | |
const char * | ast_parking_ext (void) |
Determine system parking extension. | |
int | ast_pickup_call (struct ast_channel *chan) |
Pickup a call. | |
const char * | ast_pickup_ext (void) |
Determine system call pickup extension. | |
void | ast_rdlock_call_features (void) |
void | ast_register_feature (struct ast_call_feature *feature) |
register new feature into feature_set | |
void | ast_unlock_call_features (void) |
void | ast_unregister_feature (struct ast_call_feature *feature) |
unregister feature from feature_set |
Definition in file features.h.
#define AST_FEATURE_RETURN_HANGUP -1 |
Definition at line 34 of file features.h.
#define AST_FEATURE_RETURN_KEEPTRYING 24 |
#define AST_FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER |
Definition at line 37 of file features.h.
#define AST_FEATURE_RETURN_PARKFAILED 25 |
Definition at line 42 of file features.h.
#define AST_FEATURE_RETURN_PASSDIGITS 21 |
#define AST_FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE |
Definition at line 36 of file features.h.
#define AST_FEATURE_RETURN_STOREDIGITS 22 |
Definition at line 39 of file features.h.
Referenced by detect_disconnect(), and feature_interpret_helper().
#define AST_FEATURE_RETURN_SUCCESS 23 |
Definition at line 40 of file features.h.
#define AST_FEATURE_RETURN_SUCCESSBREAK 0 |
Definition at line 35 of file features.h.
#define FEATURE_APP_ARGS_LEN 256 |
Definition at line 29 of file features.h.
#define FEATURE_APP_LEN 64 |
Definition at line 28 of file features.h.
#define FEATURE_EXTEN_LEN 32 |
Definition at line 31 of file features.h.
#define FEATURE_MAX_LEN 11 |
#define FEATURE_MOH_LEN 80 |
Definition at line 32 of file features.h.
#define FEATURE_SENSE_CHAN (1 << 0) |
Definition at line 44 of file features.h.
Referenced by ast_bridge_call(), ast_feature_interpret(), and feature_exec_app().
#define FEATURE_SENSE_PEER (1 << 1) |
#define FEATURE_SNAME_LEN 32 |
Definition at line 30 of file features.h.
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 47 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.
chan,peer,config | Set start time, check for two channels,check if monitor on check for feature activation, create new CDR |
res | on success. | |
-1 | on failure to bridge. |
append the event to featurecode. we rely on the string being zero-filled, and not overflowing it.
Definition at line 2183 of file features.c.
References ast_channel::_state, ast_channel::accountcode, ast_cdr::accountcode, add_features_datastores(), ast_channel::amaflags, ast_cdr::amaflags, ast_cdr::answer, ast_channel::appl, 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_NULL, ast_cdr_setcid(), 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_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_debug, ast_default_amaflags, ast_dtmf_stream(), ast_exists_extension(), ast_feature_interpret(), 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_opt_end_cdr_before_h_exten, AST_OPTION_FLAG_REQUEST, ast_raw_answer(), ast_set2_flag, ast_set_flag, ast_spawn_extension(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_verb, ast_channel::cdr, chan, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_num, config, ast_channel::context, ast_option_header::data, ast_channel::data, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_channel::exten, f, FEATURE_MAX_LEN, FEATURE_RETURN_PASSDIGITS, FEATURE_RETURN_SUCCESS, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_cdr::lastapp, ast_cdr::lastdata, LOG_WARNING, monitor_app, ast_channel::name, ast_cdr::next, 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_channel::uniqueid, ast_cdr::uniqueid, ast_cdr::userfield, and ast_channel::visible_indication.
Referenced by app_exec(), ast_bridge_call_thread(), bridge_exec(), builtin_atxfer(), dial_exec_full(), and park_exec().
02184 { 02185 /* Copy voice back and forth between the two channels. Give the peer 02186 the ability to transfer calls with '#<extension' syntax. */ 02187 struct ast_frame *f; 02188 struct ast_channel *who; 02189 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 02190 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 02191 char orig_channame[AST_MAX_EXTENSION]; 02192 char orig_peername[AST_MAX_EXTENSION]; 02193 int res; 02194 int diff; 02195 int hasfeatures=0; 02196 int hadfeatures=0; 02197 int autoloopflag; 02198 struct ast_option_header *aoh; 02199 struct ast_bridge_config backup_config; 02200 struct ast_cdr *bridge_cdr = NULL; 02201 struct ast_cdr *orig_peer_cdr = NULL; 02202 struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 02203 struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 02204 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 02205 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 02206 02207 memset(&backup_config, 0, sizeof(backup_config)); 02208 02209 config->start_time = ast_tvnow(); 02210 02211 if (chan && peer) { 02212 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 02213 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 02214 } else if (chan) { 02215 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 02216 } 02217 02218 set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES")); 02219 add_features_datastores(chan, peer, config); 02220 02221 /* This is an interesting case. One example is if a ringing channel gets redirected to 02222 * an extension that picks up a parked call. This will make sure that the call taken 02223 * out of parking gets told that the channel it just got bridged to is still ringing. */ 02224 if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) { 02225 ast_indicate(peer, AST_CONTROL_RINGING); 02226 } 02227 02228 if (monitor_ok) { 02229 const char *monitor_exec; 02230 struct ast_channel *src = NULL; 02231 if (!monitor_app) { 02232 if (!(monitor_app = pbx_findapp("Monitor"))) 02233 monitor_ok=0; 02234 } 02235 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 02236 src = chan; 02237 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 02238 src = peer; 02239 if (monitor_app && src) { 02240 char *tmp = ast_strdupa(monitor_exec); 02241 pbx_exec(src, monitor_app, tmp); 02242 } 02243 } 02244 02245 set_config_flags(chan, peer, config); 02246 config->firstpass = 1; 02247 02248 /* Answer if need be */ 02249 if (chan->_state != AST_STATE_UP) { 02250 if (ast_raw_answer(chan, 1)) { 02251 return -1; 02252 } 02253 } 02254 02255 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame)); 02256 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername)); 02257 orig_peer_cdr = peer_cdr; 02258 02259 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) { 02260 02261 if (chan_cdr) { 02262 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); 02263 ast_cdr_update(chan); 02264 bridge_cdr = ast_cdr_dup(chan_cdr); 02265 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 02266 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 02267 } else { 02268 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */ 02269 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */ 02270 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel)); 02271 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel)); 02272 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid)); 02273 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 02274 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 02275 ast_cdr_setcid(bridge_cdr, chan); 02276 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL; 02277 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags; 02278 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode)); 02279 /* Destination information */ 02280 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst)); 02281 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext)); 02282 if (peer_cdr) { 02283 bridge_cdr->start = peer_cdr->start; 02284 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 02285 } else { 02286 ast_cdr_start(bridge_cdr); 02287 } 02288 } 02289 ast_debug(4,"bridge answer set, chan answer set\n"); 02290 /* peer_cdr->answer will be set when a macro runs on the peer; 02291 in that case, the bridge answer will be delayed while the 02292 macro plays on the peer channel. The peer answered the call 02293 before the macro started playing. To the phone system, 02294 this is billable time for the call, even tho the caller 02295 hears nothing but ringing while the macro does its thing. */ 02296 if (peer_cdr && !ast_tvzero(peer_cdr->answer)) { 02297 bridge_cdr->answer = peer_cdr->answer; 02298 bridge_cdr->disposition = peer_cdr->disposition; 02299 if (chan_cdr) { 02300 chan_cdr->answer = peer_cdr->answer; 02301 chan_cdr->disposition = peer_cdr->disposition; 02302 } 02303 } else { 02304 ast_cdr_answer(bridge_cdr); 02305 if (chan_cdr) { 02306 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */ 02307 } 02308 } 02309 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) { 02310 if (chan_cdr) { 02311 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED); 02312 } 02313 if (peer_cdr) { 02314 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED); 02315 } 02316 } 02317 } 02318 for (;;) { 02319 struct ast_channel *other; /* used later */ 02320 02321 res = ast_channel_bridge(chan, peer, config, &f, &who); 02322 02323 /* When frame is not set, we are probably involved in a situation 02324 where we've timed out. 02325 When frame is set, we'll come this code twice; once for DTMF_BEGIN 02326 and also for DTMF_END. If we flow into the following 'if' for both, then 02327 our wait times are cut in half, as both will subtract from the 02328 feature_timer. Not good! 02329 */ 02330 if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) { 02331 /* Update time limit for next pass */ 02332 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 02333 if (res == AST_BRIDGE_RETRY) { 02334 /* The feature fully timed out but has not been updated. Skip 02335 * the potential round error from the diff calculation and 02336 * explicitly set to expired. */ 02337 config->feature_timer = -1; 02338 } else { 02339 config->feature_timer -= diff; 02340 } 02341 02342 if (hasfeatures) { 02343 /* Running on backup config, meaning a feature might be being 02344 activated, but that's no excuse to keep things going 02345 indefinitely! */ 02346 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 02347 ast_debug(1, "Timed out, realtime this time!\n"); 02348 config->feature_timer = 0; 02349 who = chan; 02350 if (f) 02351 ast_frfree(f); 02352 f = NULL; 02353 res = 0; 02354 } else if (config->feature_timer <= 0) { 02355 /* Not *really* out of time, just out of time for 02356 digits to come in for features. */ 02357 ast_debug(1, "Timed out for feature!\n"); 02358 if (!ast_strlen_zero(peer_featurecode)) { 02359 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0); 02360 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 02361 } 02362 if (!ast_strlen_zero(chan_featurecode)) { 02363 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0); 02364 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 02365 } 02366 if (f) 02367 ast_frfree(f); 02368 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 02369 if (!hasfeatures) { 02370 /* Restore original (possibly time modified) bridge config */ 02371 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 02372 memset(&backup_config, 0, sizeof(backup_config)); 02373 } 02374 hadfeatures = hasfeatures; 02375 /* Continue as we were */ 02376 continue; 02377 } else if (!f) { 02378 /* The bridge returned without a frame and there is a feature in progress. 02379 * However, we don't think the feature has quite yet timed out, so just 02380 * go back into the bridge. */ 02381 continue; 02382 } 02383 } else { 02384 if (config->feature_timer <=0) { 02385 /* We ran out of time */ 02386 config->feature_timer = 0; 02387 who = chan; 02388 if (f) 02389 ast_frfree(f); 02390 f = NULL; 02391 res = 0; 02392 } 02393 } 02394 } 02395 if (res < 0) { 02396 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) 02397 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 02398 goto before_you_go; 02399 } 02400 02401 if (!f || (f->frametype == AST_FRAME_CONTROL && 02402 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 02403 f->subclass == AST_CONTROL_CONGESTION))) { 02404 res = -1; 02405 break; 02406 } 02407 /* many things should be sent to the 'other' channel */ 02408 other = (who == chan) ? peer : chan; 02409 if (f->frametype == AST_FRAME_CONTROL) { 02410 switch (f->subclass) { 02411 case AST_CONTROL_RINGING: 02412 case AST_CONTROL_FLASH: 02413 case -1: 02414 ast_indicate(other, f->subclass); 02415 break; 02416 case AST_CONTROL_HOLD: 02417 case AST_CONTROL_UNHOLD: 02418 ast_indicate_data(other, f->subclass, f->data, f->datalen); 02419 break; 02420 case AST_CONTROL_OPTION: 02421 aoh = f->data; 02422 /* Forward option Requests */ 02423 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 02424 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 02425 f->datalen - sizeof(struct ast_option_header), 0); 02426 } 02427 break; 02428 } 02429 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 02430 /* eat it */ 02431 } else if (f->frametype == AST_FRAME_DTMF) { 02432 char *featurecode; 02433 int sense; 02434 02435 hadfeatures = hasfeatures; 02436 /* This cannot overrun because the longest feature is one shorter than our buffer */ 02437 if (who == chan) { 02438 sense = FEATURE_SENSE_CHAN; 02439 featurecode = chan_featurecode; 02440 } else { 02441 sense = FEATURE_SENSE_PEER; 02442 featurecode = peer_featurecode; 02443 } 02444 /*! append the event to featurecode. we rely on the string being zero-filled, and 02445 * not overflowing it. 02446 * \todo XXX how do we guarantee the latter ? 02447 */ 02448 featurecode[strlen(featurecode)] = f->subclass; 02449 /* Get rid of the frame before we start doing "stuff" with the channels */ 02450 ast_frfree(f); 02451 f = NULL; 02452 config->feature_timer = backup_config.feature_timer; 02453 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 02454 switch(res) { 02455 case FEATURE_RETURN_PASSDIGITS: 02456 ast_dtmf_stream(other, who, featurecode, 0, 0); 02457 /* Fall through */ 02458 case FEATURE_RETURN_SUCCESS: 02459 memset(featurecode, 0, sizeof(chan_featurecode)); 02460 break; 02461 } 02462 if (res >= FEATURE_RETURN_PASSDIGITS) { 02463 res = 0; 02464 } else 02465 break; 02466 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 02467 if (hadfeatures && !hasfeatures) { 02468 /* Restore backup */ 02469 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 02470 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 02471 } else if (hasfeatures) { 02472 if (!hadfeatures) { 02473 /* Backup configuration */ 02474 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 02475 /* Setup temporary config options */ 02476 config->play_warning = 0; 02477 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 02478 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 02479 config->warning_freq = 0; 02480 config->warning_sound = NULL; 02481 config->end_sound = NULL; 02482 config->start_sound = NULL; 02483 config->firstpass = 0; 02484 } 02485 config->start_time = ast_tvnow(); 02486 config->feature_timer = featuredigittimeout; 02487 ast_debug(1, "Set time limit to %ld\n", config->feature_timer); 02488 } 02489 } 02490 if (f) 02491 ast_frfree(f); 02492 02493 } 02494 before_you_go: 02495 02496 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) { 02497 ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */ 02498 if (bridge_cdr) { 02499 ast_cdr_discard(bridge_cdr); 02500 /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */ 02501 } 02502 return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */ 02503 } 02504 02505 if (config->end_bridge_callback) { 02506 config->end_bridge_callback(config->end_bridge_callback_data); 02507 } 02508 02509 if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && 02510 ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) { 02511 struct ast_cdr *swapper = NULL; 02512 char savelastapp[AST_MAX_EXTENSION]; 02513 char savelastdata[AST_MAX_EXTENSION]; 02514 char save_exten[AST_MAX_EXTENSION]; 02515 int save_prio; 02516 int found = 0; /* set if we find at least one match */ 02517 int spawn_error = 0; 02518 02519 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); 02520 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); 02521 if (bridge_cdr && ast_opt_end_cdr_before_h_exten) { 02522 ast_cdr_end(bridge_cdr); 02523 } 02524 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge 02525 dialplan code operate on it */ 02526 ast_channel_lock(chan); 02527 if (bridge_cdr) { 02528 swapper = chan->cdr; 02529 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp)); 02530 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata)); 02531 chan->cdr = bridge_cdr; 02532 } 02533 ast_copy_string(save_exten, chan->exten, sizeof(save_exten)); 02534 save_prio = chan->priority; 02535 ast_copy_string(chan->exten, "h", sizeof(chan->exten)); 02536 chan->priority = 1; 02537 ast_channel_unlock(chan); 02538 while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) { 02539 chan->priority++; 02540 } 02541 if (found && spawn_error) { 02542 /* Something bad happened, or a hangup has been requested. */ 02543 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 02544 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 02545 } 02546 /* swap it back */ 02547 ast_channel_lock(chan); 02548 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten)); 02549 chan->priority = save_prio; 02550 if (bridge_cdr) { 02551 if (chan->cdr == bridge_cdr) { 02552 chan->cdr = swapper; 02553 } else { 02554 bridge_cdr = NULL; 02555 } 02556 } 02557 if (chan->priority != 1 || !spawn_error) { 02558 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN); 02559 } 02560 ast_channel_unlock(chan); 02561 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */ 02562 if (bridge_cdr) { 02563 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp)); 02564 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata)); 02565 } 02566 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02567 } 02568 02569 /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */ 02570 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 02571 if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) 02572 ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED); 02573 02574 /* we can post the bridge CDR at this point */ 02575 if (bridge_cdr) { 02576 ast_cdr_end(bridge_cdr); 02577 ast_cdr_detach(bridge_cdr); 02578 } 02579 02580 /* do a specialized reset on the beginning channel 02581 CDR's, if they still exist, so as not to mess up 02582 issues in future bridges; 02583 02584 Here are the rules of the game: 02585 1. The chan and peer channel pointers will not change 02586 during the life of the bridge. 02587 2. But, in transfers, the channel names will change. 02588 between the time the bridge is started, and the 02589 time the channel ends. 02590 Usually, when a channel changes names, it will 02591 also change CDR pointers. 02592 3. Usually, only one of the two channels (chan or peer) 02593 will change names. 02594 4. Usually, if a channel changes names during a bridge, 02595 it is because of a transfer. Usually, in these situations, 02596 it is normal to see 2 bridges running simultaneously, and 02597 it is not unusual to see the two channels that change 02598 swapped between bridges. 02599 5. After a bridge occurs, we have 2 or 3 channels' CDRs 02600 to attend to; if the chan or peer changed names, 02601 we have the before and after attached CDR's. 02602 */ 02603 02604 if (new_chan_cdr) { 02605 struct ast_channel *chan_ptr = NULL; 02606 02607 if (strcasecmp(orig_channame, chan->name) != 0) { 02608 /* old channel */ 02609 chan_ptr = ast_get_channel_by_name_locked(orig_channame); 02610 if (chan_ptr) { 02611 if (!ast_bridged_channel(chan_ptr)) { 02612 struct ast_cdr *cur; 02613 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02614 if (cur == chan_cdr) { 02615 break; 02616 } 02617 } 02618 if (cur) 02619 ast_cdr_specialized_reset(chan_cdr,0); 02620 } 02621 ast_channel_unlock(chan_ptr); 02622 } 02623 /* new channel */ 02624 ast_cdr_specialized_reset(new_chan_cdr,0); 02625 } else { 02626 ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */ 02627 } 02628 } 02629 02630 { 02631 struct ast_channel *chan_ptr = NULL; 02632 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 02633 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)) 02634 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */ 02635 if (strcasecmp(orig_peername, peer->name) != 0) { 02636 /* old channel */ 02637 chan_ptr = ast_get_channel_by_name_locked(orig_peername); 02638 if (chan_ptr) { 02639 if (!ast_bridged_channel(chan_ptr)) { 02640 struct ast_cdr *cur; 02641 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02642 if (cur == peer_cdr) { 02643 break; 02644 } 02645 } 02646 if (cur) 02647 ast_cdr_specialized_reset(peer_cdr,0); 02648 } 02649 ast_channel_unlock(chan_ptr); 02650 } 02651 /* new channel */ 02652 ast_cdr_specialized_reset(new_peer_cdr,0); 02653 } else { 02654 ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */ 02655 } 02656 } 02657 02658 return res; 02659 }
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 1842 of file features.c.
References chan, feature_group_exten::feature, and feature_interpret_helper().
Referenced by detect_disconnect().
01842 { 01843 01844 return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature); 01845 }
int ast_features_reload | ( | void | ) |
Reload call features from features.conf.
Definition at line 3483 of file features.c.
References load_config(), and RESULT_SUCCESS.
03484 { 03485 load_config(); 03486 03487 return RESULT_SUCCESS; 03488 }
struct ast_call_feature* ast_find_call_feature | ( | const char * | name | ) |
look for a call feature entry by its sname
name | a string ptr, should match "automon", "blindxfer", "atxfer", etc. |
Definition at line 1597 of file features.c.
References builtin_features, FEATURES_COUNT, and ast_call_feature::sname.
Referenced by handle_request_info().
01598 { 01599 int x; 01600 for (x = 0; x < FEATURES_COUNT; x++) { 01601 if (!strcasecmp(name, builtin_features[x].sname)) 01602 return &builtin_features[x]; 01603 } 01604 return NULL; 01605 }
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. | |
timeout | is a timeout in milliseconds | |
extout | is a parameter to an int that will hold the parked location, or NULL if you want. |
0 | on success. | |
-1 | on failure. |
Definition at line 665 of file features.c.
References masq_park_call().
Referenced by manager_park(), mgcp_ss(), parkandannounce_exec(), and ss_thread().
00666 { 00667 return masq_park_call(rchan, peer, timeout, extout, 0, NULL); 00668 }
int ast_park_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | host, | |||
int | timeout, | |||
int * | extout | |||
) |
Park a call and read back parked location.
chan | the channel to actually be parked | |
host | the channel which will have the parked location read to. | |
timeout | is a timeout in milliseconds | |
extout | is a parameter to an int that will hold the parked location, or NULL if you want. |
0 | on success. | |
-1 | on failure. |
Definition at line 611 of file features.c.
References chan, and park_call_full().
Referenced by iax_park_thread(), and sip_park_thread().
00612 { 00613 return park_call_full(chan, peer, timeout, extout, NULL, NULL); 00614 }
const char* ast_parking_ext | ( | void | ) |
Determine system parking extension.
Definition at line 226 of file features.c.
References parking_ext.
Referenced by builtin_atxfer(), builtin_blindtransfer(), dp_lookup(), handle_request_refer(), mgcp_ss(), socket_process(), and ss_thread().
00227 { 00228 return parking_ext; 00229 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
chan | channel that initiated pickup. |
Definition at line 3851 of file features.c.
References ast_channel::_state, ast_answer(), ast_channel_masquerade(), ast_channel_unlock, ast_channel_walk_locked(), AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_queue_control(), AST_STATE_RING, AST_STATE_RINGING, ast_channel::callgroup, chan, LOG_WARNING, ast_channel::name, ast_channel::pbx, and ast_channel::pickupgroup.
Referenced by cb_events(), handle_request_invite(), mgcp_ss(), pickup_exec(), and ss_thread().
03852 { 03853 struct ast_channel *cur = NULL; 03854 int res = -1; 03855 03856 while ((cur = ast_channel_walk_locked(cur)) != NULL) { 03857 if (!cur->pbx && 03858 (cur != chan) && 03859 (chan->pickupgroup & cur->callgroup) && 03860 ((cur->_state == AST_STATE_RINGING) || 03861 (cur->_state == AST_STATE_RING))) { 03862 break; 03863 } 03864 ast_channel_unlock(cur); 03865 } 03866 if (cur) { 03867 ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 03868 res = ast_answer(chan); 03869 if (res) 03870 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 03871 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 03872 if (res) 03873 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 03874 res = ast_channel_masquerade(cur, chan); 03875 if (res) 03876 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 03877 ast_channel_unlock(cur); 03878 } else { 03879 ast_debug(1, "No call pickup possible...\n"); 03880 } 03881 return res; 03882 }
const char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 231 of file features.c.
References pickup_ext.
Referenced by cb_events(), get_destination(), handle_feature_show(), handle_request_invite(), mgcp_ss(), and ss_thread().
00232 { 00233 return pickup_ext; 00234 }
void ast_rdlock_call_features | ( | void | ) |
Definition at line 1587 of file features.c.
References ast_rwlock_rdlock(), and features_lock.
Referenced by handle_request_info().
01588 { 01589 ast_rwlock_rdlock(&features_lock); 01590 }
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 1424 of file features.c.
References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, feature_group_exten::feature, LOG_NOTICE, and ast_call_feature::sname.
01425 { 01426 if (!feature) { 01427 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 01428 return; 01429 } 01430 01431 AST_RWLIST_WRLOCK(&feature_list); 01432 AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry); 01433 AST_RWLIST_UNLOCK(&feature_list); 01434 01435 ast_verb(2, "Registered Feature '%s'\n",feature->sname); 01436 }
void ast_unlock_call_features | ( | void | ) |
Definition at line 1592 of file features.c.
References ast_rwlock_unlock(), and features_lock.
Referenced by handle_request_info().
01593 { 01594 ast_rwlock_unlock(&features_lock); 01595 }
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 1512 of file features.c.
References ast_free, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and feature_group_exten::feature.
01513 { 01514 if (!feature) { 01515 return; 01516 } 01517 01518 AST_RWLIST_WRLOCK(&feature_list); 01519 AST_RWLIST_REMOVE(&feature_list, feature, feature_entry); 01520 AST_RWLIST_UNLOCK(&feature_list); 01521 01522 ast_free(feature); 01523 }