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 2576 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().
02577 { 02578 /* We put the user in the parking list, then wake up the parking thread to be sure it looks 02579 after these channels too */ 02580 struct ast_context *con; 02581 char exten[AST_MAX_EXTENSION]; 02582 struct aauser *pu,*pl = NULL; 02583 char *s, *stringp, *aacontext, *aaexten = NULL; 02584 02585 s = ast_strdupa((void *) data); 02586 stringp=s; 02587 aacontext = strsep(&stringp, "|"); 02588 aaexten = strsep(&stringp, "|"); 02589 if (!aaexten) { 02590 aaexten = aacontext; 02591 aacontext = NULL; 02592 } 02593 if (!aaexten) { 02594 ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n"); 02595 return -1; 02596 } else { 02597 if (!aacontext) { 02598 aacontext = "default"; 02599 } 02600 } 02601 02602 ast_mutex_lock(&autoanswer_lock); 02603 pu = aalot; 02604 while(pu) { 02605 if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){ 02606 if (pl) 02607 pl->next = pu->next; 02608 else 02609 aalot = pu->next; 02610 break; 02611 } 02612 pl = pu; 02613 pu = pu->next; 02614 } 02615 ast_mutex_unlock(&autoanswer_lock); 02616 if (pu) { 02617 ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context); 02618 manager_event(EVENT_FLAG_CALL, "AutoanswerLogout", 02619 "Channel: %s\r\n" 02620 "Uniqueid: %s\r\n" 02621 "Context: %s\r\n" 02622 "Exten: %s\r\n" 02623 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten); 02624 ast_hangup(pu->chan); 02625 free(pu); 02626 } 02627 pu = malloc(sizeof(struct aauser)); 02628 if (pu) { 02629 memset(pu, 0, sizeof(pu)); 02630 ast_mutex_lock(&autoanswer_lock); 02631 chan->appl = "Autoanswer"; 02632 chan->data = NULL; 02633 02634 pu->chan = chan; 02635 if (chan->_state != AST_STATE_UP) { 02636 ast_answer(chan); 02637 } 02638 02639 /* Start music on hold */ 02640 ast_moh_start(pu->chan, NULL, NULL); 02641 gettimeofday(&pu->start, NULL); 02642 strncpy(pu->exten, aaexten, sizeof(pu->exten)-1); 02643 strncpy(pu->context, aacontext, sizeof(pu->exten)-1); 02644 pu->next = aalot; 02645 aalot = pu; 02646 con = ast_context_find(aacontext); 02647 if (!con) { 02648 con = ast_context_create(NULL,aacontext, registrar); 02649 if (!con) { 02650 ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext); 02651 } 02652 } 02653 if (con) { 02654 snprintf(exten, sizeof(exten), "%s", aaexten); 02655 ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar); 02656 } 02657 02658 ast_mutex_unlock(&autoanswer_lock); 02659 /* Wake up the (presumably select()ing) thread */ 02660 pthread_kill(autoanswer_thread, SIGURG); 02661 if (option_verbose > 1) 02662 ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context); 02663 manager_event(EVENT_FLAG_CALL, "AutoanswerLogin", 02664 "Channel: %s\r\n" 02665 "Uniqueid: %s\r\n" 02666 "Context: %s\r\n" 02667 "Exten: %s\r\n" 02668 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten); 02669 02670 return 0; 02671 } else { 02672 ast_log(LOG_WARNING, "Out of memory\n"); 02673 return -1; 02674 } 02675 return 0; 02676 }
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 1405 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_setoption(), 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(), builtin_atxfer(), park_exec(), and try_calling().
01406 { 01407 /* Copy voice back and forth between the two channels. Give the peer 01408 the ability to transfer calls with '#<extension' syntax. */ 01409 struct ast_frame *f; 01410 struct ast_channel *who; 01411 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 01412 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 01413 int res; 01414 int diff; 01415 int hasfeatures=0; 01416 int hadfeatures=0; 01417 struct ast_option_header *aoh; 01418 struct ast_bridge_config backup_config; 01419 struct ast_cdr *bridge_cdr; 01420 01421 memset(&backup_config, 0, sizeof(backup_config)); 01422 01423 config->start_time = ast_tvnow(); 01424 01425 if (chan && peer) { 01426 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01427 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01428 } else if (chan) 01429 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01430 01431 if (monitor_ok) { 01432 const char *monitor_exec; 01433 struct ast_channel *src = NULL; 01434 if (!monitor_app) { 01435 if (!(monitor_app = pbx_findapp("Monitor"))) 01436 monitor_ok=0; 01437 } 01438 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01439 src = chan; 01440 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01441 src = peer; 01442 if (monitor_app && src) { 01443 char *tmp = ast_strdupa(monitor_exec); 01444 pbx_exec(src, monitor_app, tmp); 01445 } 01446 } 01447 01448 set_config_flags(chan, peer, config); 01449 config->firstpass = 1; 01450 01451 /* Answer if need be */ 01452 if (ast_answer(chan)) 01453 return -1; 01454 peer->appl = "Bridged Call"; 01455 peer->data = chan->name; 01456 01457 /* copy the userfield from the B-leg to A-leg if applicable */ 01458 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) { 01459 char tmp[256]; 01460 if (!ast_strlen_zero(chan->cdr->userfield)) { 01461 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield); 01462 ast_cdr_appenduserfield(chan, tmp); 01463 } else 01464 ast_cdr_setuserfield(chan, peer->cdr->userfield); 01465 /* free the peer's cdr without ast_cdr_free complaining */ 01466 free(peer->cdr); 01467 peer->cdr = NULL; 01468 } 01469 01470 for (;;) { 01471 struct ast_channel *other; /* used later */ 01472 01473 res = ast_channel_bridge(chan, peer, config, &f, &who); 01474 01475 if (config->feature_timer) { 01476 /* Update time limit for next pass */ 01477 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 01478 config->feature_timer -= diff; 01479 if (hasfeatures) { 01480 /* Running on backup config, meaning a feature might be being 01481 activated, but that's no excuse to keep things going 01482 indefinitely! */ 01483 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01484 if (option_debug) 01485 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01486 config->feature_timer = 0; 01487 who = chan; 01488 if (f) 01489 ast_frfree(f); 01490 f = NULL; 01491 res = 0; 01492 } else if (config->feature_timer <= 0) { 01493 /* Not *really* out of time, just out of time for 01494 digits to come in for features. */ 01495 if (option_debug) 01496 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01497 if (!ast_strlen_zero(peer_featurecode)) { 01498 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01499 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01500 } 01501 if (!ast_strlen_zero(chan_featurecode)) { 01502 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01503 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01504 } 01505 if (f) 01506 ast_frfree(f); 01507 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01508 if (!hasfeatures) { 01509 /* Restore original (possibly time modified) bridge config */ 01510 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01511 memset(&backup_config, 0, sizeof(backup_config)); 01512 } 01513 hadfeatures = hasfeatures; 01514 /* Continue as we were */ 01515 continue; 01516 } else if (!f) { 01517 /* The bridge returned without a frame and there is a feature in progress. 01518 * However, we don't think the feature has quite yet timed out, so just 01519 * go back into the bridge. */ 01520 continue; 01521 } 01522 } else { 01523 if (config->feature_timer <=0) { 01524 /* We ran out of time */ 01525 config->feature_timer = 0; 01526 who = chan; 01527 if (f) 01528 ast_frfree(f); 01529 f = NULL; 01530 res = 0; 01531 } 01532 } 01533 } 01534 if (res < 0) { 01535 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) 01536 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01537 return -1; 01538 } 01539 01540 if (!f || (f->frametype == AST_FRAME_CONTROL && 01541 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 01542 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 01543 res = -1; 01544 break; 01545 } 01546 /* many things should be sent to the 'other' channel */ 01547 other = (who == chan) ? peer : chan; 01548 if (f->frametype == AST_FRAME_CONTROL) { 01549 switch (f->subclass) { 01550 case AST_CONTROL_RINGING: 01551 case AST_CONTROL_FLASH: 01552 case -1: 01553 ast_indicate(other, f->subclass); 01554 break; 01555 case AST_CONTROL_HOLD: 01556 case AST_CONTROL_UNHOLD: 01557 ast_indicate_data(other, f->subclass, f->data, f->datalen); 01558 break; 01559 case AST_CONTROL_OPTION: 01560 aoh = f->data; 01561 /* Forward option Requests */ 01562 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 01563 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 01564 f->datalen - sizeof(struct ast_option_header), 0); 01565 } 01566 break; 01567 } 01568 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 01569 /* eat it */ 01570 } else if (f->frametype == AST_FRAME_DTMF) { 01571 char *featurecode; 01572 int sense; 01573 01574 hadfeatures = hasfeatures; 01575 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01576 if (who == chan) { 01577 sense = FEATURE_SENSE_CHAN; 01578 featurecode = chan_featurecode; 01579 } else { 01580 sense = FEATURE_SENSE_PEER; 01581 featurecode = peer_featurecode; 01582 } 01583 /*! append the event to featurecode. we rely on the string being zero-filled, and 01584 * not overflowing it. 01585 * \todo XXX how do we guarantee the latter ? 01586 */ 01587 featurecode[strlen(featurecode)] = f->subclass; 01588 /* Get rid of the frame before we start doing "stuff" with the channels */ 01589 ast_frfree(f); 01590 f = NULL; 01591 config->feature_timer = backup_config.feature_timer; 01592 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01593 switch(res) { 01594 case FEATURE_RETURN_PASSDIGITS: 01595 ast_dtmf_stream(other, who, featurecode, 0); 01596 /* Fall through */ 01597 case FEATURE_RETURN_SUCCESS: 01598 memset(featurecode, 0, sizeof(chan_featurecode)); 01599 break; 01600 } 01601 if (res >= FEATURE_RETURN_PASSDIGITS) { 01602 res = 0; 01603 } else 01604 break; 01605 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01606 if (hadfeatures && !hasfeatures) { 01607 /* Restore backup */ 01608 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01609 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01610 } else if (hasfeatures) { 01611 if (!hadfeatures) { 01612 /* Backup configuration */ 01613 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01614 /* Setup temporary config options */ 01615 config->play_warning = 0; 01616 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01617 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01618 config->warning_freq = 0; 01619 config->warning_sound = NULL; 01620 config->end_sound = NULL; 01621 config->start_sound = NULL; 01622 config->firstpass = 0; 01623 } 01624 config->start_time = ast_tvnow(); 01625 config->feature_timer = featuredigittimeout; 01626 if (option_debug) 01627 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01628 } 01629 } 01630 if (f) 01631 ast_frfree(f); 01632 01633 } 01634 01635 /* arrange the cdrs */ 01636 bridge_cdr = ast_cdr_alloc(); 01637 if (bridge_cdr) { 01638 if (chan->cdr && peer->cdr) { /* both of them? merge */ 01639 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */ 01640 ast_cdr_start(bridge_cdr); /* now is the time to start */ 01641 01642 /* absorb the channel cdr */ 01643 ast_cdr_merge(bridge_cdr, chan->cdr); 01644 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 01645 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01646 01647 /* absorb the peer cdr */ 01648 ast_cdr_merge(bridge_cdr, peer->cdr); 01649 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) 01650 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */ 01651 01652 peer->cdr = NULL; 01653 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01654 } else if (chan->cdr) { 01655 /* take the cdr from the channel - literally */ 01656 ast_cdr_init(bridge_cdr,chan); 01657 /* absorb this data */ 01658 ast_cdr_merge(bridge_cdr, chan->cdr); 01659 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 01660 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01661 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01662 } else if (peer->cdr) { 01663 /* take the cdr from the peer - literally */ 01664 ast_cdr_init(bridge_cdr,peer); 01665 /* absorb this data */ 01666 ast_cdr_merge(bridge_cdr, peer->cdr); 01667 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) 01668 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01669 peer->cdr = NULL; 01670 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01671 } else { 01672 /* make up a new cdr */ 01673 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */ 01674 chan->cdr = bridge_cdr; /* */ 01675 } 01676 if (ast_strlen_zero(bridge_cdr->dstchannel)) { 01677 if (strcmp(bridge_cdr->channel, peer->name) != 0) 01678 ast_cdr_setdestchan(bridge_cdr, peer->name); 01679 else 01680 ast_cdr_setdestchan(bridge_cdr, chan->name); 01681 } 01682 } 01683 return res; 01684 }
struct ast_channel* ast_get_holded_call | ( | char * | uniqueid | ) | [read] |
Definition at line 2180 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().
02181 { 02182 int res=-1; 02183 struct ast_channel *peer=NULL; 02184 struct holdeduser *pu, *pl=NULL; 02185 02186 ast_mutex_lock(&holding_lock); 02187 pu = holdlist; 02188 while(pu) { 02189 if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) { 02190 if (pl) 02191 pl->next = pu->next; 02192 else 02193 holdlist = pu->next; 02194 break; 02195 } 02196 pl = pu; 02197 pu = pu->next; 02198 } 02199 ast_mutex_unlock(&holding_lock); 02200 if (pu) { 02201 peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid); 02202 free(pu); 02203 if (peer) { 02204 res=0; 02205 if (option_verbose > 2) 02206 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name); 02207 ast_moh_stop(peer); 02208 return peer; 02209 } else { 02210 if (option_verbose > 2) 02211 ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid); 02212 return NULL; 02213 } 02214 } else { 02215 ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid); 02216 } 02217 return NULL; 02218 }
int ast_hold_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | host | |||
) |
Definition at line 2038 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().
02039 { 02040 /* We put the user in the parking list, then wake up the parking thread to be sure it looks 02041 after these channels too */ 02042 struct holdeduser *pu; 02043 pu = malloc(sizeof(struct holdeduser)); 02044 if (pu) { 02045 memset(pu, 0, sizeof(pu)); 02046 ast_mutex_lock(&holding_lock); 02047 chan->appl = "Holded Call"; 02048 chan->data = NULL; 02049 02050 pu->chan = chan; 02051 strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid)); 02052 strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer)); 02053 /* Start music on hold */ 02054 ast_moh_start(pu->chan, NULL, NULL); 02055 gettimeofday(&pu->start, NULL); 02056 pu->next = holdlist; 02057 holdlist = pu; 02058 ast_mutex_unlock(&holding_lock); 02059 /* Wake up the (presumably select()ing) thread */ 02060 pthread_kill(holding_thread, SIGURG); 02061 02062 manager_event(EVENT_FLAG_CALL, "HoldedCall", 02063 "Channel1: %s\r\n" 02064 "Channel2: %s\r\n" 02065 "Uniqueid1: %s\r\n" 02066 "Uniqueid2: %s\r\n" 02067 ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid); 02068 02069 } else { 02070 ast_log(LOG_WARNING, "Out of memory\n"); 02071 return -1; 02072 } 02073 return 0; 02074 }
int ast_masq_autoanswer_login | ( | struct ast_channel * | rchan, | |
void * | data | |||
) |
Definition at line 2530 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().
02531 { 02532 struct ast_channel *chan; 02533 struct ast_frame *f; 02534 /* Make a new, fake channel that we'll use to masquerade in the real one */ 02535 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name); 02536 if (chan) { 02537 /* Let us keep track of the channel name */ 02538 ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name); 02539 /* Make formats okay */ 02540 chan->readformat = rchan->readformat; 02541 chan->writeformat = rchan->writeformat; 02542 ast_channel_masquerade(chan, rchan); 02543 /* Setup the extensions and such */ 02544 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1); 02545 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1); 02546 chan->priority = rchan->priority; 02547 /* might be dirty but we want trackable channels */ 02548 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid); 02549 /* Make the masq execute */ 02550 f = ast_read(chan); 02551 if (f) 02552 ast_frfree(f); 02553 ast_autoanswer_login(chan, data); 02554 } else { 02555 ast_log(LOG_WARNING, "Unable to create aa channel\n"); 02556 return -1; 02557 } 02558 return 0; 02559 }
int ast_masq_hold_call | ( | struct ast_channel * | rchan, | |
struct ast_channel * | host | |||
) |
Definition at line 2076 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.
02077 { 02078 struct ast_channel *chan; 02079 struct ast_frame *f; 02080 /* Make a new, fake channel that we'll use to masquerade in the real one */ 02081 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name); 02082 if (chan) { 02083 /* Let us keep track of the channel name */ 02084 ast_string_field_build(chan, name, "Onhold/%s",rchan->name); 02085 /* Make formats okay */ 02086 chan->readformat = rchan->readformat; 02087 chan->writeformat = rchan->writeformat; 02088 ast_channel_masquerade(chan, rchan); 02089 /* Setup the extensions and such */ 02090 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1); 02091 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1); 02092 chan->priority = rchan->priority; 02093 /* this might be dirty, but we need to preserve the uniqueid */ 02094 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid); 02095 /* Make the masq execute */ 02096 f = ast_read(chan); 02097 if (f) 02098 ast_frfree(f); 02099 ast_hold_call(chan, peer); 02100 return -1; 02101 } else { 02102 ast_log(LOG_WARNING, "Unable to create holded channel\n"); 02103 return -1; 02104 } 02105 return 0; 02106 }
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 512 of file res_features.c.
References ast_channel::amaflags, ast_channel_alloc(), ast_channel_masquerade(), ast_frfree, ast_log(), ast_park_call(), ast_read(), AST_STATE_DOWN, ast_channel::context, ast_channel::exten, f, LOG_WARNING, 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().
00513 { 00514 struct ast_channel *chan; 00515 struct ast_frame *f; 00516 00517 /* Make a new, fake channel that we'll use to masquerade in the real one */ 00518 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) { 00519 ast_log(LOG_WARNING, "Unable to create parked channel\n"); 00520 return -1; 00521 } 00522 00523 /* Make formats okay */ 00524 chan->readformat = rchan->readformat; 00525 chan->writeformat = rchan->writeformat; 00526 ast_channel_masquerade(chan, rchan); 00527 00528 /* Setup the extensions and such */ 00529 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority); 00530 00531 /* Make the masq execute */ 00532 f = ast_read(chan); 00533 if (f) 00534 ast_frfree(f); 00535 00536 ast_park_call(chan, peer, timeout, extout); 00537 return 0; 00538 }
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 507 of file res_features.c.
References park_call_full().
Referenced by ast_masq_park_call(), builtin_blindtransfer(), builtin_parkcall(), iax_park_thread(), and sip_park_thread().
00508 { 00509 return park_call_full(chan, peer, timeout, extout, NULL); 00510 }
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 214 of file res_features.c.
Referenced by builtin_blindtransfer(), dp_lookup(), handle_request_refer(), load_config(), mgcp_ss(), socket_process(), and ss_thread().
00215 { 00216 return parking_ext; 00217 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 2918 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().
02919 { 02920 struct ast_channel *cur = NULL; 02921 int res = -1; 02922 02923 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 02924 if (!cur->pbx && 02925 (cur != chan) && 02926 (chan->pickupgroup & cur->callgroup) && 02927 ((cur->_state == AST_STATE_RINGING) || 02928 (cur->_state == AST_STATE_RING))) { 02929 break; 02930 } 02931 ast_channel_unlock(cur); 02932 } 02933 if (cur) { 02934 if (option_debug) 02935 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 02936 res = ast_answer(chan); 02937 if (res) 02938 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 02939 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 02940 if (res) 02941 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 02942 res = ast_channel_masquerade(cur, chan); 02943 if (res) 02944 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 02945 ast_channel_unlock(cur); 02946 } else { 02947 if (option_debug) 02948 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 02949 } 02950 return res; 02951 }
char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 219 of file res_features.c.
Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().
00220 { 00221 return pickup_ext; 00222 }
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 975 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().
00976 { 00977 if (!feature) { 00978 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 00979 return; 00980 } 00981 00982 AST_LIST_LOCK(&feature_list); 00983 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry); 00984 AST_LIST_UNLOCK(&feature_list); 00985 00986 if (option_verbose >= 2) 00987 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 00988 }
int ast_retrieve_call | ( | struct ast_channel * | chan, | |
char * | uniqueid | |||
) |
Definition at line 2108 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().
02109 { 02110 int res=-1, dres=-1; 02111 struct ast_channel *peer=NULL; 02112 struct ast_bridge_config config; 02113 02114 peer = ast_get_holded_call(uniqueid); 02115 02116 /* JK02: it helps to answer the channel if not already up */ 02117 if (chan->_state != AST_STATE_UP) { 02118 ast_answer(chan); 02119 } 02120 02121 if (peer) { 02122 ast_mutex_unlock(&peer->lock); 02123 ast_moh_stop(peer); 02124 res = ast_channel_make_compatible(chan, peer); 02125 if (res < 0) { 02126 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name); 02127 ast_hangup(peer); 02128 return -1; 02129 } 02130 /* This runs sorta backwards, since we give the incoming channel control, as if it 02131 were the person called. */ 02132 if (option_verbose > 2) 02133 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name); 02134 02135 memset(&config,0,sizeof(struct ast_bridge_config)); 02136 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 02137 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT); 02138 config.timelimit = 0; 02139 config.play_warning = 0; 02140 config.warning_freq = 0; 02141 config.warning_sound=NULL; 02142 res = ast_bridge_call(chan,peer,&config); 02143 02144 /* Simulate the PBX hanging up */ 02145 if (res != AST_PBX_NO_HANGUP_PEER) 02146 ast_hangup(peer); 02147 return res; 02148 } else { 02149 /* XXX Play a message XXX */ 02150 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language); 02151 if (!dres) 02152 dres = ast_waitstream(chan, ""); 02153 else { 02154 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name); 02155 dres = 0; 02156 } 02157 } 02158 return res; 02159 }
int ast_retrieve_call_to_death | ( | char * | uniqueid | ) |
Definition at line 2161 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.
02162 { 02163 int res=-1; 02164 struct ast_channel *peer=NULL; 02165 02166 peer = ast_get_holded_call(uniqueid); 02167 02168 if (peer) { 02169 res=0; 02170 if (option_verbose > 2) 02171 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name); 02172 ast_mutex_unlock(&peer->lock); 02173 ast_hangup(peer); 02174 } else { 02175 ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid); 02176 } 02177 return res; 02178 }
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 991 of file res_features.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.
00992 { 00993 if (!feature) 00994 return; 00995 00996 AST_LIST_LOCK(&feature_list); 00997 AST_LIST_REMOVE(&feature_list,feature,feature_entry); 00998 AST_LIST_UNLOCK(&feature_list); 00999 free(feature); 01000 }