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_bridge_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config) |
Bridge a call, optionally allowing redirection. | |
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 | |
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_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 1330 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_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_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(), builtin_atxfer(), park_exec(), and try_calling().
01331 { 01332 /* Copy voice back and forth between the two channels. Give the peer 01333 the ability to transfer calls with '#<extension' syntax. */ 01334 struct ast_frame *f; 01335 struct ast_channel *who; 01336 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 01337 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 01338 int res; 01339 int diff; 01340 int hasfeatures=0; 01341 int hadfeatures=0; 01342 struct ast_option_header *aoh; 01343 struct ast_bridge_config backup_config; 01344 struct ast_cdr *bridge_cdr; 01345 01346 memset(&backup_config, 0, sizeof(backup_config)); 01347 01348 config->start_time = ast_tvnow(); 01349 01350 if (chan && peer) { 01351 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01352 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01353 } else if (chan) 01354 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01355 01356 if (monitor_ok) { 01357 const char *monitor_exec; 01358 struct ast_channel *src = NULL; 01359 if (!monitor_app) { 01360 if (!(monitor_app = pbx_findapp("Monitor"))) 01361 monitor_ok=0; 01362 } 01363 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01364 src = chan; 01365 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01366 src = peer; 01367 if (monitor_app && src) { 01368 char *tmp = ast_strdupa(monitor_exec); 01369 pbx_exec(src, monitor_app, tmp); 01370 } 01371 } 01372 01373 set_config_flags(chan, peer, config); 01374 config->firstpass = 1; 01375 01376 /* Answer if need be */ 01377 if (ast_answer(chan)) 01378 return -1; 01379 peer->appl = "Bridged Call"; 01380 peer->data = chan->name; 01381 01382 /* copy the userfield from the B-leg to A-leg if applicable */ 01383 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) { 01384 char tmp[256]; 01385 if (!ast_strlen_zero(chan->cdr->userfield)) { 01386 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield); 01387 ast_cdr_appenduserfield(chan, tmp); 01388 } else 01389 ast_cdr_setuserfield(chan, peer->cdr->userfield); 01390 /* free the peer's cdr without ast_cdr_free complaining */ 01391 free(peer->cdr); 01392 peer->cdr = NULL; 01393 } 01394 01395 for (;;) { 01396 struct ast_channel *other; /* used later */ 01397 01398 res = ast_channel_bridge(chan, peer, config, &f, &who); 01399 01400 if (config->feature_timer) { 01401 /* Update time limit for next pass */ 01402 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 01403 config->feature_timer -= diff; 01404 if (hasfeatures) { 01405 /* Running on backup config, meaning a feature might be being 01406 activated, but that's no excuse to keep things going 01407 indefinitely! */ 01408 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01409 if (option_debug) 01410 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01411 config->feature_timer = 0; 01412 who = chan; 01413 if (f) 01414 ast_frfree(f); 01415 f = NULL; 01416 res = 0; 01417 } else if (config->feature_timer <= 0) { 01418 /* Not *really* out of time, just out of time for 01419 digits to come in for features. */ 01420 if (option_debug) 01421 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01422 if (!ast_strlen_zero(peer_featurecode)) { 01423 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01424 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01425 } 01426 if (!ast_strlen_zero(chan_featurecode)) { 01427 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01428 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01429 } 01430 if (f) 01431 ast_frfree(f); 01432 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01433 if (!hasfeatures) { 01434 /* Restore original (possibly time modified) bridge config */ 01435 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01436 memset(&backup_config, 0, sizeof(backup_config)); 01437 } 01438 hadfeatures = hasfeatures; 01439 /* Continue as we were */ 01440 continue; 01441 } else if (!f) { 01442 /* The bridge returned without a frame and there is a feature in progress. 01443 * However, we don't think the feature has quite yet timed out, so just 01444 * go back into the bridge. */ 01445 continue; 01446 } 01447 } else { 01448 if (config->feature_timer <=0) { 01449 /* We ran out of time */ 01450 config->feature_timer = 0; 01451 who = chan; 01452 if (f) 01453 ast_frfree(f); 01454 f = NULL; 01455 res = 0; 01456 } 01457 } 01458 } 01459 if (res < 0) { 01460 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01461 return -1; 01462 } 01463 01464 if (!f || (f->frametype == AST_FRAME_CONTROL && 01465 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 01466 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 01467 res = -1; 01468 break; 01469 } 01470 /* many things should be sent to the 'other' channel */ 01471 other = (who == chan) ? peer : chan; 01472 if (f->frametype == AST_FRAME_CONTROL) { 01473 switch (f->subclass) { 01474 case AST_CONTROL_RINGING: 01475 case AST_CONTROL_FLASH: 01476 case -1: 01477 ast_indicate(other, f->subclass); 01478 break; 01479 case AST_CONTROL_HOLD: 01480 case AST_CONTROL_UNHOLD: 01481 ast_indicate_data(other, f->subclass, f->data, f->datalen); 01482 break; 01483 case AST_CONTROL_OPTION: 01484 aoh = f->data; 01485 /* Forward option Requests */ 01486 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 01487 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 01488 f->datalen - sizeof(struct ast_option_header), 0); 01489 } 01490 break; 01491 } 01492 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 01493 /* eat it */ 01494 } else if (f->frametype == AST_FRAME_DTMF) { 01495 char *featurecode; 01496 int sense; 01497 01498 hadfeatures = hasfeatures; 01499 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01500 if (who == chan) { 01501 sense = FEATURE_SENSE_CHAN; 01502 featurecode = chan_featurecode; 01503 } else { 01504 sense = FEATURE_SENSE_PEER; 01505 featurecode = peer_featurecode; 01506 } 01507 /*! append the event to featurecode. we rely on the string being zero-filled, and 01508 * not overflowing it. 01509 * \todo XXX how do we guarantee the latter ? 01510 */ 01511 featurecode[strlen(featurecode)] = f->subclass; 01512 /* Get rid of the frame before we start doing "stuff" with the channels */ 01513 ast_frfree(f); 01514 f = NULL; 01515 config->feature_timer = backup_config.feature_timer; 01516 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01517 switch(res) { 01518 case FEATURE_RETURN_PASSDIGITS: 01519 ast_dtmf_stream(other, who, featurecode, 0); 01520 /* Fall through */ 01521 case FEATURE_RETURN_SUCCESS: 01522 memset(featurecode, 0, sizeof(chan_featurecode)); 01523 break; 01524 } 01525 if (res >= FEATURE_RETURN_PASSDIGITS) { 01526 res = 0; 01527 } else 01528 break; 01529 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01530 if (hadfeatures && !hasfeatures) { 01531 /* Restore backup */ 01532 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01533 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01534 } else if (hasfeatures) { 01535 if (!hadfeatures) { 01536 /* Backup configuration */ 01537 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01538 /* Setup temporary config options */ 01539 config->play_warning = 0; 01540 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01541 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01542 config->warning_freq = 0; 01543 config->warning_sound = NULL; 01544 config->end_sound = NULL; 01545 config->start_sound = NULL; 01546 config->firstpass = 0; 01547 } 01548 config->start_time = ast_tvnow(); 01549 config->feature_timer = featuredigittimeout; 01550 if (option_debug) 01551 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01552 } 01553 } 01554 if (f) 01555 ast_frfree(f); 01556 01557 } 01558 01559 /* arrange the cdrs */ 01560 bridge_cdr = ast_cdr_alloc(); 01561 if (bridge_cdr) { 01562 if (chan->cdr && peer->cdr) { /* both of them? merge */ 01563 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */ 01564 ast_cdr_start(bridge_cdr); /* now is the time to start */ 01565 01566 /* absorb the channel cdr */ 01567 ast_cdr_merge(bridge_cdr, chan->cdr); 01568 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 01569 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01570 01571 /* absorb the peer cdr */ 01572 ast_cdr_merge(bridge_cdr, peer->cdr); 01573 if (ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) 01574 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */ 01575 01576 peer->cdr = NULL; 01577 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01578 } else if (chan->cdr) { 01579 /* take the cdr from the channel - literally */ 01580 ast_cdr_init(bridge_cdr,chan); 01581 /* absorb this data */ 01582 ast_cdr_merge(bridge_cdr, chan->cdr); 01583 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 01584 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01585 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01586 } else if (peer->cdr) { 01587 /* take the cdr from the peer - literally */ 01588 ast_cdr_init(bridge_cdr,peer); 01589 /* absorb this data */ 01590 ast_cdr_merge(bridge_cdr, peer->cdr); 01591 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) 01592 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ 01593 peer->cdr = NULL; 01594 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01595 } else { 01596 /* make up a new cdr */ 01597 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */ 01598 chan->cdr = bridge_cdr; /* */ 01599 } 01600 if (ast_strlen_zero(bridge_cdr->dstchannel)) { 01601 if (strcmp(bridge_cdr->channel, peer->name) != 0) 01602 ast_cdr_setdestchan(bridge_cdr, peer->name); 01603 else 01604 ast_cdr_setdestchan(bridge_cdr, chan->name); 01605 } 01606 } 01607 return res; 01608 }
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 442 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(), and ss_thread().
00443 { 00444 struct ast_channel *chan; 00445 struct ast_frame *f; 00446 00447 /* Make a new, fake channel that we'll use to masquerade in the real one */ 00448 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) { 00449 ast_log(LOG_WARNING, "Unable to create parked channel\n"); 00450 return -1; 00451 } 00452 00453 /* Make formats okay */ 00454 chan->readformat = rchan->readformat; 00455 chan->writeformat = rchan->writeformat; 00456 ast_channel_masquerade(chan, rchan); 00457 00458 /* Setup the extensions and such */ 00459 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority); 00460 00461 /* Make the masq execute */ 00462 f = ast_read(chan); 00463 if (f) 00464 ast_frfree(f); 00465 00466 ast_park_call(chan, peer, timeout, extout); 00467 return 0; 00468 }
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 311 of file res_features.c.
References adsi_announce_park(), ast_channel::appl, ast_add_extension2(), ast_adsi_available(), ast_adsi_unload_session(), ast_calloc, ast_context_create(), ast_context_find(), AST_CONTROL_HOLD, ast_exists_extension(), ast_free, ast_indicate_data(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_say_digits(), ast_strlen_zero(), ast_verbose(), ast_channel::context, ast_channel::data, EVENT_FLAG_CALL, ast_channel::exten, free, LOG_ERROR, LOG_WARNING, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, manager_event(), parkeduser::next, notify_metermaids(), parkeduser::notquiteyet, option_verbose, parkinglot, parkeduser::parkingnum, pbx_builtin_getvar_helper(), ast_channel::priority, S_OR, strdup, and VERBOSE_PREFIX_2.
Referenced by ast_masq_park_call(), builtin_blindtransfer(), builtin_parkcall(), iax_park_thread(), park_call_exec(), and sip_park_thread().
00312 { 00313 struct parkeduser *pu, *cur; 00314 int i, x = -1, parking_range; 00315 struct ast_context *con; 00316 const char *parkingexten; 00317 00318 /* Allocate memory for parking data */ 00319 if (!(pu = ast_calloc(1, sizeof(*pu)))) 00320 return -1; 00321 00322 /* Lock parking lot */ 00323 ast_mutex_lock(&parking_lock); 00324 /* Check for channel variable PARKINGEXTEN */ 00325 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"); 00326 if (!ast_strlen_zero(parkingexten)) { 00327 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) { 00328 ast_mutex_unlock(&parking_lock); 00329 free(pu); 00330 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con); 00331 return -1; /* We failed to park this call, plain and simple so we need to error out */ 00332 } 00333 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten)); 00334 x = atoi(parkingexten); 00335 } else { 00336 /* Select parking space within range */ 00337 parking_range = parking_stop - parking_start+1; 00338 for (i = 0; i < parking_range; i++) { 00339 x = (i + parking_offset) % parking_range + parking_start; 00340 cur = parkinglot; 00341 while(cur) { 00342 if (cur->parkingnum == x) 00343 break; 00344 cur = cur->next; 00345 } 00346 if (!cur) 00347 break; 00348 } 00349 00350 if (!(i < parking_range)) { 00351 ast_log(LOG_WARNING, "No more parking spaces\n"); 00352 free(pu); 00353 ast_mutex_unlock(&parking_lock); 00354 return -1; 00355 } 00356 /* Set pointer for next parking */ 00357 if (parkfindnext) 00358 parking_offset = x - parking_start + 1; 00359 } 00360 00361 chan->appl = "Parked Call"; 00362 chan->data = NULL; 00363 00364 pu->chan = chan; 00365 00366 /* Put the parked channel on hold if we have two different channels */ 00367 if (chan != peer) { 00368 ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 00369 S_OR(parkmohclass, NULL), 00370 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0); 00371 } 00372 00373 pu->start = ast_tvnow(); 00374 pu->parkingnum = x; 00375 pu->parkingtime = (timeout > 0) ? timeout : parkingtime; 00376 if (extout) 00377 *extout = x; 00378 00379 if (peer) 00380 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername)); 00381 00382 /* Remember what had been dialed, so that if the parking 00383 expires, we try to come back to the same place */ 00384 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context)); 00385 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten)); 00386 pu->priority = chan->macropriority ? chan->macropriority : chan->priority; 00387 pu->next = parkinglot; 00388 parkinglot = pu; 00389 00390 /* If parking a channel directly, don't quiet yet get parking running on it */ 00391 if (peer == chan) 00392 pu->notquiteyet = 1; 00393 ast_mutex_unlock(&parking_lock); 00394 /* Wake up the (presumably select()ing) thread */ 00395 pthread_kill(parking_thread, SIGURG); 00396 if (option_verbose > 1) 00397 ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parking_con, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000)); 00398 00399 if (pu->parkingnum != -1) 00400 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x); 00401 manager_event(EVENT_FLAG_CALL, "ParkedCall", 00402 "Exten: %s\r\n" 00403 "Channel: %s\r\n" 00404 "From: %s\r\n" 00405 "Timeout: %ld\r\n" 00406 "CallerID: %s\r\n" 00407 "CallerIDName: %s\r\n", 00408 pu->parkingexten, pu->chan->name, peer ? peer->name : "", 00409 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL), 00410 S_OR(pu->chan->cid.cid_num, "<unknown>"), 00411 S_OR(pu->chan->cid.cid_name, "<unknown>") 00412 ); 00413 00414 if (peer && adsipark && ast_adsi_available(peer)) { 00415 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */ 00416 ast_adsi_unload_session(peer); 00417 } 00418 00419 con = ast_context_find(parking_con); 00420 if (!con) 00421 con = ast_context_create(NULL, parking_con, registrar); 00422 if (!con) /* Still no context? Bad */ 00423 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con); 00424 /* Tell the peer channel the number of the parking space */ 00425 if (peer && pu->parkingnum != -1) /* Only say number if it's a number */ 00426 ast_say_digits(peer, pu->parkingnum, "", peer->language); 00427 if (con) { 00428 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free, registrar)) 00429 notify_metermaids(pu->parkingexten, parking_con); 00430 } 00431 if (pu->notquiteyet) { 00432 /* Wake up parking thread if we're really done */ 00433 ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 00434 S_OR(parkmohclass, NULL), 00435 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0); 00436 pu->notquiteyet = 0; 00437 pthread_kill(parking_thread, SIGURG); 00438 } 00439 return 0; 00440 }
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 155 of file res_features.c.
Referenced by builtin_blindtransfer(), dp_lookup(), handle_request_refer(), mgcp_ss(), socket_process(), and ss_thread().
00156 { 00157 return parking_ext; 00158 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 2138 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().
02139 { 02140 struct ast_channel *cur = NULL; 02141 int res = -1; 02142 02143 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 02144 if (!cur->pbx && 02145 (cur != chan) && 02146 (chan->pickupgroup & cur->callgroup) && 02147 ((cur->_state == AST_STATE_RINGING) || 02148 (cur->_state == AST_STATE_RING))) { 02149 break; 02150 } 02151 ast_channel_unlock(cur); 02152 } 02153 if (cur) { 02154 if (option_debug) 02155 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 02156 res = ast_answer(chan); 02157 if (res) 02158 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 02159 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 02160 if (res) 02161 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 02162 res = ast_channel_masquerade(cur, chan); 02163 if (res) 02164 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 02165 ast_channel_unlock(cur); 02166 } else { 02167 if (option_debug) 02168 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 02169 } 02170 return res; 02171 }
char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 160 of file res_features.c.
Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().
00161 { 00162 return pickup_ext; 00163 }
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 899 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.
00900 { 00901 if (!feature) { 00902 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 00903 return; 00904 } 00905 00906 AST_LIST_LOCK(&feature_list); 00907 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry); 00908 AST_LIST_UNLOCK(&feature_list); 00909 00910 if (option_verbose >= 2) 00911 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 00912 }
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 915 of file res_features.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.
00916 { 00917 if (!feature) 00918 return; 00919 00920 AST_LIST_LOCK(&feature_list); 00921 AST_LIST_REMOVE(&feature_list,feature,feature_entry); 00922 AST_LIST_UNLOCK(&feature_list); 00923 free(feature); 00924 }