This graph shows which files directly or indirectly include this file:

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_SNAME_LEN 32 |
| #define | PARK_APP_NAME "Park" |
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_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 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_SNAME_LEN 32 |
Definition at line 30 of file features.h.
| #define PARK_APP_NAME "Park" |
| 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 1437 of file res_features.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_answer(), ast_bridged_channel(), ast_cdr_alloc(), ast_cdr_answer(), AST_CDR_ANSWERED, ast_cdr_detach(), 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_default_amaflags, ast_dtmf_stream(), ast_exists_extension(), ast_feature_interpret(), AST_FEATURE_NO_H_EXTEN, AST_FEATURE_PLAY_WARNING, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, 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_PBX_KEEPALIVE, AST_PBX_NO_HANGUP_PEER_PARKED, ast_set2_flag, ast_set_flag, ast_spawn_extension(), AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verbose(), ast_channel::cdr, ast_cdr::channel, config, ast_option_header::data, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, f, 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_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(), set_config_flags(), ast_cdr::start, ast_cdr::uniqueid, ast_cdr::userfield, and VERBOSE_PREFIX_2.
Referenced by app_exec(), ast_bridge_call_thread(), builtin_atxfer(), park_exec(), and try_calling().
01438 { 01439 /* Copy voice back and forth between the two channels. Give the peer 01440 the ability to transfer calls with '#<extension' syntax. */ 01441 struct ast_frame *f; 01442 struct ast_channel *who; 01443 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 01444 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 01445 char orig_channame[AST_MAX_EXTENSION]; 01446 char orig_peername[AST_MAX_EXTENSION]; 01447 01448 int res; 01449 int diff; 01450 int hasfeatures=0; 01451 int hadfeatures=0; 01452 int autoloopflag; 01453 struct ast_option_header *aoh; 01454 struct ast_bridge_config backup_config; 01455 struct ast_cdr *bridge_cdr = NULL; 01456 struct ast_cdr *orig_peer_cdr = NULL; 01457 struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 01458 struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 01459 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 01460 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 01461 01462 memset(&backup_config, 0, sizeof(backup_config)); 01463 01464 config->start_time = ast_tvnow(); 01465 01466 if (chan && peer) { 01467 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01468 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01469 } else if (chan) 01470 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01471 01472 if (monitor_ok) { 01473 const char *monitor_exec; 01474 struct ast_channel *src = NULL; 01475 if (!monitor_app) { 01476 if (!(monitor_app = pbx_findapp("Monitor"))) 01477 monitor_ok=0; 01478 } 01479 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01480 src = chan; 01481 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01482 src = peer; 01483 if (monitor_app && src) { 01484 char *tmp = ast_strdupa(monitor_exec); 01485 pbx_exec(src, monitor_app, tmp); 01486 } 01487 } 01488 01489 set_config_flags(chan, peer, config); 01490 config->firstpass = 1; 01491 01492 /* Answer if need be */ 01493 if (ast_answer(chan)) 01494 return -1; 01495 01496 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame)); 01497 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername)); 01498 orig_peer_cdr = peer_cdr; 01499 01500 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) { 01501 01502 if (chan_cdr) { 01503 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); 01504 ast_cdr_update(chan); 01505 bridge_cdr = ast_cdr_dup(chan_cdr); 01506 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp)); 01507 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata)); 01508 } else { 01509 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */ 01510 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */ 01511 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel)); 01512 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel)); 01513 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid)); 01514 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp)); 01515 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata)); 01516 ast_cdr_setcid(bridge_cdr, chan); 01517 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL; 01518 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags; 01519 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode)); 01520 /* Destination information */ 01521 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst)); 01522 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext)); 01523 if (peer_cdr) { 01524 bridge_cdr->start = peer_cdr->start; 01525 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 01526 } else { 01527 ast_cdr_start(bridge_cdr); 01528 } 01529 } 01530 /* peer_cdr->answer will be set when a macro runs on the peer; 01531 in that case, the bridge answer will be delayed while the 01532 macro plays on the peer channel. The peer answered the call 01533 before the macro started playing. To the phone system, 01534 this is billable time for the call, even tho the caller 01535 hears nothing but ringing while the macro does its thing. */ 01536 if (peer_cdr && !ast_tvzero(peer_cdr->answer)) { 01537 bridge_cdr->answer = peer_cdr->answer; 01538 chan_cdr->answer = peer_cdr->answer; 01539 bridge_cdr->disposition = peer_cdr->disposition; 01540 chan_cdr->disposition = peer_cdr->disposition; 01541 } else { 01542 ast_cdr_answer(bridge_cdr); 01543 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */ 01544 } 01545 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED); 01546 if (peer_cdr) { 01547 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED); 01548 } 01549 } 01550 01551 for (;;) { 01552 struct ast_channel *other; /* used later */ 01553 01554 res = ast_channel_bridge(chan, peer, config, &f, &who); 01555 01556 if (config->feature_timer) { 01557 /* Update time limit for next pass */ 01558 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 01559 config->feature_timer -= diff; 01560 if (hasfeatures) { 01561 /* Running on backup config, meaning a feature might be being 01562 activated, but that's no excuse to keep things going 01563 indefinitely! */ 01564 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01565 if (option_debug) 01566 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01567 config->feature_timer = 0; 01568 who = chan; 01569 if (f) 01570 ast_frfree(f); 01571 f = NULL; 01572 res = 0; 01573 } else if (config->feature_timer <= 0) { 01574 /* Not *really* out of time, just out of time for 01575 digits to come in for features. */ 01576 if (option_debug) 01577 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01578 if (!ast_strlen_zero(peer_featurecode)) { 01579 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01580 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01581 } 01582 if (!ast_strlen_zero(chan_featurecode)) { 01583 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01584 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01585 } 01586 if (f) 01587 ast_frfree(f); 01588 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01589 if (!hasfeatures) { 01590 /* Restore original (possibly time modified) bridge config */ 01591 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01592 memset(&backup_config, 0, sizeof(backup_config)); 01593 } 01594 hadfeatures = hasfeatures; 01595 /* Continue as we were */ 01596 continue; 01597 } else if (!f) { 01598 /* The bridge returned without a frame and there is a feature in progress. 01599 * However, we don't think the feature has quite yet timed out, so just 01600 * go back into the bridge. */ 01601 continue; 01602 } 01603 } else { 01604 if (config->feature_timer <=0) { 01605 /* We ran out of time */ 01606 config->feature_timer = 0; 01607 who = chan; 01608 if (f) 01609 ast_frfree(f); 01610 f = NULL; 01611 res = 0; 01612 } 01613 } 01614 } 01615 if (res < 0) { 01616 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) 01617 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01618 goto before_you_go; 01619 } 01620 01621 if (!f || (f->frametype == AST_FRAME_CONTROL && 01622 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 01623 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 01624 res = -1; 01625 break; 01626 } 01627 /* many things should be sent to the 'other' channel */ 01628 other = (who == chan) ? peer : chan; 01629 if (f->frametype == AST_FRAME_CONTROL) { 01630 switch (f->subclass) { 01631 case AST_CONTROL_RINGING: 01632 case AST_CONTROL_FLASH: 01633 case -1: 01634 ast_indicate(other, f->subclass); 01635 break; 01636 case AST_CONTROL_HOLD: 01637 case AST_CONTROL_UNHOLD: 01638 ast_indicate_data(other, f->subclass, f->data, f->datalen); 01639 break; 01640 case AST_CONTROL_OPTION: 01641 aoh = f->data; 01642 /* Forward option Requests */ 01643 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 01644 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 01645 f->datalen - sizeof(struct ast_option_header), 0); 01646 } 01647 break; 01648 } 01649 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 01650 /* eat it */ 01651 } else if (f->frametype == AST_FRAME_DTMF) { 01652 char *featurecode; 01653 int sense; 01654 01655 hadfeatures = hasfeatures; 01656 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01657 if (who == chan) { 01658 sense = FEATURE_SENSE_CHAN; 01659 featurecode = chan_featurecode; 01660 } else { 01661 sense = FEATURE_SENSE_PEER; 01662 featurecode = peer_featurecode; 01663 } 01664 /*! append the event to featurecode. we rely on the string being zero-filled, and 01665 * not overflowing it. 01666 * \todo XXX how do we guarantee the latter ? 01667 */ 01668 featurecode[strlen(featurecode)] = f->subclass; 01669 /* Get rid of the frame before we start doing "stuff" with the channels */ 01670 ast_frfree(f); 01671 f = NULL; 01672 config->feature_timer = backup_config.feature_timer; 01673 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01674 switch(res) { 01675 case FEATURE_RETURN_PASSDIGITS: 01676 ast_dtmf_stream(other, who, featurecode, 0); 01677 /* Fall through */ 01678 case FEATURE_RETURN_SUCCESS: 01679 memset(featurecode, 0, sizeof(chan_featurecode)); 01680 break; 01681 } 01682 if (res >= FEATURE_RETURN_PASSDIGITS) { 01683 res = 0; 01684 } else 01685 break; 01686 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01687 if (hadfeatures && !hasfeatures) { 01688 /* Restore backup */ 01689 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01690 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01691 } else if (hasfeatures) { 01692 if (!hadfeatures) { 01693 /* Backup configuration */ 01694 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01695 /* Setup temporary config options */ 01696 config->play_warning = 0; 01697 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01698 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01699 config->warning_freq = 0; 01700 config->warning_sound = NULL; 01701 config->end_sound = NULL; 01702 config->start_sound = NULL; 01703 config->firstpass = 0; 01704 } 01705 config->start_time = ast_tvnow(); 01706 config->feature_timer = featuredigittimeout; 01707 if (option_debug) 01708 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01709 } 01710 } 01711 if (f) 01712 ast_frfree(f); 01713 01714 } 01715 before_you_go: 01716 if (res != AST_PBX_KEEPALIVE && config->end_bridge_callback) { 01717 config->end_bridge_callback(); 01718 } 01719 01720 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); 01721 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); 01722 if (res != AST_PBX_KEEPALIVE && !ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) { 01723 struct ast_cdr *swapper; 01724 char savelastapp[AST_MAX_EXTENSION]; 01725 char savelastdata[AST_MAX_EXTENSION]; 01726 char save_exten[AST_MAX_EXTENSION]; 01727 int save_prio; 01728 01729 if (ast_opt_end_cdr_before_h_exten) { 01730 ast_cdr_end(bridge_cdr); 01731 } 01732 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge 01733 dialplan code operate on it */ 01734 swapper = chan->cdr; 01735 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp)); 01736 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata)); 01737 ast_channel_lock(chan); 01738 chan->cdr = bridge_cdr; 01739 ast_copy_string(save_exten, chan->exten, sizeof(save_exten)); 01740 ast_copy_string(chan->exten, "h", sizeof(chan->exten)); 01741 save_prio = chan->priority; 01742 chan->priority = 1; 01743 ast_channel_unlock(chan); 01744 while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 01745 if (ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 01746 /* Something bad happened, or a hangup has been requested. */ 01747 if (option_debug) 01748 ast_log(LOG_DEBUG, "Spawn h extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 01749 if (option_verbose > 1) 01750 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); 01751 break; 01752 } 01753 chan->priority++; 01754 } 01755 /* swap it back */ 01756 ast_channel_lock(chan); 01757 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten)); 01758 chan->priority = save_prio; 01759 chan->cdr = swapper; 01760 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN); 01761 ast_channel_unlock(chan); 01762 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */ 01763 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp)); 01764 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata)); 01765 } 01766 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); 01767 01768 /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */ 01769 if (res != AST_PBX_KEEPALIVE) { 01770 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 01771 if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) 01772 ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED); 01773 } 01774 01775 /* we can post the bridge CDR at this point */ 01776 ast_cdr_end(bridge_cdr); 01777 ast_cdr_detach(bridge_cdr); 01778 01779 /* do a specialized reset on the beginning channel 01780 CDR's, if they still exist, so as not to mess up 01781 issues in future bridges; 01782 01783 Here are the rules of the game: 01784 1. The chan and peer channel pointers will not change 01785 during the life of the bridge. 01786 2. But, in transfers, the channel names will change. 01787 between the time the bridge is started, and the 01788 time the channel ends. 01789 Usually, when a channel changes names, it will 01790 also change CDR pointers. 01791 3. Usually, only one of the two channels (chan or peer) 01792 will change names. 01793 4. Usually, if a channel changes names during a bridge, 01794 it is because of a transfer. Usually, in these situations, 01795 it is normal to see 2 bridges running simultaneously, and 01796 it is not unusual to see the two channels that change 01797 swapped between bridges. 01798 5. After a bridge occurs, we have 2 or 3 channels' CDRs 01799 to attend to; if the chan or peer changed names, 01800 we have the before and after attached CDR's. 01801 6. Parking has to be accounted for in the code: 01802 a. Parking will cause ast_bridge_call to return 01803 either AST_PBX_NO_HANGUP_PEER or AST_PBX_NO_HANGUP_PEER_PARKED; 01804 in the latter case, peer is (most likely) a bad 01805 pointer, you can no longer deref it. If it does still 01806 exist, it is under another's thread control, and 01807 could be destroyed at any time. 01808 b. The same applies to AST_PBX_KEEPALIVE, in which 01809 case, the chan ptr cannot be used, as another thread 01810 owns it and may have destroyed the channel. 01811 c. In the former case, you need to check peer to see if it 01812 still exists before you deref it, and obtain a lock. 01813 d. In neither case should you do an ast_hangup(peer). 01814 e. Do not overwrite the result code from ast_bridge_call. 01815 */ 01816 01817 if (res != AST_PBX_KEEPALIVE && new_chan_cdr) { 01818 struct ast_channel *chan_ptr = NULL; 01819 01820 if (strcasecmp(orig_channame, chan->name) != 0) { 01821 /* old channel */ 01822 chan_ptr = ast_get_channel_by_name_locked(orig_channame); 01823 if (chan_ptr) { 01824 if (!ast_bridged_channel(chan_ptr)) { 01825 struct ast_cdr *cur; 01826 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 01827 if (cur == chan_cdr) { 01828 break; 01829 } 01830 } 01831 if (cur) 01832 ast_cdr_specialized_reset(chan_cdr,0); 01833 } 01834 ast_channel_unlock(chan_ptr); 01835 } 01836 /* new channel */ 01837 ast_cdr_specialized_reset(new_chan_cdr,0); 01838 } else { 01839 ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */ 01840 } 01841 } 01842 01843 if (res != AST_PBX_NO_HANGUP_PEER_PARKED) { /* if the peer was involved in a park, don't even touch it; it's probably gone */ 01844 struct ast_channel *chan_ptr = NULL; 01845 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 01846 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)) 01847 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */ 01848 if (strcasecmp(orig_peername, peer->name) != 0) { 01849 /* old channel */ 01850 chan_ptr = ast_get_channel_by_name_locked(orig_peername); 01851 if (chan_ptr) { 01852 if (!ast_bridged_channel(chan_ptr)) { 01853 struct ast_cdr *cur; 01854 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 01855 if (cur == peer_cdr) { 01856 break; 01857 } 01858 } 01859 if (cur) 01860 ast_cdr_specialized_reset(peer_cdr,0); 01861 } 01862 ast_channel_unlock(chan_ptr); 01863 } 01864 /* new channel */ 01865 ast_cdr_specialized_reset(new_peer_cdr,0); 01866 } else { 01867 ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */ 01868 } 01869 } 01870 return res; 01871 }
| 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 529 of file res_features.c.
References masq_park_call().
Referenced by handle_exec(), manager_park(), mgcp_ss(), parkandannounce_exec(), and ss_thread().
00530 { 00531 return masq_park_call(rchan, peer, timeout, extout, 0); 00532 }
| 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 484 of file res_features.c.
References park_call_full().
Referenced by builtin_blindtransfer(), builtin_parkcall(), iax_park_thread(), and sip_park_thread().
00485 { 00486 return park_call_full(chan, peer, timeout, extout, NULL); 00487 }
| 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 162 of file res_features.c.
Referenced by builtin_blindtransfer(), dp_lookup(), handle_request_refer(), mgcp_ss(), socket_process(), and ss_thread().
00163 { 00164 return parking_ext; 00165 }
| int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 2446 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, option_debug, ast_channel::pbx, and ast_channel::pickupgroup.
Referenced by cb_events(), handle_request_invite(), mgcp_ss(), and ss_thread().
02447 { 02448 struct ast_channel *cur = NULL; 02449 int res = -1; 02450 02451 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 02452 if (!cur->pbx && 02453 (cur != chan) && 02454 (chan->pickupgroup & cur->callgroup) && 02455 ((cur->_state == AST_STATE_RINGING) || 02456 (cur->_state == AST_STATE_RING))) { 02457 break; 02458 } 02459 ast_channel_unlock(cur); 02460 } 02461 if (cur) { 02462 if (option_debug) 02463 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 02464 res = ast_answer(chan); 02465 if (res) 02466 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 02467 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 02468 if (res) 02469 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 02470 res = ast_channel_masquerade(cur, chan); 02471 if (res) 02472 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 02473 ast_channel_unlock(cur); 02474 } else { 02475 if (option_debug) 02476 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 02477 } 02478 return res; 02479 }
| char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 167 of file res_features.c.
Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().
00168 { 00169 return pickup_ext; 00170 }
| 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 1010 of file res_features.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_verbose(), LOG_NOTICE, option_verbose, ast_call_feature::sname, and VERBOSE_PREFIX_2.
01011 { 01012 if (!feature) { 01013 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 01014 return; 01015 } 01016 01017 AST_LIST_LOCK(&feature_list); 01018 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry); 01019 AST_LIST_UNLOCK(&feature_list); 01020 01021 if (option_verbose >= 2) 01022 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 01023 }
| 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 1026 of file res_features.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.
01027 { 01028 if (!feature) 01029 return; 01030 01031 AST_LIST_LOCK(&feature_list); 01032 AST_LIST_REMOVE(&feature_list,feature,feature_entry); 01033 AST_LIST_UNLOCK(&feature_list); 01034 free(feature); 01035 }
1.5.1