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 |
Functions | |
int | ast_autoanswer_login (struct ast_channel *chan, void *data) |
int | ast_bridge_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config) |
Bridge a call, optionally allowing redirection. | |
struct ast_channel * | ast_get_holded_call (char *uniqueid) |
int | ast_hold_call (struct ast_channel *chan, struct ast_channel *host) |
int | ast_masq_autoanswer_login (struct ast_channel *rchan, void *data) |
int | ast_masq_hold_call (struct ast_channel *rchan, struct ast_channel *host) |
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 | |
int | ast_retrieve_call (struct ast_channel *chan, char *uniqueid) |
int | ast_retrieve_call_to_death (char *uniqueid) |
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 |
#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 |
int ast_autoanswer_login | ( | struct ast_channel * | chan, | |
void * | data | |||
) |
Definition at line 2767 of file res_features.c.
References ast_channel::_state, ast_channel::appl, ast_add_extension2(), ast_answer(), ast_context_create(), ast_context_find(), ast_hangup(), ast_log(), AST_MAX_EXTENSION, ast_moh_start(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, ast_strdupa, ast_verbose(), aauser::chan, aauser::context, ast_channel::data, EVENT_FLAG_CALL, aauser::exten, exten, free, LOG_ERROR, LOG_NOTICE, LOG_WARNING, malloc, manager_event(), aauser::next, option_verbose, s, aauser::start, strdup, strsep(), and VERBOSE_PREFIX_2.
Referenced by ast_masq_autoanswer_login(), and autoanswer_exec().
02768 { 02769 /* We put the user in the parking list, then wake up the parking thread to be sure it looks 02770 after these channels too */ 02771 struct ast_context *con; 02772 char exten[AST_MAX_EXTENSION]; 02773 struct aauser *pu,*pl = NULL; 02774 char *s, *stringp, *aacontext, *aaexten = NULL; 02775 02776 s = ast_strdupa((void *) data); 02777 stringp=s; 02778 aacontext = strsep(&stringp, "|"); 02779 aaexten = strsep(&stringp, "|"); 02780 if (!aaexten) { 02781 aaexten = aacontext; 02782 aacontext = NULL; 02783 } 02784 if (!aaexten) { 02785 ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n"); 02786 return -1; 02787 } else { 02788 if (!aacontext) { 02789 aacontext = "default"; 02790 } 02791 } 02792 02793 ast_mutex_lock(&autoanswer_lock); 02794 pu = aalot; 02795 while(pu) { 02796 if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){ 02797 if (pl) 02798 pl->next = pu->next; 02799 else 02800 aalot = pu->next; 02801 break; 02802 } 02803 pl = pu; 02804 pu = pu->next; 02805 } 02806 ast_mutex_unlock(&autoanswer_lock); 02807 if (pu) { 02808 ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context); 02809 manager_event(EVENT_FLAG_CALL, "AutoanswerLogout", 02810 "Channel: %s\r\n" 02811 "Uniqueid: %s\r\n" 02812 "Context: %s\r\n" 02813 "Exten: %s\r\n" 02814 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten); 02815 ast_hangup(pu->chan); 02816 free(pu); 02817 } 02818 pu = malloc(sizeof(struct aauser)); 02819 if (pu) { 02820 memset(pu, 0, sizeof(pu)); 02821 ast_mutex_lock(&autoanswer_lock); 02822 chan->appl = "Autoanswer"; 02823 chan->data = NULL; 02824 02825 pu->chan = chan; 02826 if (chan->_state != AST_STATE_UP) { 02827 ast_answer(chan); 02828 } 02829 02830 /* Start music on hold */ 02831 ast_moh_start(pu->chan, NULL, NULL); 02832 gettimeofday(&pu->start, NULL); 02833 strncpy(pu->exten, aaexten, sizeof(pu->exten)-1); 02834 strncpy(pu->context, aacontext, sizeof(pu->exten)-1); 02835 pu->next = aalot; 02836 aalot = pu; 02837 con = ast_context_find(aacontext); 02838 if (!con) { 02839 con = ast_context_create(NULL,aacontext, registrar); 02840 if (!con) { 02841 ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext); 02842 } 02843 } 02844 if (con) { 02845 snprintf(exten, sizeof(exten), "%s", aaexten); 02846 ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar); 02847 } 02848 02849 ast_mutex_unlock(&autoanswer_lock); 02850 /* Wake up the (presumably select()ing) thread */ 02851 pthread_kill(autoanswer_thread, SIGURG); 02852 if (option_verbose > 1) 02853 ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context); 02854 manager_event(EVENT_FLAG_CALL, "AutoanswerLogin", 02855 "Channel: %s\r\n" 02856 "Uniqueid: %s\r\n" 02857 "Context: %s\r\n" 02858 "Exten: %s\r\n" 02859 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten); 02860 02861 return 0; 02862 } else { 02863 ast_log(LOG_WARNING, "Out of memory\n"); 02864 return -1; 02865 } 02866 return 0; 02867 }
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_channel::appl, ast_answer(), ast_cdr_alloc(), ast_cdr_appenduserfield(), ast_cdr_discard(), AST_CDR_FLAG_LOCKED, ast_cdr_init(), ast_cdr_merge(), ast_cdr_setdestchan(), ast_cdr_setuserfield(), ast_cdr_start(), 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_dtmf_stream(), ast_feature_interpret(), AST_FEATURE_PLAY_WARNING, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, ast_frfree, ast_indicate(), ast_indicate_data(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_FLAG_REQUEST, AST_OPTION_RELAXDTMF, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, ast_cdr::channel, ast_option_header::data, ast_frame::data, ast_channel::data, ast_frame::datalen, ast_cdr::dstchannel, ast_bridge_config::end_sound, f, FEATURE_MAX_LEN, FEATURE_RETURN_PASSDIGITS, FEATURE_RETURN_SUCCESS, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_bridge_config::feature_timer, ast_bridge_config::features_callee, ast_bridge_config::features_caller, ast_bridge_config::firstpass, ast_option_header::flag, ast_frame::frametype, free, LOG_DEBUG, LOG_WARNING, ast_option_header::option, option_debug, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), ast_bridge_config::play_warning, set_config_flags(), ast_bridge_config::start_sound, ast_bridge_config::start_time, ast_frame::subclass, ast_cdr::userfield, ast_bridge_config::warning_freq, and ast_bridge_config::warning_sound.
Referenced by app_exec(), ast_bridge_call_thread(), ast_retrieve_call(), autoanswer_exec(), bridge_exec(), 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 int res; 01446 int diff; 01447 int hasfeatures=0; 01448 int hadfeatures=0; 01449 struct ast_option_header *aoh; 01450 struct ast_bridge_config backup_config; 01451 struct ast_cdr *bridge_cdr; 01452 01453 memset(&backup_config, 0, sizeof(backup_config)); 01454 01455 config->start_time = ast_tvnow(); 01456 01457 if (chan && peer) { 01458 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01459 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01460 } else if (chan) 01461 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01462 01463 if (monitor_ok) { 01464 const char *monitor_exec; 01465 struct ast_channel *src = NULL; 01466 if (!monitor_app) { 01467 if (!(monitor_app = pbx_findapp("Monitor"))) 01468 monitor_ok=0; 01469 } 01470 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01471 src = chan; 01472 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01473 src = peer; 01474 if (monitor_app && src) { 01475 char *tmp = ast_strdupa(monitor_exec); 01476 pbx_exec(src, monitor_app, tmp); 01477 } 01478 } 01479 01480 set_config_flags(chan, peer, config); 01481 config->firstpass = 1; 01482 01483 /* Answer if need be */ 01484 if (ast_answer(chan)) 01485 return -1; 01486 peer->appl = "Bridged Call"; 01487 peer->data = chan->name; 01488 01489 /* copy the userfield from the B-leg to A-leg if applicable */ 01490 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) { 01491 char tmp[256]; 01492 if (!ast_strlen_zero(chan->cdr->userfield)) { 01493 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield); 01494 ast_cdr_appenduserfield(chan, tmp); 01495 } else 01496 ast_cdr_setuserfield(chan, peer->cdr->userfield); 01497 /* free the peer's cdr without ast_cdr_free complaining */ 01498 free(peer->cdr); 01499 peer->cdr = NULL; 01500 } 01501 01502 for (;;) { 01503 struct ast_channel *other; /* used later */ 01504 01505 res = ast_channel_bridge(chan, peer, config, &f, &who); 01506 01507 if (config->feature_timer) { 01508 /* Update time limit for next pass */ 01509 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 01510 config->feature_timer -= diff; 01511 if (hasfeatures) { 01512 /* Running on backup config, meaning a feature might be being 01513 activated, but that's no excuse to keep things going 01514 indefinitely! */ 01515 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01516 if (option_debug) 01517 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01518 config->feature_timer = 0; 01519 who = chan; 01520 if (f) 01521 ast_frfree(f); 01522 f = NULL; 01523 res = 0; 01524 } else if (config->feature_timer <= 0) { 01525 /* Not *really* out of time, just out of time for 01526 digits to come in for features. */ 01527 if (option_debug) 01528 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01529 if (!ast_strlen_zero(peer_featurecode)) { 01530 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01531 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01532 } 01533 if (!ast_strlen_zero(chan_featurecode)) { 01534 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01535 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01536 } 01537 if (f) 01538 ast_frfree(f); 01539 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01540 if (!hasfeatures) { 01541 /* Restore original (possibly time modified) bridge config */ 01542 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01543 memset(&backup_config, 0, sizeof(backup_config)); 01544 } 01545 hadfeatures = hasfeatures; 01546 /* Continue as we were */ 01547 continue; 01548 } else if (!f) { 01549 /* The bridge returned without a frame and there is a feature in progress. 01550 * However, we don't think the feature has quite yet timed out, so just 01551 * go back into the bridge. */ 01552 continue; 01553 } 01554 } else { 01555 if (config->feature_timer <=0) { 01556 /* We ran out of time */ 01557 config->feature_timer = 0; 01558 who = chan; 01559 if (f) 01560 ast_frfree(f); 01561 f = NULL; 01562 res = 0; 01563 } 01564 } 01565 } 01566 if (res < 0) { 01567 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) 01568 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01569 return -1; 01570 } 01571 01572 if (!f || (f->frametype == AST_FRAME_CONTROL && 01573 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 01574 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 01575 res = -1; 01576 break; 01577 } 01578 /* many things should be sent to the 'other' channel */ 01579 other = (who == chan) ? peer : chan; 01580 if (f->frametype == AST_FRAME_CONTROL) { 01581 switch (f->subclass) { 01582 case AST_CONTROL_RINGING: 01583 case AST_CONTROL_FLASH: 01584 case -1: 01585 ast_indicate(other, f->subclass); 01586 break; 01587 case AST_CONTROL_HOLD: 01588 case AST_CONTROL_UNHOLD: 01589 ast_indicate_data(other, f->subclass, f->data, f->datalen); 01590 break; 01591 case AST_CONTROL_OPTION: 01592 aoh = f->data; 01593 /* Forward option Requests, but only ones we know are safe 01594 * These are ONLY sent by chan_iax2 and I'm not convinced that 01595 * they are useful. I haven't deleted them entirely because I 01596 * just am not sure of the ramifications of removing them. */ 01597 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 01598 switch (ntohs(aoh->option)) { 01599 case AST_OPTION_TONE_VERIFY: 01600 case AST_OPTION_TDD: 01601 case AST_OPTION_RELAXDTMF: 01602 case AST_OPTION_AUDIO_MODE: 01603 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 01604 f->datalen - sizeof(struct ast_option_header), 0); 01605 } 01606 } 01607 break; 01608 } 01609 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 01610 /* eat it */ 01611 } else if (f->frametype == AST_FRAME_DTMF) { 01612 char *featurecode; 01613 int sense; 01614 01615 hadfeatures = hasfeatures; 01616 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01617 if (who == chan) { 01618 sense = FEATURE_SENSE_CHAN; 01619 featurecode = chan_featurecode; 01620 } else { 01621 sense = FEATURE_SENSE_PEER; 01622 featurecode = peer_featurecode; 01623 } 01624 /*! append the event to featurecode. we rely on the string being zero-filled, and 01625 * not overflowing it. 01626 * \todo XXX how do we guarantee the latter ? 01627 */ 01628 featurecode[strlen(featurecode)] = f->subclass; 01629 /* Get rid of the frame before we start doing "stuff" with the channels */ 01630 ast_frfree(f); 01631 f = NULL; 01632 config->feature_timer = backup_config.feature_timer; 01633 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01634 switch(res) { 01635 case FEATURE_RETURN_PASSDIGITS: 01636 ast_dtmf_stream(other, who, featurecode, 0); 01637 /* Fall through */ 01638 case FEATURE_RETURN_SUCCESS: 01639 memset(featurecode, 0, sizeof(chan_featurecode)); 01640 break; 01641 } 01642 if (res >= FEATURE_RETURN_PASSDIGITS) { 01643 res = 0; 01644 } else 01645 break; 01646 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01647 if (hadfeatures && !hasfeatures) { 01648 /* Restore backup */ 01649 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01650 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01651 } else if (hasfeatures) { 01652 if (!hadfeatures) { 01653 /* Backup configuration */ 01654 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01655 /* Setup temporary config options */ 01656 config->play_warning = 0; 01657 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01658 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01659 config->warning_freq = 0; 01660 config->warning_sound = NULL; 01661 config->end_sound = NULL; 01662 config->start_sound = NULL; 01663 config->firstpass = 0; 01664 } 01665 config->start_time = ast_tvnow(); 01666 config->feature_timer = featuredigittimeout; 01667 if (option_debug) 01668 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01669 } 01670 } 01671 if (f) 01672 ast_frfree(f); 01673 01674 } 01675 01676 /* arrange the cdrs */ 01677 bridge_cdr = ast_cdr_alloc(); 01678 if (bridge_cdr) { 01679 if (chan->cdr && peer->cdr) { /* both of them? merge */ 01680 ast_channel_lock(chan); /* lock the channel before modifing cdrs */ 01681 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */ 01682 ast_cdr_start(bridge_cdr); /* now is the time to start */ 01683 01684 /* absorb the channel cdr */ 01685 ast_cdr_merge(bridge_cdr, chan->cdr); 01686 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 01687 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01688 01689 chan->cdr = NULL; /* remove pointer to freed memory before releasing the lock */ 01690 01691 ast_channel_unlock(chan); 01692 01693 /* absorb the peer cdr */ 01694 ast_channel_lock(peer); 01695 ast_cdr_merge(bridge_cdr, peer->cdr); 01696 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) 01697 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */ 01698 01699 peer->cdr = NULL; 01700 ast_channel_unlock(peer); 01701 01702 ast_channel_lock(chan); 01703 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01704 ast_channel_unlock(chan); 01705 01706 } else if (chan->cdr) { 01707 01708 ast_channel_lock(chan); /* Lock before modifying CDR */ 01709 /* take the cdr from the channel - literally */ 01710 ast_cdr_init(bridge_cdr,chan); 01711 /* absorb this data */ 01712 ast_cdr_merge(bridge_cdr, chan->cdr); 01713 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 01714 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01715 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01716 ast_channel_unlock(chan); 01717 } else if (peer->cdr) { 01718 ast_channel_lock(peer); /* Lock before modifying CDR */ 01719 /* take the cdr from the peer - literally */ 01720 ast_cdr_init(bridge_cdr,peer); 01721 /* absorb this data */ 01722 ast_cdr_merge(bridge_cdr, peer->cdr); 01723 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) 01724 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01725 peer->cdr = NULL; 01726 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01727 ast_channel_unlock(peer); 01728 } else { 01729 ast_channel_lock(chan); /* Lock before modifying CDR */ 01730 /* make up a new cdr */ 01731 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */ 01732 chan->cdr = bridge_cdr; /* */ 01733 ast_channel_unlock(chan); 01734 } 01735 if (ast_strlen_zero(bridge_cdr->dstchannel)) { 01736 if (strcmp(bridge_cdr->channel, peer->name) != 0) 01737 ast_cdr_setdestchan(bridge_cdr, peer->name); 01738 else 01739 ast_cdr_setdestchan(bridge_cdr, chan->name); 01740 } 01741 } 01742 return res; 01743 }
struct ast_channel* ast_get_holded_call | ( | char * | uniqueid | ) | [read] |
Definition at line 2252 of file res_features.c.
References ast_get_channel_by_uniqueid_locked(), ast_log(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, LOG_WARNING, holdeduser::next, option_verbose, holdeduser::uniqueid, and VERBOSE_PREFIX_3.
Referenced by ast_retrieve_call(), and ast_retrieve_call_to_death().
02253 { 02254 int res=-1; 02255 struct ast_channel *peer=NULL; 02256 struct holdeduser *pu, *pl=NULL; 02257 02258 ast_mutex_lock(&holding_lock); 02259 pu = holdlist; 02260 while(pu) { 02261 if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) { 02262 if (pl) 02263 pl->next = pu->next; 02264 else 02265 holdlist = pu->next; 02266 break; 02267 } 02268 pl = pu; 02269 pu = pu->next; 02270 } 02271 ast_mutex_unlock(&holding_lock); 02272 if (pu) { 02273 peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid); 02274 free(pu); 02275 if (peer) { 02276 res=0; 02277 if (option_verbose > 2) 02278 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name); 02279 ast_moh_stop(peer); 02280 return peer; 02281 } else { 02282 if (option_verbose > 2) 02283 ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid); 02284 return NULL; 02285 } 02286 } else { 02287 ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid); 02288 } 02289 return NULL; 02290 }
int ast_hold_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | host | |||
) |
Definition at line 2110 of file res_features.c.
References ast_channel::appl, ast_log(), ast_moh_start(), ast_mutex_lock(), ast_mutex_unlock(), holdeduser::chan, ast_channel::data, EVENT_FLAG_CALL, LOG_WARNING, malloc, manager_event(), holdeduser::next, holdeduser::start, holdeduser::uniqueid, and holdeduser::uniqueidpeer.
Referenced by ast_masq_hold_call().
02111 { 02112 /* We put the user in the parking list, then wake up the parking thread to be sure it looks 02113 after these channels too */ 02114 struct holdeduser *pu; 02115 pu = malloc(sizeof(struct holdeduser)); 02116 if (pu) { 02117 memset(pu, 0, sizeof(pu)); 02118 ast_mutex_lock(&holding_lock); 02119 chan->appl = "Holded Call"; 02120 chan->data = NULL; 02121 02122 pu->chan = chan; 02123 strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid)); 02124 strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer)); 02125 /* Start music on hold */ 02126 ast_moh_start(pu->chan, NULL, NULL); 02127 gettimeofday(&pu->start, NULL); 02128 pu->next = holdlist; 02129 holdlist = pu; 02130 ast_mutex_unlock(&holding_lock); 02131 /* Wake up the (presumably select()ing) thread */ 02132 pthread_kill(holding_thread, SIGURG); 02133 02134 manager_event(EVENT_FLAG_CALL, "HoldedCall", 02135 "Channel1: %s\r\n" 02136 "Channel2: %s\r\n" 02137 "Uniqueid1: %s\r\n" 02138 "Uniqueid2: %s\r\n" 02139 ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid); 02140 02141 } else { 02142 ast_log(LOG_WARNING, "Out of memory\n"); 02143 return -1; 02144 } 02145 return 0; 02146 }
int ast_masq_autoanswer_login | ( | struct ast_channel * | rchan, | |
void * | data | |||
) |
Definition at line 2721 of file res_features.c.
References ast_autoanswer_login(), ast_channel_alloc(), ast_channel_masquerade(), ast_frfree, ast_log(), ast_read(), AST_STATE_DOWN, ast_string_field_build, ast_channel::context, ast_channel::exten, f, LOG_WARNING, name, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
Referenced by autoanswer_login_exec().
02722 { 02723 struct ast_channel *chan; 02724 struct ast_frame *f; 02725 /* Make a new, fake channel that we'll use to masquerade in the real one */ 02726 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name); 02727 if (chan) { 02728 /* Let us keep track of the channel name */ 02729 ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name); 02730 /* Make formats okay */ 02731 chan->readformat = rchan->readformat; 02732 chan->writeformat = rchan->writeformat; 02733 ast_channel_masquerade(chan, rchan); 02734 /* Setup the extensions and such */ 02735 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1); 02736 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1); 02737 chan->priority = rchan->priority; 02738 /* might be dirty but we want trackable channels */ 02739 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid); 02740 /* Make the masq execute */ 02741 f = ast_read(chan); 02742 if (f) 02743 ast_frfree(f); 02744 ast_autoanswer_login(chan, data); 02745 } else { 02746 ast_log(LOG_WARNING, "Unable to create aa channel\n"); 02747 return -1; 02748 } 02749 return 0; 02750 }
int ast_masq_hold_call | ( | struct ast_channel * | rchan, | |
struct ast_channel * | host | |||
) |
Definition at line 2148 of file res_features.c.
References ast_channel_alloc(), ast_channel_masquerade(), ast_frfree, ast_hold_call(), ast_log(), ast_read(), AST_STATE_DOWN, ast_string_field_build, ast_channel::context, ast_channel::exten, f, LOG_WARNING, name, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
02149 { 02150 struct ast_channel *chan; 02151 struct ast_frame *f; 02152 /* Make a new, fake channel that we'll use to masquerade in the real one */ 02153 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name); 02154 if (chan) { 02155 /* Let us keep track of the channel name */ 02156 ast_string_field_build(chan, name, "Onhold/%s",rchan->name); 02157 /* Make formats okay */ 02158 chan->readformat = rchan->readformat; 02159 chan->writeformat = rchan->writeformat; 02160 ast_channel_masquerade(chan, rchan); 02161 /* Setup the extensions and such */ 02162 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1); 02163 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1); 02164 chan->priority = rchan->priority; 02165 /* this might be dirty, but we need to preserve the uniqueid */ 02166 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid); 02167 /* Make the masq execute */ 02168 f = ast_read(chan); 02169 if (f) 02170 ast_frfree(f); 02171 ast_hold_call(chan, peer); 02172 return -1; 02173 } else { 02174 ast_log(LOG_WARNING, "Unable to create holded channel\n"); 02175 return -1; 02176 } 02177 return 0; 02178 }
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 538 of file res_features.c.
References ast_channel::amaflags, ast_channel_alloc(), ast_channel_masquerade(), ast_frfree, ast_log(), ast_read(), AST_STATE_DOWN, ast_strdupa, ast_channel::context, ast_channel::exten, f, LOG_WARNING, park_call_full(), ast_channel::priority, ast_channel::readformat, set_c_e_p(), and ast_channel::writeformat.
Referenced by manager_park(), mgcp_ss(), parkandannounce_exec(), rpt_exec(), and ss_thread().
00539 { 00540 struct ast_channel *chan; 00541 struct ast_frame *f; 00542 char *orig_chan_name = NULL; 00543 00544 /* Make a new, fake channel that we'll use to masquerade in the real one */ 00545 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) { 00546 ast_log(LOG_WARNING, "Unable to create parked channel\n"); 00547 return -1; 00548 } 00549 00550 /* Make formats okay */ 00551 chan->readformat = rchan->readformat; 00552 chan->writeformat = rchan->writeformat; 00553 ast_channel_masquerade(chan, rchan); 00554 00555 /* Setup the extensions and such */ 00556 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority); 00557 00558 /* Make the masq execute */ 00559 f = ast_read(chan); 00560 if (f) 00561 ast_frfree(f); 00562 00563 orig_chan_name = ast_strdupa(chan->name); 00564 00565 park_call_full(chan, peer, timeout, extout, orig_chan_name); 00566 00567 return 0; 00568 }
int ast_park_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | peer, | |||
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 Park the channel chan, and read back the parked location to the host. If the call is not picked up within a specified period of time, then the call will return to the last step that it was in (in terms of exten, priority and context) | |
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 533 of file res_features.c.
References park_call_full().
Referenced by builtin_blindtransfer(), builtin_parkcall(), iax_park_thread(), and sip_park_thread().
00534 { 00535 return park_call_full(chan, peer, timeout, extout, NULL); 00536 }
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 218 of file res_features.c.
Referenced by builtin_blindtransfer(), dp_lookup(), handle_request_refer(), load_config(), mgcp_ss(), socket_process(), and ss_thread().
00219 { 00220 return parking_ext; 00221 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 3109 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().
03110 { 03111 struct ast_channel *cur = NULL; 03112 int res = -1; 03113 03114 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 03115 if (!cur->pbx && 03116 (cur != chan) && 03117 (chan->pickupgroup & cur->callgroup) && 03118 ((cur->_state == AST_STATE_RINGING) || 03119 (cur->_state == AST_STATE_RING))) { 03120 break; 03121 } 03122 ast_channel_unlock(cur); 03123 } 03124 if (cur) { 03125 if (option_debug) 03126 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 03127 res = ast_answer(chan); 03128 if (res) 03129 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 03130 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 03131 if (res) 03132 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 03133 res = ast_channel_masquerade(cur, chan); 03134 if (res) 03135 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 03136 ast_channel_unlock(cur); 03137 } else { 03138 if (option_debug) 03139 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 03140 } 03141 return res; 03142 }
char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 223 of file res_features.c.
Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().
00224 { 00225 return pickup_ext; 00226 }
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 1006 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.
Referenced by load_config().
01007 { 01008 if (!feature) { 01009 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 01010 return; 01011 } 01012 01013 AST_LIST_LOCK(&feature_list); 01014 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry); 01015 AST_LIST_UNLOCK(&feature_list); 01016 01017 if (option_verbose >= 2) 01018 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 01019 }
int ast_retrieve_call | ( | struct ast_channel * | chan, | |
char * | uniqueid | |||
) |
Definition at line 2180 of file res_features.c.
References ast_channel::_state, ast_answer(), ast_bridge_call(), ast_channel_make_compatible(), AST_FEATURE_REDIRECT, ast_get_holded_call(), ast_hangup(), ast_log(), ast_moh_stop(), ast_mutex_unlock(), AST_PBX_NO_HANGUP_PEER, ast_set_flag, AST_STATE_UP, ast_streamfile(), ast_verbose(), ast_waitstream(), ast_bridge_config::features_callee, ast_bridge_config::features_caller, LOG_WARNING, option_verbose, ast_bridge_config::play_warning, ast_bridge_config::timelimit, VERBOSE_PREFIX_3, ast_bridge_config::warning_freq, and ast_bridge_config::warning_sound.
Referenced by retrieve_call_exec().
02181 { 02182 int res=-1, dres=-1; 02183 struct ast_channel *peer=NULL; 02184 struct ast_bridge_config config; 02185 02186 peer = ast_get_holded_call(uniqueid); 02187 02188 /* JK02: it helps to answer the channel if not already up */ 02189 if (chan->_state != AST_STATE_UP) { 02190 ast_answer(chan); 02191 } 02192 02193 if (peer) { 02194 ast_mutex_unlock(&peer->lock); 02195 ast_moh_stop(peer); 02196 res = ast_channel_make_compatible(chan, peer); 02197 if (res < 0) { 02198 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name); 02199 ast_hangup(peer); 02200 return -1; 02201 } 02202 /* This runs sorta backwards, since we give the incoming channel control, as if it 02203 were the person called. */ 02204 if (option_verbose > 2) 02205 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name); 02206 02207 memset(&config,0,sizeof(struct ast_bridge_config)); 02208 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 02209 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT); 02210 config.timelimit = 0; 02211 config.play_warning = 0; 02212 config.warning_freq = 0; 02213 config.warning_sound=NULL; 02214 res = ast_bridge_call(chan,peer,&config); 02215 02216 /* Simulate the PBX hanging up */ 02217 if (res != AST_PBX_NO_HANGUP_PEER) 02218 ast_hangup(peer); 02219 return res; 02220 } else { 02221 /* XXX Play a message XXX */ 02222 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language); 02223 if (!dres) 02224 dres = ast_waitstream(chan, ""); 02225 else { 02226 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name); 02227 dres = 0; 02228 } 02229 } 02230 return res; 02231 }
int ast_retrieve_call_to_death | ( | char * | uniqueid | ) |
Definition at line 2233 of file res_features.c.
References ast_get_holded_call(), ast_hangup(), ast_log(), ast_mutex_unlock(), ast_verbose(), ast_channel::lock, LOG_WARNING, option_verbose, and VERBOSE_PREFIX_3.
02234 { 02235 int res=-1; 02236 struct ast_channel *peer=NULL; 02237 02238 peer = ast_get_holded_call(uniqueid); 02239 02240 if (peer) { 02241 res=0; 02242 if (option_verbose > 2) 02243 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name); 02244 ast_mutex_unlock(&peer->lock); 02245 ast_hangup(peer); 02246 } else { 02247 ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid); 02248 } 02249 return res; 02250 }
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 1022 of file res_features.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.
01023 { 01024 if (!feature) 01025 return; 01026 01027 AST_LIST_LOCK(&feature_list); 01028 AST_LIST_REMOVE(&feature_list,feature,feature_entry); 01029 AST_LIST_UNLOCK(&feature_list); 01030 free(feature); 01031 }