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 2758 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().
02759 { 02760 /* We put the user in the parking list, then wake up the parking thread to be sure it looks 02761 after these channels too */ 02762 struct ast_context *con; 02763 char exten[AST_MAX_EXTENSION]; 02764 struct aauser *pu,*pl = NULL; 02765 char *s, *stringp, *aacontext, *aaexten = NULL; 02766 02767 s = ast_strdupa((void *) data); 02768 stringp=s; 02769 aacontext = strsep(&stringp, "|"); 02770 aaexten = strsep(&stringp, "|"); 02771 if (!aaexten) { 02772 aaexten = aacontext; 02773 aacontext = NULL; 02774 } 02775 if (!aaexten) { 02776 ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n"); 02777 return -1; 02778 } else { 02779 if (!aacontext) { 02780 aacontext = "default"; 02781 } 02782 } 02783 02784 ast_mutex_lock(&autoanswer_lock); 02785 pu = aalot; 02786 while(pu) { 02787 if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){ 02788 if (pl) 02789 pl->next = pu->next; 02790 else 02791 aalot = pu->next; 02792 break; 02793 } 02794 pl = pu; 02795 pu = pu->next; 02796 } 02797 ast_mutex_unlock(&autoanswer_lock); 02798 if (pu) { 02799 ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context); 02800 manager_event(EVENT_FLAG_CALL, "AutoanswerLogout", 02801 "Channel: %s\r\n" 02802 "Uniqueid: %s\r\n" 02803 "Context: %s\r\n" 02804 "Exten: %s\r\n" 02805 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten); 02806 ast_hangup(pu->chan); 02807 free(pu); 02808 } 02809 pu = malloc(sizeof(struct aauser)); 02810 if (pu) { 02811 memset(pu, 0, sizeof(pu)); 02812 ast_mutex_lock(&autoanswer_lock); 02813 chan->appl = "Autoanswer"; 02814 chan->data = NULL; 02815 02816 pu->chan = chan; 02817 if (chan->_state != AST_STATE_UP) { 02818 ast_answer(chan); 02819 } 02820 02821 /* Start music on hold */ 02822 ast_moh_start(pu->chan, NULL, NULL); 02823 gettimeofday(&pu->start, NULL); 02824 strncpy(pu->exten, aaexten, sizeof(pu->exten)-1); 02825 strncpy(pu->context, aacontext, sizeof(pu->exten)-1); 02826 pu->next = aalot; 02827 aalot = pu; 02828 con = ast_context_find(aacontext); 02829 if (!con) { 02830 con = ast_context_create(NULL,aacontext, registrar); 02831 if (!con) { 02832 ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext); 02833 } 02834 } 02835 if (con) { 02836 snprintf(exten, sizeof(exten), "%s", aaexten); 02837 ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar); 02838 } 02839 02840 ast_mutex_unlock(&autoanswer_lock); 02841 /* Wake up the (presumably select()ing) thread */ 02842 pthread_kill(autoanswer_thread, SIGURG); 02843 if (option_verbose > 1) 02844 ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context); 02845 manager_event(EVENT_FLAG_CALL, "AutoanswerLogin", 02846 "Channel: %s\r\n" 02847 "Uniqueid: %s\r\n" 02848 "Context: %s\r\n" 02849 "Exten: %s\r\n" 02850 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten); 02851 02852 return 0; 02853 } else { 02854 ast_log(LOG_WARNING, "Out of memory\n"); 02855 return -1; 02856 } 02857 return 0; 02858 }
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_FLAG_REQUEST, 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 */ 01594 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 01595 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 01596 f->datalen - sizeof(struct ast_option_header), 0); 01597 } 01598 break; 01599 } 01600 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 01601 /* eat it */ 01602 } else if (f->frametype == AST_FRAME_DTMF) { 01603 char *featurecode; 01604 int sense; 01605 01606 hadfeatures = hasfeatures; 01607 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01608 if (who == chan) { 01609 sense = FEATURE_SENSE_CHAN; 01610 featurecode = chan_featurecode; 01611 } else { 01612 sense = FEATURE_SENSE_PEER; 01613 featurecode = peer_featurecode; 01614 } 01615 /*! append the event to featurecode. we rely on the string being zero-filled, and 01616 * not overflowing it. 01617 * \todo XXX how do we guarantee the latter ? 01618 */ 01619 featurecode[strlen(featurecode)] = f->subclass; 01620 /* Get rid of the frame before we start doing "stuff" with the channels */ 01621 ast_frfree(f); 01622 f = NULL; 01623 config->feature_timer = backup_config.feature_timer; 01624 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01625 switch(res) { 01626 case FEATURE_RETURN_PASSDIGITS: 01627 ast_dtmf_stream(other, who, featurecode, 0); 01628 /* Fall through */ 01629 case FEATURE_RETURN_SUCCESS: 01630 memset(featurecode, 0, sizeof(chan_featurecode)); 01631 break; 01632 } 01633 if (res >= FEATURE_RETURN_PASSDIGITS) { 01634 res = 0; 01635 } else 01636 break; 01637 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01638 if (hadfeatures && !hasfeatures) { 01639 /* Restore backup */ 01640 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01641 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01642 } else if (hasfeatures) { 01643 if (!hadfeatures) { 01644 /* Backup configuration */ 01645 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01646 /* Setup temporary config options */ 01647 config->play_warning = 0; 01648 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01649 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01650 config->warning_freq = 0; 01651 config->warning_sound = NULL; 01652 config->end_sound = NULL; 01653 config->start_sound = NULL; 01654 config->firstpass = 0; 01655 } 01656 config->start_time = ast_tvnow(); 01657 config->feature_timer = featuredigittimeout; 01658 if (option_debug) 01659 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01660 } 01661 } 01662 if (f) 01663 ast_frfree(f); 01664 01665 } 01666 01667 /* arrange the cdrs */ 01668 bridge_cdr = ast_cdr_alloc(); 01669 if (bridge_cdr) { 01670 if (chan->cdr && peer->cdr) { /* both of them? merge */ 01671 ast_channel_lock(chan); /* lock the channel before modifing cdrs */ 01672 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */ 01673 ast_cdr_start(bridge_cdr); /* now is the time to start */ 01674 01675 /* absorb the channel cdr */ 01676 ast_cdr_merge(bridge_cdr, chan->cdr); 01677 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 01678 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01679 01680 chan->cdr = NULL; /* remove pointer to freed memory before releasing the lock */ 01681 01682 ast_channel_unlock(chan); 01683 01684 /* absorb the peer cdr */ 01685 ast_channel_lock(peer); 01686 ast_cdr_merge(bridge_cdr, peer->cdr); 01687 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) 01688 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */ 01689 01690 peer->cdr = NULL; 01691 ast_channel_unlock(peer); 01692 01693 ast_channel_lock(chan); 01694 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01695 ast_channel_unlock(chan); 01696 01697 } else if (chan->cdr) { 01698 01699 ast_channel_lock(chan); /* Lock before modifying CDR */ 01700 /* take the cdr from the channel - literally */ 01701 ast_cdr_init(bridge_cdr,chan); 01702 /* absorb this data */ 01703 ast_cdr_merge(bridge_cdr, chan->cdr); 01704 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 01705 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01706 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01707 ast_channel_unlock(chan); 01708 } else if (peer->cdr) { 01709 ast_channel_lock(peer); /* Lock before modifying CDR */ 01710 /* take the cdr from the peer - literally */ 01711 ast_cdr_init(bridge_cdr,peer); 01712 /* absorb this data */ 01713 ast_cdr_merge(bridge_cdr, peer->cdr); 01714 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) 01715 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01716 peer->cdr = NULL; 01717 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01718 ast_channel_unlock(peer); 01719 } else { 01720 ast_channel_lock(chan); /* Lock before modifying CDR */ 01721 /* make up a new cdr */ 01722 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */ 01723 chan->cdr = bridge_cdr; /* */ 01724 ast_channel_unlock(chan); 01725 } 01726 if (ast_strlen_zero(bridge_cdr->dstchannel)) { 01727 if (strcmp(bridge_cdr->channel, peer->name) != 0) 01728 ast_cdr_setdestchan(bridge_cdr, peer->name); 01729 else 01730 ast_cdr_setdestchan(bridge_cdr, chan->name); 01731 } 01732 } 01733 return res; 01734 }
struct ast_channel* ast_get_holded_call | ( | char * | uniqueid | ) | [read] |
Definition at line 2243 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().
02244 { 02245 int res=-1; 02246 struct ast_channel *peer=NULL; 02247 struct holdeduser *pu, *pl=NULL; 02248 02249 ast_mutex_lock(&holding_lock); 02250 pu = holdlist; 02251 while(pu) { 02252 if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) { 02253 if (pl) 02254 pl->next = pu->next; 02255 else 02256 holdlist = pu->next; 02257 break; 02258 } 02259 pl = pu; 02260 pu = pu->next; 02261 } 02262 ast_mutex_unlock(&holding_lock); 02263 if (pu) { 02264 peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid); 02265 free(pu); 02266 if (peer) { 02267 res=0; 02268 if (option_verbose > 2) 02269 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name); 02270 ast_moh_stop(peer); 02271 return peer; 02272 } else { 02273 if (option_verbose > 2) 02274 ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid); 02275 return NULL; 02276 } 02277 } else { 02278 ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid); 02279 } 02280 return NULL; 02281 }
int ast_hold_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | host | |||
) |
Definition at line 2101 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().
02102 { 02103 /* We put the user in the parking list, then wake up the parking thread to be sure it looks 02104 after these channels too */ 02105 struct holdeduser *pu; 02106 pu = malloc(sizeof(struct holdeduser)); 02107 if (pu) { 02108 memset(pu, 0, sizeof(pu)); 02109 ast_mutex_lock(&holding_lock); 02110 chan->appl = "Holded Call"; 02111 chan->data = NULL; 02112 02113 pu->chan = chan; 02114 strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid)); 02115 strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer)); 02116 /* Start music on hold */ 02117 ast_moh_start(pu->chan, NULL, NULL); 02118 gettimeofday(&pu->start, NULL); 02119 pu->next = holdlist; 02120 holdlist = pu; 02121 ast_mutex_unlock(&holding_lock); 02122 /* Wake up the (presumably select()ing) thread */ 02123 pthread_kill(holding_thread, SIGURG); 02124 02125 manager_event(EVENT_FLAG_CALL, "HoldedCall", 02126 "Channel1: %s\r\n" 02127 "Channel2: %s\r\n" 02128 "Uniqueid1: %s\r\n" 02129 "Uniqueid2: %s\r\n" 02130 ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid); 02131 02132 } else { 02133 ast_log(LOG_WARNING, "Out of memory\n"); 02134 return -1; 02135 } 02136 return 0; 02137 }
int ast_masq_autoanswer_login | ( | struct ast_channel * | rchan, | |
void * | data | |||
) |
Definition at line 2712 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().
02713 { 02714 struct ast_channel *chan; 02715 struct ast_frame *f; 02716 /* Make a new, fake channel that we'll use to masquerade in the real one */ 02717 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name); 02718 if (chan) { 02719 /* Let us keep track of the channel name */ 02720 ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name); 02721 /* Make formats okay */ 02722 chan->readformat = rchan->readformat; 02723 chan->writeformat = rchan->writeformat; 02724 ast_channel_masquerade(chan, rchan); 02725 /* Setup the extensions and such */ 02726 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1); 02727 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1); 02728 chan->priority = rchan->priority; 02729 /* might be dirty but we want trackable channels */ 02730 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid); 02731 /* Make the masq execute */ 02732 f = ast_read(chan); 02733 if (f) 02734 ast_frfree(f); 02735 ast_autoanswer_login(chan, data); 02736 } else { 02737 ast_log(LOG_WARNING, "Unable to create aa channel\n"); 02738 return -1; 02739 } 02740 return 0; 02741 }
int ast_masq_hold_call | ( | struct ast_channel * | rchan, | |
struct ast_channel * | host | |||
) |
Definition at line 2139 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.
02140 { 02141 struct ast_channel *chan; 02142 struct ast_frame *f; 02143 /* Make a new, fake channel that we'll use to masquerade in the real one */ 02144 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name); 02145 if (chan) { 02146 /* Let us keep track of the channel name */ 02147 ast_string_field_build(chan, name, "Onhold/%s",rchan->name); 02148 /* Make formats okay */ 02149 chan->readformat = rchan->readformat; 02150 chan->writeformat = rchan->writeformat; 02151 ast_channel_masquerade(chan, rchan); 02152 /* Setup the extensions and such */ 02153 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1); 02154 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1); 02155 chan->priority = rchan->priority; 02156 /* this might be dirty, but we need to preserve the uniqueid */ 02157 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid); 02158 /* Make the masq execute */ 02159 f = ast_read(chan); 02160 if (f) 02161 ast_frfree(f); 02162 ast_hold_call(chan, peer); 02163 return -1; 02164 } else { 02165 ast_log(LOG_WARNING, "Unable to create holded channel\n"); 02166 return -1; 02167 } 02168 return 0; 02169 }
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 3100 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().
03101 { 03102 struct ast_channel *cur = NULL; 03103 int res = -1; 03104 03105 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 03106 if (!cur->pbx && 03107 (cur != chan) && 03108 (chan->pickupgroup & cur->callgroup) && 03109 ((cur->_state == AST_STATE_RINGING) || 03110 (cur->_state == AST_STATE_RING))) { 03111 break; 03112 } 03113 ast_channel_unlock(cur); 03114 } 03115 if (cur) { 03116 if (option_debug) 03117 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 03118 res = ast_answer(chan); 03119 if (res) 03120 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 03121 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 03122 if (res) 03123 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 03124 res = ast_channel_masquerade(cur, chan); 03125 if (res) 03126 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 03127 ast_channel_unlock(cur); 03128 } else { 03129 if (option_debug) 03130 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 03131 } 03132 return res; 03133 }
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 2171 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().
02172 { 02173 int res=-1, dres=-1; 02174 struct ast_channel *peer=NULL; 02175 struct ast_bridge_config config; 02176 02177 peer = ast_get_holded_call(uniqueid); 02178 02179 /* JK02: it helps to answer the channel if not already up */ 02180 if (chan->_state != AST_STATE_UP) { 02181 ast_answer(chan); 02182 } 02183 02184 if (peer) { 02185 ast_mutex_unlock(&peer->lock); 02186 ast_moh_stop(peer); 02187 res = ast_channel_make_compatible(chan, peer); 02188 if (res < 0) { 02189 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name); 02190 ast_hangup(peer); 02191 return -1; 02192 } 02193 /* This runs sorta backwards, since we give the incoming channel control, as if it 02194 were the person called. */ 02195 if (option_verbose > 2) 02196 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name); 02197 02198 memset(&config,0,sizeof(struct ast_bridge_config)); 02199 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 02200 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT); 02201 config.timelimit = 0; 02202 config.play_warning = 0; 02203 config.warning_freq = 0; 02204 config.warning_sound=NULL; 02205 res = ast_bridge_call(chan,peer,&config); 02206 02207 /* Simulate the PBX hanging up */ 02208 if (res != AST_PBX_NO_HANGUP_PEER) 02209 ast_hangup(peer); 02210 return res; 02211 } else { 02212 /* XXX Play a message XXX */ 02213 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language); 02214 if (!dres) 02215 dres = ast_waitstream(chan, ""); 02216 else { 02217 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name); 02218 dres = 0; 02219 } 02220 } 02221 return res; 02222 }
int ast_retrieve_call_to_death | ( | char * | uniqueid | ) |
Definition at line 2224 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.
02225 { 02226 int res=-1; 02227 struct ast_channel *peer=NULL; 02228 02229 peer = ast_get_holded_call(uniqueid); 02230 02231 if (peer) { 02232 res=0; 02233 if (option_verbose > 2) 02234 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name); 02235 ast_mutex_unlock(&peer->lock); 02236 ast_hangup(peer); 02237 } else { 02238 ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid); 02239 } 02240 return res; 02241 }
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 }