#include "asterisk/pbx.h"
#include "asterisk/linkedlists.h"
Go to the source code of this file.
Data Structures | |
struct | ast_call_feature |
Defines | |
#define | AST_FEATURE_RETURN_HANGUP -1 |
#define | AST_FEATURE_RETURN_KEEPTRYING 24 |
#define | AST_FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER |
#define | AST_FEATURE_RETURN_PARKFAILED 25 |
#define | AST_FEATURE_RETURN_PASSDIGITS 21 |
#define | AST_FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE |
#define | AST_FEATURE_RETURN_STOREDIGITS 22 |
#define | AST_FEATURE_RETURN_SUCCESS 23 |
#define | AST_FEATURE_RETURN_SUCCESSBREAK 0 |
#define | DEFAULT_PARKINGLOT "default" |
#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_SENSE_CHAN (1 << 0) |
#define | FEATURE_SENSE_PEER (1 << 1) |
#define | FEATURE_SNAME_LEN 32 |
#define | PARK_APP_NAME "Park" |
Typedefs | |
typedef int(*) | ast_feature_operation (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data) |
Enumerations | |
enum | { AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0), AST_FEATURE_FLAG_ONPEER = (1 << 1), AST_FEATURE_FLAG_ONSELF = (1 << 2), AST_FEATURE_FLAG_BYCALLEE = (1 << 3), AST_FEATURE_FLAG_BYCALLER = (1 << 4), AST_FEATURE_FLAG_BYBOTH = (3 << 3) } |
main call feature structure More... | |
Functions | |
int | ast_bridge_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config) |
Bridge a call, optionally allowing redirection. | |
int | ast_bridge_timelimit (struct ast_channel *chan, struct ast_bridge_config *config, char *parse, struct timeval *calldurationlimit) |
parse L option and read associated channel variables to set warning, warning frequency, and timelimit | |
int | ast_feature_detect (struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) |
detect a feature before bridging | |
int | ast_features_reload (void) |
Reload call features from features.conf. | |
ast_call_feature * | ast_find_call_feature (const char *name) |
look for a call feature entry by its sname | |
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, const char *parkexten, int *extout) |
Park a call and read back parked location. | |
int | ast_parking_ext_valid (const char *exten_str, struct ast_channel *chan, const char *context) |
Determine if parking extension exists in a given context. | |
int | ast_pickup_call (struct ast_channel *chan) |
Pickup a call. | |
const char * | ast_pickup_ext (void) |
Determine system call pickup extension. | |
void | ast_rdlock_call_features (void) |
void | ast_register_feature (struct ast_call_feature *feature) |
register new feature into feature_set | |
void | ast_unlock_call_features (void) |
void | ast_unregister_feature (struct ast_call_feature *feature) |
unregister feature from feature_set |
Definition in file features.h.
#define AST_FEATURE_RETURN_HANGUP -1 |
#define AST_FEATURE_RETURN_KEEPTRYING 24 |
Definition at line 47 of file features.h.
Referenced by feature_exec_app(), and feature_interpret_helper().
#define AST_FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER |
Definition at line 43 of file features.h.
#define AST_FEATURE_RETURN_PARKFAILED 25 |
Definition at line 48 of file features.h.
Referenced by builtin_blindtransfer(), and masq_park_call().
#define AST_FEATURE_RETURN_PASSDIGITS 21 |
Definition at line 44 of file features.h.
Referenced by ast_bridge_call(), and feature_interpret_helper().
#define AST_FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE |
Definition at line 42 of file features.h.
#define AST_FEATURE_RETURN_STOREDIGITS 22 |
Definition at line 45 of file features.h.
Referenced by detect_disconnect(), and feature_interpret_helper().
#define AST_FEATURE_RETURN_SUCCESS 23 |
Definition at line 46 of file features.h.
Referenced by ast_bridge_call(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), and feature_exec_app().
#define AST_FEATURE_RETURN_SUCCESSBREAK 0 |
#define DEFAULT_PARKINGLOT "default" |
#define FEATURE_APP_ARGS_LEN 256 |
Definition at line 32 of file features.h.
#define FEATURE_APP_LEN 64 |
Definition at line 31 of file features.h.
#define FEATURE_EXTEN_LEN 32 |
Definition at line 34 of file features.h.
#define FEATURE_MAX_LEN 11 |
#define FEATURE_MOH_LEN 80 |
Definition at line 35 of file features.h.
#define FEATURE_SENSE_CHAN (1 << 0) |
Definition at line 50 of file features.h.
Referenced by ast_bridge_call(), feature_exec_app(), and feature_interpret().
#define FEATURE_SENSE_PEER (1 << 1) |
#define FEATURE_SNAME_LEN 32 |
Definition at line 33 of file features.h.
#define PARK_APP_NAME "Park" |
typedef int(*) ast_feature_operation(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data) |
Definition at line 53 of file features.h.
anonymous enum |
main call feature structure
AST_FEATURE_FLAG_NEEDSDTMF | |
AST_FEATURE_FLAG_ONPEER | |
AST_FEATURE_FLAG_ONSELF | |
AST_FEATURE_FLAG_BYCALLEE | |
AST_FEATURE_FLAG_BYCALLER | |
AST_FEATURE_FLAG_BYBOTH |
Definition at line 57 of file features.h.
00057 { 00058 AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0), 00059 AST_FEATURE_FLAG_ONPEER = (1 << 1), 00060 AST_FEATURE_FLAG_ONSELF = (1 << 2), 00061 AST_FEATURE_FLAG_BYCALLEE = (1 << 3), 00062 AST_FEATURE_FLAG_BYCALLER = (1 << 4), 00063 AST_FEATURE_FLAG_BYBOTH = (3 << 3), 00064 };
int ast_bridge_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | peer, | |||
struct ast_bridge_config * | config | |||
) |
Bridge a call, optionally allowing redirection.
chan,peer,config | Set start time, check for two channels,check if monitor on check for feature activation, create new CDR |
res | on success. | |
-1 | on failure to bridge. |
append the event to featurecode. we rely on the string being zero-filled, and not overflowing it.
Definition at line 3395 of file features.c.
References ast_channel::_state, ast_channel::accountcode, ast_cdr::accountcode, add_features_datastores(), ast_cdr::amaflags, ast_channel::amaflags, ast_cdr::answer, ast_channel::appl, AST_BRIDGE_RETRY, ast_bridged_channel(), ast_cdr_alloc(), ast_cdr_answer(), AST_CDR_ANSWERED, ast_cdr_appenduserfield(), ast_cdr_detach(), ast_cdr_discard(), ast_cdr_dup_unique_swap(), ast_cdr_end(), AST_CDR_FLAG_BRIDGED, AST_CDR_FLAG_DIALED, AST_CDR_FLAG_MAIN, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NULL, ast_cdr_setaccount(), ast_cdr_setanswer(), ast_cdr_setcid(), ast_cdr_setdisposition(), ast_cdr_setuserfield(), ast_cdr_specialized_reset(), ast_cdr_start(), ast_cdr_update(), AST_CEL_BRIDGE_END, AST_CEL_BRIDGE_START, ast_cel_report_event(), ast_channel_bridge(), ast_channel_connected_line_macro(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_log(), ast_channel_redirecting_macro(), ast_channel_set_linkgroup(), ast_channel_setoption(), ast_channel_unlock, ast_channel_unref, ast_check_hangup(), ast_clear_flag, AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OPTION, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_default_amaflags, ast_dtmf_stream(), ast_exists_extension(), AST_FEATURE_NO_H_EXTEN, AST_FEATURE_RETURN_PASSDIGITS, AST_FEATURE_RETURN_SUCCESS, AST_FEATURE_WARNING_ACTIVE, AST_FLAG_BRIDGE_HANGUP_DONT, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frfree, ast_indicate(), ast_indicate_data(), ast_log(), ast_opt_end_cdr_before_h_exten, AST_OPTION_AUDIO_MODE, AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, AST_OPTION_FLAG_REQUEST, AST_OPTION_RELAXDTMF, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_raw_answer(), ast_set2_flag, ast_set_flag, ast_spawn_extension(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_verb, ast_channel::caller, ast_channel::cdr, ast_cdr::channel, config, ast_channel::context, ast_channel::data, ast_option_header::data, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_channel::exten, f, feature_interpret(), FEATURE_MAX_LEN, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, featuredigittimeout, ast_party_caller::id, ast_cdr::lastapp, ast_cdr::lastdata, LOG_WARNING, monitor_app, monitor_ok, ast_channel::name, ast_cdr::next, ast_party_id::number, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), pick_unlocked_cdr(), ast_channel::priority, S_COR, S_OR, set_bridge_features_on_config(), set_config_flags(), ast_cdr::start, ast_party_number::str, ast_cdr::uniqueid, ast_channel::uniqueid, ast_cdr::userfield, ast_party_number::valid, and ast_channel::visible_indication.
Referenced by app_exec(), bridge_call_thread(), bridge_exec(), builtin_atxfer(), dial_exec_full(), and park_exec_full().
03396 { 03397 /* Copy voice back and forth between the two channels. Give the peer 03398 the ability to transfer calls with '#<extension' syntax. */ 03399 struct ast_frame *f; 03400 struct ast_channel *who; 03401 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 03402 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 03403 char orig_channame[AST_MAX_EXTENSION]; 03404 char orig_peername[AST_MAX_EXTENSION]; 03405 int res; 03406 int diff; 03407 int hasfeatures=0; 03408 int hadfeatures=0; 03409 int autoloopflag; 03410 int we_disabled_peer_cdr = 0; 03411 struct ast_option_header *aoh; 03412 struct ast_cdr *bridge_cdr = NULL; 03413 struct ast_cdr *orig_peer_cdr = NULL; 03414 struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */ 03415 struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */ 03416 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 03417 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 03418 03419 if (chan && peer) { 03420 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 03421 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 03422 } else if (chan) { 03423 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 03424 } 03425 03426 set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES")); 03427 add_features_datastores(chan, peer, config); 03428 03429 /* This is an interesting case. One example is if a ringing channel gets redirected to 03430 * an extension that picks up a parked call. This will make sure that the call taken 03431 * out of parking gets told that the channel it just got bridged to is still ringing. */ 03432 if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) { 03433 ast_indicate(peer, AST_CONTROL_RINGING); 03434 } 03435 03436 if (monitor_ok) { 03437 const char *monitor_exec; 03438 struct ast_channel *src = NULL; 03439 if (!monitor_app) { 03440 if (!(monitor_app = pbx_findapp("Monitor"))) 03441 monitor_ok=0; 03442 } 03443 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 03444 src = chan; 03445 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 03446 src = peer; 03447 if (monitor_app && src) { 03448 char *tmp = ast_strdupa(monitor_exec); 03449 pbx_exec(src, monitor_app, tmp); 03450 } 03451 } 03452 03453 set_config_flags(chan, peer, config); 03454 03455 /* Answer if need be */ 03456 if (chan->_state != AST_STATE_UP) { 03457 if (ast_raw_answer(chan, 1)) { 03458 return -1; 03459 } 03460 } 03461 03462 #ifdef FOR_DEBUG 03463 /* show the two channels and cdrs involved in the bridge for debug & devel purposes */ 03464 ast_channel_log("Pre-bridge CHAN Channel info", chan); 03465 ast_channel_log("Pre-bridge PEER Channel info", peer); 03466 #endif 03467 /* two channels are being marked as linked here */ 03468 ast_channel_set_linkgroup(chan,peer); 03469 03470 /* copy the userfield from the B-leg to A-leg if applicable */ 03471 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) { 03472 char tmp[256]; 03473 if (!ast_strlen_zero(chan->cdr->userfield)) { 03474 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield); 03475 ast_cdr_appenduserfield(chan, tmp); 03476 } else 03477 ast_cdr_setuserfield(chan, peer->cdr->userfield); 03478 /* Don't delete the CDR; just disable it. */ 03479 ast_set_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED); 03480 we_disabled_peer_cdr = 1; 03481 } 03482 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame)); 03483 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername)); 03484 orig_peer_cdr = peer_cdr; 03485 03486 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) { 03487 03488 if (chan_cdr) { 03489 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); 03490 ast_cdr_update(chan); 03491 bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr); 03492 /* rip any forked CDR's off of the chan_cdr and attach 03493 * them to the bridge_cdr instead */ 03494 bridge_cdr->next = chan_cdr->next; 03495 chan_cdr->next = NULL; 03496 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 03497 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 03498 if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) { 03499 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 03500 } 03501 ast_cdr_setaccount(peer, chan->accountcode); 03502 03503 } else { 03504 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */ 03505 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */ 03506 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel)); 03507 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel)); 03508 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid)); 03509 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 03510 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 03511 ast_cdr_setcid(bridge_cdr, chan); 03512 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL; 03513 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags; 03514 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode)); 03515 /* Destination information */ 03516 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst)); 03517 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext)); 03518 if (peer_cdr) { 03519 bridge_cdr->start = peer_cdr->start; 03520 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 03521 } else { 03522 ast_cdr_start(bridge_cdr); 03523 } 03524 } 03525 ast_debug(4,"bridge answer set, chan answer set\n"); 03526 /* peer_cdr->answer will be set when a macro runs on the peer; 03527 in that case, the bridge answer will be delayed while the 03528 macro plays on the peer channel. The peer answered the call 03529 before the macro started playing. To the phone system, 03530 this is billable time for the call, even tho the caller 03531 hears nothing but ringing while the macro does its thing. */ 03532 03533 /* Another case where the peer cdr's time will be set, is when 03534 A self-parks by pickup up phone and dialing 700, then B 03535 picks up A by dialing its parking slot; there may be more 03536 practical paths that get the same result, tho... in which 03537 case you get the previous answer time from the Park... which 03538 is before the bridge's start time, so I added in the 03539 tvcmp check to the if below */ 03540 03541 if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) { 03542 ast_cdr_setanswer(bridge_cdr, peer_cdr->answer); 03543 ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition); 03544 if (chan_cdr) { 03545 ast_cdr_setanswer(chan_cdr, peer_cdr->answer); 03546 ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition); 03547 } 03548 } else { 03549 ast_cdr_answer(bridge_cdr); 03550 if (chan_cdr) { 03551 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */ 03552 } 03553 } 03554 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) { 03555 if (chan_cdr) { 03556 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED); 03557 } 03558 if (peer_cdr) { 03559 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED); 03560 } 03561 } 03562 /* the DIALED flag may be set if a dialed channel is transfered 03563 * and then bridged to another channel. In order for the 03564 * bridge CDR to be written, the DIALED flag must not be 03565 * present. */ 03566 ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED); 03567 } 03568 ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, NULL); 03569 for (;;) { 03570 struct ast_channel *other; /* used later */ 03571 03572 res = ast_channel_bridge(chan, peer, config, &f, &who); 03573 03574 /* When frame is not set, we are probably involved in a situation 03575 where we've timed out. 03576 When frame is set, we'll come this code twice; once for DTMF_BEGIN 03577 and also for DTMF_END. If we flow into the following 'if' for both, then 03578 our wait times are cut in half, as both will subtract from the 03579 feature_timer. Not good! 03580 */ 03581 if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) { 03582 /* Update feature timer for next pass */ 03583 diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time); 03584 if (res == AST_BRIDGE_RETRY) { 03585 /* The feature fully timed out but has not been updated. Skip 03586 * the potential round error from the diff calculation and 03587 * explicitly set to expired. */ 03588 config->feature_timer = -1; 03589 } else { 03590 config->feature_timer -= diff; 03591 } 03592 03593 if (hasfeatures) { 03594 if (config->feature_timer <= 0) { 03595 /* Not *really* out of time, just out of time for 03596 digits to come in for features. */ 03597 ast_debug(1, "Timed out for feature!\n"); 03598 if (!ast_strlen_zero(peer_featurecode)) { 03599 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0); 03600 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 03601 } 03602 if (!ast_strlen_zero(chan_featurecode)) { 03603 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0); 03604 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 03605 } 03606 if (f) 03607 ast_frfree(f); 03608 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 03609 if (!hasfeatures) { 03610 /* No more digits expected - reset the timer */ 03611 config->feature_timer = 0; 03612 } 03613 hadfeatures = hasfeatures; 03614 /* Continue as we were */ 03615 continue; 03616 } else if (!f) { 03617 /* The bridge returned without a frame and there is a feature in progress. 03618 * However, we don't think the feature has quite yet timed out, so just 03619 * go back into the bridge. */ 03620 continue; 03621 } 03622 } else { 03623 if (config->feature_timer <=0) { 03624 /* We ran out of time */ 03625 config->feature_timer = 0; 03626 who = chan; 03627 if (f) 03628 ast_frfree(f); 03629 f = NULL; 03630 res = 0; 03631 } 03632 } 03633 } 03634 if (res < 0) { 03635 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) { 03636 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 03637 } 03638 goto before_you_go; 03639 } 03640 03641 if (!f || (f->frametype == AST_FRAME_CONTROL && 03642 (f->subclass.integer == AST_CONTROL_HANGUP || f->subclass.integer == AST_CONTROL_BUSY || 03643 f->subclass.integer == AST_CONTROL_CONGESTION))) { 03644 res = -1; 03645 break; 03646 } 03647 /* many things should be sent to the 'other' channel */ 03648 other = (who == chan) ? peer : chan; 03649 if (f->frametype == AST_FRAME_CONTROL) { 03650 switch (f->subclass.integer) { 03651 case AST_CONTROL_RINGING: 03652 case AST_CONTROL_FLASH: 03653 case -1: 03654 ast_indicate(other, f->subclass.integer); 03655 break; 03656 case AST_CONTROL_CONNECTED_LINE: 03657 if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) { 03658 break; 03659 } 03660 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 03661 break; 03662 case AST_CONTROL_REDIRECTING: 03663 if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) { 03664 break; 03665 } 03666 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 03667 break; 03668 case AST_CONTROL_AOC: 03669 case AST_CONTROL_HOLD: 03670 case AST_CONTROL_UNHOLD: 03671 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 03672 break; 03673 case AST_CONTROL_OPTION: 03674 aoh = f->data.ptr; 03675 /* Forward option Requests, but only ones we know are safe 03676 * These are ONLY sent by chan_iax2 and I'm not convinced that 03677 * they are useful. I haven't deleted them entirely because I 03678 * just am not sure of the ramifications of removing them. */ 03679 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 03680 switch (ntohs(aoh->option)) { 03681 case AST_OPTION_TONE_VERIFY: 03682 case AST_OPTION_TDD: 03683 case AST_OPTION_RELAXDTMF: 03684 case AST_OPTION_AUDIO_MODE: 03685 case AST_OPTION_DIGIT_DETECT: 03686 case AST_OPTION_FAX_DETECT: 03687 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 03688 f->datalen - sizeof(struct ast_option_header), 0); 03689 } 03690 } 03691 break; 03692 } 03693 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 03694 /* eat it */ 03695 } else if (f->frametype == AST_FRAME_DTMF) { 03696 char *featurecode; 03697 int sense; 03698 03699 hadfeatures = hasfeatures; 03700 /* This cannot overrun because the longest feature is one shorter than our buffer */ 03701 if (who == chan) { 03702 sense = FEATURE_SENSE_CHAN; 03703 featurecode = chan_featurecode; 03704 } else { 03705 sense = FEATURE_SENSE_PEER; 03706 featurecode = peer_featurecode; 03707 } 03708 /*! append the event to featurecode. we rely on the string being zero-filled, and 03709 * not overflowing it. 03710 * \todo XXX how do we guarantee the latter ? 03711 */ 03712 featurecode[strlen(featurecode)] = f->subclass.integer; 03713 /* Get rid of the frame before we start doing "stuff" with the channels */ 03714 ast_frfree(f); 03715 f = NULL; 03716 config->feature_timer = 0; 03717 res = feature_interpret(chan, peer, config, featurecode, sense); 03718 switch(res) { 03719 case AST_FEATURE_RETURN_PASSDIGITS: 03720 ast_dtmf_stream(other, who, featurecode, 0, 0); 03721 /* Fall through */ 03722 case AST_FEATURE_RETURN_SUCCESS: 03723 memset(featurecode, 0, sizeof(chan_featurecode)); 03724 break; 03725 } 03726 if (res >= AST_FEATURE_RETURN_PASSDIGITS) { 03727 res = 0; 03728 } else { 03729 break; 03730 } 03731 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 03732 if (hadfeatures && !hasfeatures) { 03733 /* Feature completed or timed out */ 03734 config->feature_timer = 0; 03735 } else if (hasfeatures) { 03736 if (config->timelimit) { 03737 /* No warning next time - we are waiting for future */ 03738 ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE); 03739 } 03740 config->feature_start_time = ast_tvnow(); 03741 config->feature_timer = featuredigittimeout; 03742 ast_debug(1, "Set feature timer to %ld ms\n", config->feature_timer); 03743 } 03744 } 03745 if (f) 03746 ast_frfree(f); 03747 03748 } 03749 ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, NULL); 03750 before_you_go: 03751 03752 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) { 03753 ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */ 03754 if (bridge_cdr) { 03755 ast_cdr_discard(bridge_cdr); 03756 /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */ 03757 } 03758 return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */ 03759 } 03760 03761 if (config->end_bridge_callback) { 03762 config->end_bridge_callback(config->end_bridge_callback_data); 03763 } 03764 03765 /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation 03766 * if it were, then chan belongs to a different thread now, and might have been hung up long 03767 * ago. 03768 */ 03769 if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) 03770 && ast_exists_extension(chan, chan->context, "h", 1, 03771 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 03772 struct ast_cdr *swapper = NULL; 03773 char savelastapp[AST_MAX_EXTENSION]; 03774 char savelastdata[AST_MAX_EXTENSION]; 03775 char save_exten[AST_MAX_EXTENSION]; 03776 int save_prio; 03777 int found = 0; /* set if we find at least one match */ 03778 int spawn_error = 0; 03779 03780 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); 03781 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); 03782 if (bridge_cdr && ast_opt_end_cdr_before_h_exten) { 03783 ast_cdr_end(bridge_cdr); 03784 } 03785 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge 03786 dialplan code operate on it */ 03787 ast_channel_lock(chan); 03788 if (bridge_cdr) { 03789 swapper = chan->cdr; 03790 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp)); 03791 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata)); 03792 chan->cdr = bridge_cdr; 03793 } 03794 ast_copy_string(save_exten, chan->exten, sizeof(save_exten)); 03795 save_prio = chan->priority; 03796 ast_copy_string(chan->exten, "h", sizeof(chan->exten)); 03797 chan->priority = 1; 03798 ast_channel_unlock(chan); 03799 while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, 03800 chan->priority, 03801 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL), 03802 &found, 1)) == 0) { 03803 chan->priority++; 03804 } 03805 if (spawn_error 03806 && (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, 03807 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 03808 || ast_check_hangup(chan))) { 03809 /* if the extension doesn't exist or a hangup occurred, this isn't really a spawn error */ 03810 spawn_error = 0; 03811 } 03812 if (found && spawn_error) { 03813 /* Something bad happened, or a hangup has been requested. */ 03814 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 03815 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 03816 } 03817 /* swap it back */ 03818 ast_channel_lock(chan); 03819 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten)); 03820 chan->priority = save_prio; 03821 if (bridge_cdr) { 03822 if (chan->cdr == bridge_cdr) { 03823 chan->cdr = swapper; 03824 } else { 03825 bridge_cdr = NULL; 03826 } 03827 } 03828 if (!spawn_error) { 03829 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN); 03830 } 03831 ast_channel_unlock(chan); 03832 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */ 03833 if (bridge_cdr) { 03834 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp)); 03835 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata)); 03836 } 03837 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); 03838 } 03839 03840 /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */ 03841 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 03842 if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) 03843 ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED); 03844 03845 /* we can post the bridge CDR at this point */ 03846 if (bridge_cdr) { 03847 ast_cdr_end(bridge_cdr); 03848 ast_cdr_detach(bridge_cdr); 03849 } 03850 03851 /* do a specialized reset on the beginning channel 03852 CDR's, if they still exist, so as not to mess up 03853 issues in future bridges; 03854 03855 Here are the rules of the game: 03856 1. The chan and peer channel pointers will not change 03857 during the life of the bridge. 03858 2. But, in transfers, the channel names will change. 03859 between the time the bridge is started, and the 03860 time the channel ends. 03861 Usually, when a channel changes names, it will 03862 also change CDR pointers. 03863 3. Usually, only one of the two channels (chan or peer) 03864 will change names. 03865 4. Usually, if a channel changes names during a bridge, 03866 it is because of a transfer. Usually, in these situations, 03867 it is normal to see 2 bridges running simultaneously, and 03868 it is not unusual to see the two channels that change 03869 swapped between bridges. 03870 5. After a bridge occurs, we have 2 or 3 channels' CDRs 03871 to attend to; if the chan or peer changed names, 03872 we have the before and after attached CDR's. 03873 */ 03874 03875 if (new_chan_cdr) { 03876 struct ast_channel *chan_ptr = NULL; 03877 03878 if (strcasecmp(orig_channame, chan->name) != 0) { 03879 /* old channel */ 03880 if ((chan_ptr = ast_channel_get_by_name(orig_channame))) { 03881 ast_channel_lock(chan_ptr); 03882 if (!ast_bridged_channel(chan_ptr)) { 03883 struct ast_cdr *cur; 03884 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 03885 if (cur == chan_cdr) { 03886 break; 03887 } 03888 } 03889 if (cur) { 03890 ast_cdr_specialized_reset(chan_cdr, 0); 03891 } 03892 } 03893 ast_channel_unlock(chan_ptr); 03894 chan_ptr = ast_channel_unref(chan_ptr); 03895 } 03896 /* new channel */ 03897 ast_cdr_specialized_reset(new_chan_cdr, 0); 03898 } else { 03899 ast_cdr_specialized_reset(chan->cdr, 0); /* nothing changed, reset the chan cdr */ 03900 } 03901 } 03902 03903 { 03904 struct ast_channel *chan_ptr = NULL; 03905 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 03906 if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED)) 03907 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */ 03908 if (strcasecmp(orig_peername, peer->name) != 0) { 03909 /* old channel */ 03910 if ((chan_ptr = ast_channel_get_by_name(orig_peername))) { 03911 ast_channel_lock(chan_ptr); 03912 if (!ast_bridged_channel(chan_ptr)) { 03913 struct ast_cdr *cur; 03914 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 03915 if (cur == peer_cdr) { 03916 break; 03917 } 03918 } 03919 if (cur) { 03920 ast_cdr_specialized_reset(peer_cdr, 0); 03921 } 03922 } 03923 ast_channel_unlock(chan_ptr); 03924 chan_ptr = ast_channel_unref(chan_ptr); 03925 } 03926 /* new channel */ 03927 if (new_peer_cdr) { 03928 ast_cdr_specialized_reset(new_peer_cdr, 0); 03929 } 03930 } else { 03931 if (we_disabled_peer_cdr) { 03932 ast_clear_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED); 03933 } 03934 ast_cdr_specialized_reset(peer->cdr, 0); /* nothing changed, reset the peer cdr */ 03935 } 03936 } 03937 03938 return res; 03939 }
int ast_bridge_timelimit | ( | struct ast_channel * | chan, | |
struct ast_bridge_config * | config, | |||
char * | parse, | |||
struct timeval * | calldurationlimit | |||
) |
parse L option and read associated channel variables to set warning, warning frequency, and timelimit
Definition at line 5700 of file features.c.
References ast_channel_lock, ast_channel_unlock, AST_FEATURE_PLAY_WARNING, ast_log(), ast_set_flag, ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_verb, config, LOG_WARNING, pbx_builtin_getvar_helper(), S_OR, strsep(), and var.
Referenced by bridge_exec(), and dial_exec_full().
05702 { 05703 char *stringp = ast_strdupa(parse); 05704 char *limit_str, *warning_str, *warnfreq_str; 05705 const char *var; 05706 int play_to_caller = 0, play_to_callee = 0; 05707 int delta; 05708 05709 limit_str = strsep(&stringp, ":"); 05710 warning_str = strsep(&stringp, ":"); 05711 warnfreq_str = strsep(&stringp, ":"); 05712 05713 config->timelimit = atol(limit_str); 05714 if (warning_str) 05715 config->play_warning = atol(warning_str); 05716 if (warnfreq_str) 05717 config->warning_freq = atol(warnfreq_str); 05718 05719 if (!config->timelimit) { 05720 ast_log(LOG_WARNING, "Bridge does not accept L(%s), hanging up.\n", limit_str); 05721 config->timelimit = config->play_warning = config->warning_freq = 0; 05722 config->warning_sound = NULL; 05723 return -1; /* error */ 05724 } else if ( (delta = config->play_warning - config->timelimit) > 0) { 05725 int w = config->warning_freq; 05726 05727 /* If the first warning is requested _after_ the entire call would end, 05728 and no warning frequency is requested, then turn off the warning. If 05729 a warning frequency is requested, reduce the 'first warning' time by 05730 that frequency until it falls within the call's total time limit. 05731 Graphically: 05732 timelim->| delta |<-playwarning 05733 0__________________|_________________| 05734 | w | | | | 05735 05736 so the number of intervals to cut is 1+(delta-1)/w 05737 */ 05738 05739 if (w == 0) { 05740 config->play_warning = 0; 05741 } else { 05742 config->play_warning -= w * ( 1 + (delta-1)/w ); 05743 if (config->play_warning < 1) 05744 config->play_warning = config->warning_freq = 0; 05745 } 05746 } 05747 05748 ast_channel_lock(chan); 05749 05750 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER"); 05751 play_to_caller = var ? ast_true(var) : 1; 05752 05753 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE"); 05754 play_to_callee = var ? ast_true(var) : 0; 05755 05756 if (!play_to_caller && !play_to_callee) 05757 play_to_caller = 1; 05758 05759 var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE"); 05760 config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft"); 05761 05762 /* The code looking at config wants a NULL, not just "", to decide 05763 * that the message should not be played, so we replace "" with NULL. 05764 * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is 05765 * not found. 05766 */ 05767 05768 var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE"); 05769 config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL; 05770 05771 var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE"); 05772 config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL; 05773 05774 ast_channel_unlock(chan); 05775 05776 /* undo effect of S(x) in case they are both used */ 05777 calldurationlimit->tv_sec = 0; 05778 calldurationlimit->tv_usec = 0; 05779 05780 /* more efficient to do it like S(x) does since no advanced opts */ 05781 if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) { 05782 calldurationlimit->tv_sec = config->timelimit / 1000; 05783 calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000; 05784 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n", 05785 calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0); 05786 config->timelimit = play_to_caller = play_to_callee = 05787 config->play_warning = config->warning_freq = 0; 05788 } else { 05789 ast_verb(4, "Limit Data for this call:\n"); 05790 ast_verb(4, "timelimit = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0); 05791 ast_verb(4, "play_warning = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0); 05792 ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no"); 05793 ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no"); 05794 ast_verb(4, "warning_freq = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0); 05795 ast_verb(4, "start_sound = %s\n", S_OR(config->start_sound, "")); 05796 ast_verb(4, "warning_sound = %s\n", config->warning_sound); 05797 ast_verb(4, "end_sound = %s\n", S_OR(config->end_sound, "")); 05798 } 05799 if (play_to_caller) 05800 ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 05801 if (play_to_callee) 05802 ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 05803 return 0; 05804 }
int ast_feature_detect | ( | struct ast_channel * | chan, | |
struct ast_flags * | features, | |||
const char * | code, | |||
struct ast_call_feature * | feature | |||
) |
detect a feature before bridging
chan | ||
features | an ast_flags ptr | |
code | ptr of input code | |
feature |
ast_call_feature | ptr to be set if found |
Definition at line 2881 of file features.c.
References feature_group_exten::feature, and feature_interpret_helper().
Referenced by detect_disconnect().
02881 { 02882 02883 return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature); 02884 }
int ast_features_reload | ( | void | ) |
Reload call features from features.conf.
Definition at line 5198 of file features.c.
References ao2_t_callback, load_config(), OBJ_NODATA, OBJ_UNLINK, parkinglot_is_marked_cb(), parkinglot_markall_cb(), and parkinglots.
Referenced by handle_features_reload().
05199 { 05200 int res; 05201 05202 ao2_t_callback(parkinglots, OBJ_NODATA, parkinglot_markall_cb, NULL, "callback to mark all parkinglots"); 05203 res = load_config(); /* Reload configuration */ 05204 ao2_t_callback(parkinglots, OBJ_NODATA | OBJ_UNLINK, parkinglot_is_marked_cb, NULL, "callback to remove all marked parkinglots"); 05205 05206 return res; 05207 }
struct ast_call_feature* ast_find_call_feature | ( | const char * | name | ) |
look for a call feature entry by its sname
name | a string ptr, should match "automon", "blindxfer", "atxfer", etc. |
Definition at line 2623 of file features.c.
References builtin_features, FEATURES_COUNT, and ast_call_feature::sname.
Referenced by action_atxfer(), and handle_request_info().
02624 { 02625 int x; 02626 for (x = 0; x < FEATURES_COUNT; x++) { 02627 if (!strcasecmp(name, builtin_features[x].sname)) 02628 return &builtin_features[x]; 02629 } 02630 return NULL; 02631 }
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. | |
timeout | is a timeout in milliseconds | |
extout | is a parameter to an int that will hold the parked location, or NULL if you want. |
0 | on success. | |
-1 | on failure. |
Definition at line 1299 of file features.c.
References masq_park_call().
Referenced by __analog_ss_thread(), analog_ss_thread(), handle_exec(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), parkandannounce_exec(), and rpt_exec().
01300 { 01301 return masq_park_call(rchan, peer, timeout, extout, 0, NULL); 01302 }
int ast_park_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | host, | |||
int | timeout, | |||
const char * | parkexten, | |||
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. | |
timeout | is a timeout in milliseconds | |
extout | is a parameter to an int that will hold the parked location, or NULL if you want. |
0 | on success. | |
-1 | on failure. |
Definition at line 1225 of file features.c.
References ao2_callback, args, find_parkinglot_by_exten_cb(), park_call_full(), and parkinglots.
Referenced by iax_park_thread(), and sip_park_thread().
01226 { 01227 struct ast_parkinglot *found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, (void *) parkexten); 01228 01229 struct ast_park_call_args args = { 01230 .timeout = timeout, 01231 .extout = extout, 01232 .parkinglot = found_lot, 01233 }; 01234 01235 return park_call_full(chan, peer, &args); 01236 }
int ast_parking_ext_valid | ( | const char * | exten_str, | |
struct ast_channel * | chan, | |||
const char * | context | |||
) |
Determine if parking extension exists in a given context.
0 | if extension does not exist | |
1 | if extension does exist |
Definition at line 643 of file features.c.
References ast_get_extension_app(), E_MATCH, feature_group_exten::exten, PARK_APP_NAME, pbx_find_extension(), and pbx_find_info::stacklen.
Referenced by __analog_ss_thread(), analog_ss_thread(), dp_lookup(), handle_request_refer(), mgcp_ss(), and socket_process().
00644 { 00645 struct ast_exten *exten; 00646 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 00647 const char *app_at_exten; 00648 00649 exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL, E_MATCH); 00650 if (!exten) { 00651 return 0; 00652 } 00653 00654 app_at_exten = ast_get_extension_app(exten); 00655 if (!app_at_exten || strcmp(PARK_APP_NAME, app_at_exten)) { 00656 return 0; 00657 } 00658 00659 return 1; 00660 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
chan | channel that initiated pickup. |
Definition at line 5598 of file features.c.
References ast_answer(), ast_channel_callback(), ast_channel_connected_line_macro(), ast_channel_lock_both, ast_channel_masquerade(), ast_channel_queue_connected_line_update(), ast_channel_unlock, ast_channel_unref, ast_channel_update_connected_line(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_manager_event_multichan, ast_party_connected_line_collect_caller(), ast_queue_control(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_channel::caller, ast_channel::connected, EVENT_FLAG_CALL, find_channel_by_group(), LOG_WARNING, ast_channel::name, pickupfailsound, pickupsound, and ast_party_connected_line::source.
Referenced by __analog_ss_thread(), analog_ss_thread(), cb_events(), handle_request_invite(), mgcp_ss(), and pickup_exec().
05599 { 05600 struct ast_channel *cur, *chans[2] = { chan, }; 05601 struct ast_party_connected_line connected_caller; 05602 int res; 05603 const char *chan_name; 05604 const char *cur_name; 05605 05606 if (!(cur = ast_channel_callback(find_channel_by_group, NULL, chan, 0))) { 05607 ast_debug(1, "No call pickup possible...\n"); 05608 if (!ast_strlen_zero(pickupfailsound)) { 05609 ast_stream_and_wait(chan, pickupfailsound, ""); 05610 } 05611 return -1; 05612 } 05613 05614 chans[1] = cur; 05615 05616 ast_channel_lock_both(cur, chan); 05617 05618 cur_name = ast_strdupa(cur->name); 05619 chan_name = ast_strdupa(chan->name); 05620 05621 ast_debug(1, "Call pickup on chan '%s' by '%s'\n", cur_name, chan_name); 05622 05623 connected_caller = cur->connected; 05624 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 05625 if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) { 05626 ast_channel_update_connected_line(chan, &connected_caller, NULL); 05627 } 05628 05629 ast_party_connected_line_collect_caller(&connected_caller, &chan->caller); 05630 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 05631 ast_channel_queue_connected_line_update(chan, &connected_caller, NULL); 05632 05633 ast_channel_unlock(cur); 05634 ast_channel_unlock(chan); 05635 05636 if (ast_answer(chan)) { 05637 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name); 05638 } 05639 05640 if (ast_queue_control(chan, AST_CONTROL_ANSWER)) { 05641 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name); 05642 } 05643 05644 if ((res = ast_channel_masquerade(cur, chan))) { 05645 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan_name, cur_name); 05646 } 05647 05648 if (!ast_strlen_zero(pickupsound)) { 05649 ast_stream_and_wait(cur, pickupsound, ""); 05650 } 05651 05652 /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */ 05653 ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans, 05654 "Channel: %s\r\nTargetChannel: %s\r\n", chan->name, cur->name); 05655 05656 cur = ast_channel_unref(cur); 05657 05658 return res; 05659 }
const char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 662 of file features.c.
References pickup_ext.
Referenced by __analog_ss_thread(), analog_ss_thread(), cb_events(), get_destination(), handle_feature_show(), handle_request_invite(), and mgcp_ss().
00663 { 00664 return pickup_ext; 00665 }
void ast_rdlock_call_features | ( | void | ) |
Definition at line 2613 of file features.c.
References ast_rwlock_rdlock, and features_lock.
Referenced by handle_request_info().
02614 { 02615 ast_rwlock_rdlock(&features_lock); 02616 }
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 2457 of file features.c.
References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, feature_group_exten::feature, ast_call_feature::feature_entry, LOG_NOTICE, and ast_call_feature::sname.
02458 { 02459 if (!feature) { 02460 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 02461 return; 02462 } 02463 02464 AST_RWLIST_WRLOCK(&feature_list); 02465 AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry); 02466 AST_RWLIST_UNLOCK(&feature_list); 02467 02468 ast_verb(2, "Registered Feature '%s'\n",feature->sname); 02469 }
void ast_unlock_call_features | ( | void | ) |
Definition at line 2618 of file features.c.
References ast_rwlock_unlock, and features_lock.
Referenced by handle_request_info().
02619 { 02620 ast_rwlock_unlock(&features_lock); 02621 }
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 2537 of file features.c.
References ast_free, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and feature_group_exten::feature.
02538 { 02539 if (!feature) { 02540 return; 02541 } 02542 02543 AST_RWLIST_WRLOCK(&feature_list); 02544 AST_RWLIST_REMOVE(&feature_list, feature, feature_entry); 02545 AST_RWLIST_UNLOCK(&feature_list); 02546 02547 ast_free(feature); 02548 }