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 |
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. | |
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 |
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.
int ast_autoanswer_login | ( | struct ast_channel * | chan, | |
void * | data | |||
) |
Definition at line 2758 of file res_features.c.
References ast_channel::_state, aalot, 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(), autoanswer, autoanswer_thread, aauser::chan, aauser::context, ast_channel::data, EVENT_FLAG_CALL, exten, aauser::exten, free, LOG_ERROR, LOG_NOTICE, LOG_WARNING, malloc, manager_event(), aauser::next, option_verbose, registrar, s, 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, config, ast_channel::data, ast_option_header::data, ast_cdr::dstchannel, f, FEATURE_MAX_LEN, FEATURE_RETURN_PASSDIGITS, FEATURE_RETURN_SUCCESS, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_option_header::flag, free, LOG_DEBUG, LOG_WARNING, monitor_app, ast_option_header::option, option_debug, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), set_config_flags(), and ast_cdr::userfield.
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 | ) |
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, holdlist, 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, holding_thread, holdlist, LOG_WARNING, malloc, and manager_event().
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(), 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.
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(), 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.
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(), config, LOG_WARNING, option_verbose, and VERBOSE_PREFIX_3.
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 }