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_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. | |
int | ast_park_metermaid_add (void(*maid)(char *exten, char *context), char *context) |
Add parking watcher (metermaid) to list. These will be notified when we create or remove parking extensions in the dial plan. | |
int | ast_park_metermaid_remove (int id) |
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 |
#define FEATURE_APP_LEN 64 |
#define FEATURE_EXTEN_LEN 32 |
#define FEATURE_MAX_LEN 11 |
#define FEATURE_SNAME_LEN 32 |
int ast_bridge_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | peer, | |||
struct ast_bridge_config * | config | |||
) |
Bridge a call, optionally allowing redirection.
Definition at line 1361 of file res_features.c.
References ast_channel::appl, ast_answer(), ast_cdr_appenduserfield(), ast_cdr_setuserfield(), ast_channel_bridge(), ast_channel_setoption(), ast_clear_flag, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_OPTION, AST_CONTROL_RINGING, ast_dtmf_stream(), ast_feature_interpret(), AST_FEATURE_PLAY_WARNING, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_indicate(), ast_log(), AST_OPTION_FLAG_REQUEST, ast_strlen_zero(), ast_channel::cdr, config, ast_channel::data, ast_frame::data, ast_option_header::data, ast_frame::datalen, FEATURE_MAX_LEN, FEATURE_RETURN_PASSDIGITS, FEATURE_RETURN_SUCCESS, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_option_header::flag, ast_frame::frametype, free, LOG_DEBUG, LOG_WARNING, monitor_app, ast_channel::name, ast_option_header::option, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), set_config_flags(), ast_frame::subclass, and ast_cdr::userfield.
Referenced by ast_bridge_call_thread(), builtin_atxfer(), dial_exec_full(), park_exec(), and try_calling().
01362 { 01363 /* Copy voice back and forth between the two channels. Give the peer 01364 the ability to transfer calls with '#<extension' syntax. */ 01365 struct ast_frame *f; 01366 struct ast_channel *who; 01367 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 01368 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 01369 int res; 01370 int diff; 01371 int hasfeatures=0; 01372 int hadfeatures=0; 01373 struct ast_option_header *aoh; 01374 struct timeval start = { 0 , 0 }; 01375 struct ast_bridge_config backup_config; 01376 char *monitor_exec; 01377 01378 memset(&backup_config, 0, sizeof(backup_config)); 01379 01380 config->start_time = ast_tvnow(); 01381 01382 if (chan && peer) { 01383 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01384 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01385 } else if (chan) 01386 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01387 01388 if (monitor_ok) { 01389 if (!monitor_app) { 01390 if (!(monitor_app = pbx_findapp("Monitor"))) 01391 monitor_ok=0; 01392 } 01393 if (monitor_app) { 01394 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01395 pbx_exec(chan, monitor_app, monitor_exec, 1); 01396 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01397 pbx_exec(peer, monitor_app, monitor_exec, 1); 01398 } 01399 } 01400 01401 set_config_flags(chan, peer, config); 01402 config->firstpass = 1; 01403 01404 /* Answer if need be */ 01405 if (ast_answer(chan)) 01406 return -1; 01407 peer->appl = "Bridged Call"; 01408 peer->data = chan->name; 01409 01410 /* copy the userfield from the B-leg to A-leg if applicable */ 01411 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) { 01412 char tmp[256]; 01413 if (!ast_strlen_zero(chan->cdr->userfield)) { 01414 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield); 01415 ast_cdr_appenduserfield(chan, tmp); 01416 } else 01417 ast_cdr_setuserfield(chan, peer->cdr->userfield); 01418 /* free the peer's cdr without ast_cdr_free complaining */ 01419 free(peer->cdr); 01420 peer->cdr = NULL; 01421 } 01422 for (;;) { 01423 if (config->feature_timer) 01424 start = ast_tvnow(); 01425 01426 res = ast_channel_bridge(chan, peer, config, &f, &who); 01427 01428 if (config->feature_timer) { 01429 /* Update time limit for next pass */ 01430 diff = ast_tvdiff_ms(ast_tvnow(), start); 01431 config->feature_timer -= diff; 01432 if (hasfeatures) { 01433 /* Running on backup config, meaning a feature might be being 01434 activated, but that's no excuse to keep things going 01435 indefinitely! */ 01436 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01437 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01438 config->feature_timer = 0; 01439 who = chan; 01440 if (f) 01441 ast_frfree(f); 01442 f = NULL; 01443 res = 0; 01444 } else if (config->feature_timer <= 0) { 01445 /* Not *really* out of time, just out of time for 01446 digits to come in for features. */ 01447 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01448 if (!ast_strlen_zero(peer_featurecode)) { 01449 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01450 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01451 } 01452 if (!ast_strlen_zero(chan_featurecode)) { 01453 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01454 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01455 } 01456 if (f) 01457 ast_frfree(f); 01458 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01459 if (!hasfeatures) { 01460 /* Restore original (possibly time modified) bridge config */ 01461 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01462 memset(&backup_config, 0, sizeof(backup_config)); 01463 } 01464 hadfeatures = hasfeatures; 01465 /* Continue as we were */ 01466 continue; 01467 } 01468 } else { 01469 if (config->feature_timer <=0) { 01470 /* We ran out of time */ 01471 config->feature_timer = 0; 01472 who = chan; 01473 if (f) 01474 ast_frfree(f); 01475 f = NULL; 01476 res = 0; 01477 } 01478 } 01479 } 01480 if (res < 0) { 01481 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01482 return -1; 01483 } 01484 01485 if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 01486 (f->subclass == AST_CONTROL_CONGESTION)))) { 01487 res = -1; 01488 break; 01489 } 01490 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) { 01491 if (who == chan) 01492 ast_indicate(peer, AST_CONTROL_RINGING); 01493 else 01494 ast_indicate(chan, AST_CONTROL_RINGING); 01495 } 01496 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) { 01497 if (who == chan) 01498 ast_indicate(peer, -1); 01499 else 01500 ast_indicate(chan, -1); 01501 } 01502 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) { 01503 if (who == chan) 01504 ast_indicate(peer, AST_CONTROL_FLASH); 01505 else 01506 ast_indicate(chan, AST_CONTROL_FLASH); 01507 } 01508 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) { 01509 aoh = f->data; 01510 /* Forward option Requests */ 01511 if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) { 01512 if (who == chan) 01513 ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0); 01514 else 01515 ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0); 01516 } 01517 } 01518 /* check for '*', if we find it it's time to disconnect */ 01519 if (f && (f->frametype == AST_FRAME_DTMF)) { 01520 char *featurecode; 01521 int sense; 01522 struct ast_channel *other; 01523 01524 hadfeatures = hasfeatures; 01525 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01526 if (who == chan) { 01527 other = peer; 01528 sense = FEATURE_SENSE_CHAN; 01529 featurecode = chan_featurecode; 01530 } else { 01531 other = chan; 01532 sense = FEATURE_SENSE_PEER; 01533 featurecode = peer_featurecode; 01534 } 01535 featurecode[strlen(featurecode)] = f->subclass; 01536 /* Get rid of the frame before we start doing "stuff" with the channels */ 01537 ast_frfree(f); 01538 f = NULL; 01539 config->feature_timer = backup_config.feature_timer; 01540 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01541 switch(res) { 01542 case FEATURE_RETURN_PASSDIGITS: 01543 ast_dtmf_stream(other, who, featurecode, 0); 01544 /* Fall through */ 01545 case FEATURE_RETURN_SUCCESS: 01546 memset(featurecode, 0, sizeof(chan_featurecode)); 01547 break; 01548 } 01549 if (res >= FEATURE_RETURN_PASSDIGITS) { 01550 res = 0; 01551 } else 01552 break; 01553 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01554 if (hadfeatures && !hasfeatures) { 01555 /* Restore backup */ 01556 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01557 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01558 } else if (hasfeatures) { 01559 if (!hadfeatures) { 01560 /* Backup configuration */ 01561 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01562 /* Setup temporary config options */ 01563 config->play_warning = 0; 01564 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01565 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01566 config->warning_freq = 0; 01567 config->warning_sound = NULL; 01568 config->end_sound = NULL; 01569 config->start_sound = NULL; 01570 config->firstpass = 0; 01571 } 01572 config->start_time = ast_tvnow(); 01573 config->feature_timer = featuredigittimeout; 01574 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01575 } 01576 } 01577 if (f) 01578 ast_frfree(f); 01579 } 01580 return res; 01581 }
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 498 of file res_features.c.
References ast_channel_alloc(), ast_channel_masquerade(), ast_frfree(), ast_log(), ast_park_call(), ast_read(), ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
Referenced by mgcp_ss(), parkandannounce_exec(), rpt_exec(), skinny_ss(), and ss_thread().
00499 { 00500 struct ast_channel *chan; 00501 struct ast_frame *f; 00502 00503 /* Make a new, fake channel that we'll use to masquerade in the real one */ 00504 chan = ast_channel_alloc(0); 00505 if (chan) { 00506 /* Let us keep track of the channel name */ 00507 snprintf(chan->name, sizeof (chan->name), "Parked/%s",rchan->name); 00508 00509 /* Make formats okay */ 00510 chan->readformat = rchan->readformat; 00511 chan->writeformat = rchan->writeformat; 00512 ast_channel_masquerade(chan, rchan); 00513 00514 /* Setup the extensions and such */ 00515 ast_copy_string(chan->context, rchan->context, sizeof(chan->context)); 00516 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten)); 00517 chan->priority = rchan->priority; 00518 00519 /* Make the masq execute */ 00520 f = ast_read(chan); 00521 if (f) 00522 ast_frfree(f); 00523 ast_park_call(chan, peer, timeout, extout); 00524 } else { 00525 ast_log(LOG_WARNING, "Unable to create parked channel\n"); 00526 return -1; 00527 } 00528 return 0; 00529 }
int ast_park_call | ( | struct ast_channel * | chan, | |
struct ast_channel * | host, | |||
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 373 of file res_features.c.
References adsi_announce_park(), adsi_available(), adsi_unload_session(), ast_channel::appl, ast_add_extension2(), ast_context_create(), ast_context_find(), AST_CONTROL_HOLD, ast_indicate(), ast_log(), AST_MAX_EXTENSION, ast_moh_start(), ast_mutex_lock(), ast_mutex_unlock(), ast_say_digits(), ast_strlen_zero(), ast_verbose(), parkeduser::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, parkeduser::context, ast_channel::context, ast_channel::data, EVENT_FLAG_CALL, exten, parkeduser::exten, ast_channel::exten, free, FREE, LOG_ERROR, LOG_WARNING, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, malloc, manager_event(), ast_channel::name, parkeduser::next, notify_metermaids(), parkeduser::notquiteyet, option_verbose, parkinglot, parkeduser::parkingnum, parkeduser::parkingtime, parkeduser::peername, parkeduser::priority, ast_channel::priority, parkeduser::start, strdup, and VERBOSE_PREFIX_2.
Referenced by ast_masq_park_call(), builtin_blindtransfer(), iax_park_thread(), park_call_exec(), and sip_park_thread().
00374 { 00375 struct parkeduser *pu, *cur; 00376 int i,x,parking_range; 00377 char exten[AST_MAX_EXTENSION]; 00378 struct ast_context *con; 00379 00380 pu = malloc(sizeof(struct parkeduser)); 00381 if (!pu) { 00382 ast_log(LOG_WARNING, "Out of memory\n"); 00383 return -1; 00384 } 00385 memset(pu, 0, sizeof(struct parkeduser)); 00386 ast_mutex_lock(&parking_lock); 00387 parking_range = parking_stop - parking_start+1; 00388 for (i = 0; i < parking_range; i++) { 00389 x = (i + parking_offset) % parking_range + parking_start; 00390 cur = parkinglot; 00391 while(cur) { 00392 if (cur->parkingnum == x) 00393 break; 00394 cur = cur->next; 00395 } 00396 if (!cur) 00397 break; 00398 } 00399 00400 if (!(i < parking_range)) { 00401 ast_log(LOG_WARNING, "No more parking spaces\n"); 00402 free(pu); 00403 ast_mutex_unlock(&parking_lock); 00404 return -1; 00405 } 00406 if (parkfindnext) 00407 parking_offset = x - parking_start + 1; 00408 chan->appl = "Parked Call"; 00409 chan->data = NULL; 00410 00411 pu->chan = chan; 00412 /* Start music on hold */ 00413 if (chan != peer) { 00414 ast_indicate(pu->chan, AST_CONTROL_HOLD); 00415 ast_moh_start(pu->chan, NULL); 00416 } 00417 pu->start = ast_tvnow(); 00418 pu->parkingnum = x; 00419 if (timeout > 0) 00420 pu->parkingtime = timeout; 00421 else 00422 pu->parkingtime = parkingtime; 00423 if (extout) 00424 *extout = x; 00425 if (peer) 00426 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername)); 00427 00428 /* Remember what had been dialed, so that if the parking 00429 expires, we try to come back to the same place */ 00430 if (!ast_strlen_zero(chan->macrocontext)) 00431 ast_copy_string(pu->context, chan->macrocontext, sizeof(pu->context)); 00432 else 00433 ast_copy_string(pu->context, chan->context, sizeof(pu->context)); 00434 if (!ast_strlen_zero(chan->macroexten)) 00435 ast_copy_string(pu->exten, chan->macroexten, sizeof(pu->exten)); 00436 else 00437 ast_copy_string(pu->exten, chan->exten, sizeof(pu->exten)); 00438 if (chan->macropriority) 00439 pu->priority = chan->macropriority; 00440 else 00441 pu->priority = chan->priority; 00442 pu->next = parkinglot; 00443 parkinglot = pu; 00444 /* If parking a channel directly, don't quiet yet get parking running on it */ 00445 if (peer == chan) 00446 pu->notquiteyet = 1; 00447 ast_mutex_unlock(&parking_lock); 00448 /* Wake up the (presumably select()ing) thread */ 00449 pthread_kill(parking_thread, SIGURG); 00450 if (option_verbose > 1) 00451 ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000)); 00452 00453 manager_event(EVENT_FLAG_CALL, "ParkedCall", 00454 "Exten: %d\r\n" 00455 "Channel: %s\r\n" 00456 "From: %s\r\n" 00457 "Timeout: %ld\r\n" 00458 "CallerID: %s\r\n" 00459 "CallerIDName: %s\r\n" 00460 ,pu->parkingnum, pu->chan->name, peer ? peer->name : "" 00461 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL) 00462 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>") 00463 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>") 00464 ); 00465 00466 if (peer) { 00467 if (adsipark && adsi_available(peer)) { 00468 adsi_announce_park(peer, pu->parkingnum); 00469 } 00470 if (adsipark && adsi_available(peer)) { 00471 adsi_unload_session(peer); 00472 } 00473 } 00474 con = ast_context_find(parking_con); 00475 if (!con) { 00476 con = ast_context_create(NULL, parking_con, registrar); 00477 if (!con) { 00478 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con); 00479 } 00480 } 00481 if (con) { 00482 snprintf(exten, sizeof(exten), "%d", x); 00483 00484 if (ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar) == 0) 00485 notify_metermaids(exten, parking_con); /* Notify watchers */ 00486 } 00487 if (peer) 00488 ast_say_digits(peer, pu->parkingnum, "", peer->language); 00489 if (pu->notquiteyet) { 00490 /* Wake up parking thread if we're really done */ 00491 ast_moh_start(pu->chan, NULL); 00492 pu->notquiteyet = 0; 00493 pthread_kill(parking_thread, SIGURG); 00494 } 00495 return 0; 00496 }
Add parking watcher (metermaid) to list. These will be notified when we create or remove parking extensions in the dial plan.
Add parking watcher (metermaid) to list. These will be notified when we create or remove parking extensions in the dial plan
Definition at line 292 of file res_features.c.
References ast_log(), features_parkwatch::callback, features_parkwatch::context, features_parkwatch::id, LOG_DEBUG, LOG_ERROR, malloc, metermaids, features_parkwatch::next, option_debug, and strdup.
Referenced by load_module().
00293 { 00294 struct features_parkwatch *newmaid; 00295 struct features_parkwatch *maids = metermaids; 00296 00297 newmaid = malloc(sizeof(struct features_parkwatch)); 00298 if (!newmaid) { 00299 ast_log(LOG_ERROR, "Can't allocate parking watcher, out of memory.\n"); 00300 return -1; 00301 } 00302 memset(newmaid, 0, sizeof(struct features_parkwatch)); 00303 00304 /* Spool till end of list */ 00305 while(maids && maids->next) { 00306 maids = maids->next; 00307 } 00308 00309 newmaid->callback = maid; 00310 if (context) 00311 newmaid->context = strdup(context); 00312 newmaid->id = metermaidid; 00313 00314 /* Generate new ID */ 00315 metermaidid++; 00316 00317 /* Link the new object to the list */ 00318 if (maids) 00319 maids->next = newmaid; 00320 else 00321 metermaids = newmaid; 00322 if (option_debug > 1) 00323 ast_log(LOG_DEBUG, "Added metermaid # %d\n", metermaidid); 00324 return metermaidid; 00325 }
int ast_park_metermaid_remove | ( | int | id | ) |
Remove parking watcher
Definition at line 328 of file res_features.c.
References features_parkwatch::context, free, features_parkwatch::id, metermaids, and features_parkwatch::next.
Referenced by unload_module().
00329 { 00330 struct features_parkwatch *maids = metermaids; 00331 struct features_parkwatch *prev = NULL; 00332 struct features_parkwatch *kill = NULL; 00333 00334 while (maids && !kill) { 00335 if (maids->id == id) { 00336 if (prev) { 00337 prev->next = maids->next; 00338 } else { 00339 metermaids = maids->next; 00340 } 00341 kill = maids; 00342 } 00343 prev = maids; 00344 maids = maids->next; 00345 } 00346 if (!kill) 00347 return -1; /* Did not find id */ 00348 if (kill->context) 00349 free(kill->context); 00350 free(kill); 00351 return 0; 00352 }
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 177 of file res_features.c.
Referenced by builtin_blindtransfer(), dp_lookup(), get_refer_info(), handle_request_refer(), load_config(), mgcp_ss(), skinny_ss(), socket_read(), and ss_thread().
00178 { 00179 return parking_ext; 00180 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 2033 of file res_features.c.
References ast_channel::_state, ast_answer(), ast_channel_masquerade(), ast_channel_walk_locked(), AST_CONTROL_ANSWER, ast_log(), ast_mutex_unlock(), ast_queue_control(), AST_STATE_RING, AST_STATE_RINGING, ast_channel::callgroup, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_debug, ast_channel::pbx, and ast_channel::pickupgroup.
Referenced by cb_events(), handle_request_invite(), mgcp_ss(), monitor_handle_notowned(), skinny_ss(), and ss_thread().
02034 { 02035 struct ast_channel *cur = NULL; 02036 int res = -1; 02037 02038 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 02039 if (!cur->pbx && 02040 (cur != chan) && 02041 (chan->pickupgroup & cur->callgroup) && 02042 ((cur->_state == AST_STATE_RINGING) || 02043 (cur->_state == AST_STATE_RING))) { 02044 break; 02045 } 02046 ast_mutex_unlock(&cur->lock); 02047 } 02048 if (cur) { 02049 if (option_debug) 02050 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 02051 res = ast_answer(chan); 02052 if (res) 02053 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 02054 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 02055 if (res) 02056 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 02057 res = ast_channel_masquerade(cur, chan); 02058 if (res) 02059 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 02060 ast_mutex_unlock(&cur->lock); 02061 } else { 02062 if (option_debug) 02063 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 02064 } 02065 return res; 02066 }
char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 182 of file res_features.c.
Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), monitor_handle_notowned(), skinny_ss(), and ss_thread().
00183 { 00184 return pickup_ext; 00185 }
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 972 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().
00973 { 00974 if (!feature) { 00975 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 00976 return; 00977 } 00978 00979 AST_LIST_LOCK(&feature_list); 00980 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry); 00981 AST_LIST_UNLOCK(&feature_list); 00982 00983 if (option_verbose >= 2) 00984 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 00985 }
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 988 of file res_features.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.
00989 { 00990 if (!feature) return; 00991 00992 AST_LIST_LOCK(&feature_list); 00993 AST_LIST_REMOVE(&feature_list,feature,feature_entry); 00994 AST_LIST_UNLOCK(&feature_list); 00995 free(feature); 00996 }