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 1308 of file res_features.c.
References ast_channel::appl, ast_answer(), ast_cdr_alloc(), ast_cdr_appenduserfield(), ast_cdr_discard(), 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_OPTION, AST_CONTROL_RINGING, 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_log(), AST_OPTION_FLAG_REQUEST, ast_strdupa, ast_strlen_zero(), 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, featuredigittimeout, ast_option_header::flag, free, LOG_DEBUG, LOG_WARNING, monitor_app, monitor_ok, 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().
01309 { 01310 /* Copy voice back and forth between the two channels. Give the peer 01311 the ability to transfer calls with '#<extension' syntax. */ 01312 struct ast_frame *f; 01313 struct ast_channel *who; 01314 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 01315 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 01316 int res; 01317 int diff; 01318 int hasfeatures=0; 01319 int hadfeatures=0; 01320 struct ast_option_header *aoh; 01321 struct ast_bridge_config backup_config; 01322 struct ast_cdr *bridge_cdr; 01323 01324 memset(&backup_config, 0, sizeof(backup_config)); 01325 01326 config->start_time = ast_tvnow(); 01327 01328 if (chan && peer) { 01329 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01330 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01331 } else if (chan) 01332 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01333 01334 if (monitor_ok) { 01335 const char *monitor_exec; 01336 struct ast_channel *src = NULL; 01337 if (!monitor_app) { 01338 if (!(monitor_app = pbx_findapp("Monitor"))) 01339 monitor_ok=0; 01340 } 01341 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01342 src = chan; 01343 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01344 src = peer; 01345 if (monitor_app && src) { 01346 char *tmp = ast_strdupa(monitor_exec); 01347 pbx_exec(src, monitor_app, tmp); 01348 } 01349 } 01350 01351 set_config_flags(chan, peer, config); 01352 config->firstpass = 1; 01353 01354 /* Answer if need be */ 01355 if (ast_answer(chan)) 01356 return -1; 01357 peer->appl = "Bridged Call"; 01358 peer->data = chan->name; 01359 01360 /* copy the userfield from the B-leg to A-leg if applicable */ 01361 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) { 01362 char tmp[256]; 01363 if (!ast_strlen_zero(chan->cdr->userfield)) { 01364 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield); 01365 ast_cdr_appenduserfield(chan, tmp); 01366 } else 01367 ast_cdr_setuserfield(chan, peer->cdr->userfield); 01368 /* free the peer's cdr without ast_cdr_free complaining */ 01369 free(peer->cdr); 01370 peer->cdr = NULL; 01371 } 01372 01373 for (;;) { 01374 struct ast_channel *other; /* used later */ 01375 01376 res = ast_channel_bridge(chan, peer, config, &f, &who); 01377 01378 if (config->feature_timer) { 01379 /* Update time limit for next pass */ 01380 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 01381 config->feature_timer -= diff; 01382 if (hasfeatures) { 01383 /* Running on backup config, meaning a feature might be being 01384 activated, but that's no excuse to keep things going 01385 indefinitely! */ 01386 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01387 if (option_debug) 01388 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01389 config->feature_timer = 0; 01390 who = chan; 01391 if (f) 01392 ast_frfree(f); 01393 f = NULL; 01394 res = 0; 01395 } else if (config->feature_timer <= 0) { 01396 /* Not *really* out of time, just out of time for 01397 digits to come in for features. */ 01398 if (option_debug) 01399 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01400 if (!ast_strlen_zero(peer_featurecode)) { 01401 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01402 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01403 } 01404 if (!ast_strlen_zero(chan_featurecode)) { 01405 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01406 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01407 } 01408 if (f) 01409 ast_frfree(f); 01410 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01411 if (!hasfeatures) { 01412 /* Restore original (possibly time modified) bridge config */ 01413 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01414 memset(&backup_config, 0, sizeof(backup_config)); 01415 } 01416 hadfeatures = hasfeatures; 01417 /* Continue as we were */ 01418 continue; 01419 } else if (!f) { 01420 /* The bridge returned without a frame and there is a feature in progress. 01421 * However, we don't think the feature has quite yet timed out, so just 01422 * go back into the bridge. */ 01423 continue; 01424 } 01425 } else { 01426 if (config->feature_timer <=0) { 01427 /* We ran out of time */ 01428 config->feature_timer = 0; 01429 who = chan; 01430 if (f) 01431 ast_frfree(f); 01432 f = NULL; 01433 res = 0; 01434 } 01435 } 01436 } 01437 if (res < 0) { 01438 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01439 return -1; 01440 } 01441 01442 if (!f || (f->frametype == AST_FRAME_CONTROL && 01443 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 01444 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 01445 res = -1; 01446 break; 01447 } 01448 /* many things should be sent to the 'other' channel */ 01449 other = (who == chan) ? peer : chan; 01450 if (f->frametype == AST_FRAME_CONTROL) { 01451 if (f->subclass == AST_CONTROL_RINGING) 01452 ast_indicate(other, AST_CONTROL_RINGING); 01453 else if (f->subclass == -1) 01454 ast_indicate(other, -1); 01455 else if (f->subclass == AST_CONTROL_FLASH) 01456 ast_indicate(other, AST_CONTROL_FLASH); 01457 else if (f->subclass == AST_CONTROL_OPTION) { 01458 aoh = f->data; 01459 /* Forward option Requests */ 01460 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) 01461 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0); 01462 } 01463 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 01464 /* eat it */ 01465 } else if (f->frametype == AST_FRAME_DTMF) { 01466 char *featurecode; 01467 int sense; 01468 01469 hadfeatures = hasfeatures; 01470 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01471 if (who == chan) { 01472 sense = FEATURE_SENSE_CHAN; 01473 featurecode = chan_featurecode; 01474 } else { 01475 sense = FEATURE_SENSE_PEER; 01476 featurecode = peer_featurecode; 01477 } 01478 /*! append the event to featurecode. we rely on the string being zero-filled, and 01479 * not overflowing it. 01480 * \todo XXX how do we guarantee the latter ? 01481 */ 01482 featurecode[strlen(featurecode)] = f->subclass; 01483 /* Get rid of the frame before we start doing "stuff" with the channels */ 01484 ast_frfree(f); 01485 f = NULL; 01486 config->feature_timer = backup_config.feature_timer; 01487 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01488 switch(res) { 01489 case FEATURE_RETURN_PASSDIGITS: 01490 ast_dtmf_stream(other, who, featurecode, 0); 01491 /* Fall through */ 01492 case FEATURE_RETURN_SUCCESS: 01493 memset(featurecode, 0, sizeof(chan_featurecode)); 01494 break; 01495 } 01496 if (res >= FEATURE_RETURN_PASSDIGITS) { 01497 res = 0; 01498 } else 01499 break; 01500 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01501 if (hadfeatures && !hasfeatures) { 01502 /* Restore backup */ 01503 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01504 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01505 } else if (hasfeatures) { 01506 if (!hadfeatures) { 01507 /* Backup configuration */ 01508 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01509 /* Setup temporary config options */ 01510 config->play_warning = 0; 01511 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01512 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01513 config->warning_freq = 0; 01514 config->warning_sound = NULL; 01515 config->end_sound = NULL; 01516 config->start_sound = NULL; 01517 config->firstpass = 0; 01518 } 01519 config->start_time = ast_tvnow(); 01520 config->feature_timer = featuredigittimeout; 01521 if (option_debug) 01522 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01523 } 01524 } 01525 if (f) 01526 ast_frfree(f); 01527 01528 } 01529 01530 /* arrange the cdrs */ 01531 bridge_cdr = ast_cdr_alloc(); 01532 if (bridge_cdr) { 01533 if (chan->cdr && peer->cdr) { /* both of them? merge */ 01534 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */ 01535 ast_cdr_start(bridge_cdr); /* now is the time to start */ 01536 01537 /* absorb the channel cdr */ 01538 ast_cdr_merge(bridge_cdr, chan->cdr); 01539 ast_cdr_discard(chan->cdr); /* no posting these guys */ 01540 01541 /* absorb the peer cdr */ 01542 ast_cdr_merge(bridge_cdr, peer->cdr); 01543 ast_cdr_discard(peer->cdr); /* no posting these guys */ 01544 peer->cdr = NULL; 01545 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01546 } else if (chan->cdr) { 01547 /* take the cdr from the channel - literally */ 01548 ast_cdr_init(bridge_cdr,chan); 01549 /* absorb this data */ 01550 ast_cdr_merge(bridge_cdr, chan->cdr); 01551 ast_cdr_discard(chan->cdr); /* no posting these guys */ 01552 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01553 } else if (peer->cdr) { 01554 /* take the cdr from the peer - literally */ 01555 ast_cdr_init(bridge_cdr,peer); 01556 /* absorb this data */ 01557 ast_cdr_merge(bridge_cdr, peer->cdr); 01558 ast_cdr_discard(peer->cdr); /* no posting these guys */ 01559 peer->cdr = NULL; 01560 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ 01561 } else { 01562 /* make up a new cdr */ 01563 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */ 01564 chan->cdr = bridge_cdr; /* */ 01565 } 01566 if (ast_strlen_zero(bridge_cdr->dstchannel)) { 01567 if (strcmp(bridge_cdr->channel, peer->name) != 0) 01568 ast_cdr_setdestchan(bridge_cdr, peer->name); 01569 else 01570 ast_cdr_setdestchan(bridge_cdr, chan->name); 01571 } 01572 } 01573 return res; 01574 }
| 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 439 of file res_features.c.
References ast_channel::amaflags, ast_channel_alloc(), ast_channel_masquerade(), ast_frfree(), ast_log(), ast_park_call(), ast_read(), AST_STATE_DOWN, ast_channel::context, ast_channel::exten, f, LOG_WARNING, ast_channel::priority, ast_channel::readformat, set_c_e_p(), and ast_channel::writeformat.
Referenced by manager_park(), mgcp_ss(), parkandannounce_exec(), rpt_exec(), and ss_thread().
00440 { 00441 struct ast_channel *chan; 00442 struct ast_frame *f; 00443 00444 /* Make a new, fake channel that we'll use to masquerade in the real one */ 00445 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) { 00446 ast_log(LOG_WARNING, "Unable to create parked channel\n"); 00447 return -1; 00448 } 00449 00450 /* Make formats okay */ 00451 chan->readformat = rchan->readformat; 00452 chan->writeformat = rchan->writeformat; 00453 ast_channel_masquerade(chan, rchan); 00454 00455 /* Setup the extensions and such */ 00456 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority); 00457 00458 /* Make the masq execute */ 00459 f = ast_read(chan); 00460 if (f) 00461 ast_frfree(f); 00462 00463 ast_park_call(chan, peer, timeout, extout); 00464 return 0; 00465 }
| 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_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con); 00329 return 0; /* Continue execution if possible */ 00330 } 00331 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten)); 00332 } else { 00333 /* Select parking space within range */ 00334 parking_range = parking_stop - parking_start+1; 00335 for (i = 0; i < parking_range; i++) { 00336 x = (i + parking_offset) % parking_range + parking_start; 00337 cur = parkinglot; 00338 while(cur) { 00339 if (cur->parkingnum == x) 00340 break; 00341 cur = cur->next; 00342 } 00343 if (!cur) 00344 break; 00345 } 00346 00347 if (!(i < parking_range)) { 00348 ast_log(LOG_WARNING, "No more parking spaces\n"); 00349 free(pu); 00350 ast_mutex_unlock(&parking_lock); 00351 return -1; 00352 } 00353 /* Set pointer for next parking */ 00354 if (parkfindnext) 00355 parking_offset = x - parking_start + 1; 00356 } 00357 00358 chan->appl = "Parked Call"; 00359 chan->data = NULL; 00360 00361 pu->chan = chan; 00362 00363 /* Put the parked channel on hold if we have two different channels */ 00364 if (chan != peer) { 00365 ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 00366 S_OR(parkmohclass, NULL), 00367 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0); 00368 } 00369 00370 pu->start = ast_tvnow(); 00371 pu->parkingnum = x; 00372 pu->parkingtime = (timeout > 0) ? timeout : parkingtime; 00373 if (extout) 00374 *extout = x; 00375 00376 if (peer) 00377 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername)); 00378 00379 /* Remember what had been dialed, so that if the parking 00380 expires, we try to come back to the same place */ 00381 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context)); 00382 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten)); 00383 pu->priority = chan->macropriority ? chan->macropriority : chan->priority; 00384 pu->next = parkinglot; 00385 parkinglot = pu; 00386 00387 /* If parking a channel directly, don't quiet yet get parking running on it */ 00388 if (peer == chan) 00389 pu->notquiteyet = 1; 00390 ast_mutex_unlock(&parking_lock); 00391 /* Wake up the (presumably select()ing) thread */ 00392 pthread_kill(parking_thread, SIGURG); 00393 if (option_verbose > 1) 00394 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)); 00395 00396 if (pu->parkingnum != -1) 00397 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x); 00398 manager_event(EVENT_FLAG_CALL, "ParkedCall", 00399 "Exten: %s\r\n" 00400 "Channel: %s\r\n" 00401 "From: %s\r\n" 00402 "Timeout: %ld\r\n" 00403 "CallerID: %s\r\n" 00404 "CallerIDName: %s\r\n", 00405 pu->parkingexten, pu->chan->name, peer ? peer->name : "", 00406 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL), 00407 S_OR(pu->chan->cid.cid_num, "<unknown>"), 00408 S_OR(pu->chan->cid.cid_name, "<unknown>") 00409 ); 00410 00411 if (peer && adsipark && ast_adsi_available(peer)) { 00412 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */ 00413 ast_adsi_unload_session(peer); 00414 } 00415 00416 con = ast_context_find(parking_con); 00417 if (!con) 00418 con = ast_context_create(NULL, parking_con, registrar); 00419 if (!con) /* Still no context? Bad */ 00420 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con); 00421 else { /* Add extension to context */ 00422 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free, registrar)) 00423 notify_metermaids(pu->parkingexten, parking_con); 00424 } 00425 /* Tell the peer channel the number of the parking space */ 00426 if (peer && pu->parkingnum != -1) /* Only say number if it's a number */ 00427 ast_say_digits(peer, pu->parkingnum, "", peer->language); 00428 if (pu->notquiteyet) { 00429 /* Wake up parking thread if we're really done */ 00430 ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 00431 S_OR(parkmohclass, NULL), 00432 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0); 00433 pu->notquiteyet = 0; 00434 pthread_kill(parking_thread, SIGURG); 00435 } 00436 return 0; 00437 }
| 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 2108 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().
02109 { 02110 struct ast_channel *cur = NULL; 02111 int res = -1; 02112 02113 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 02114 if (!cur->pbx && 02115 (cur != chan) && 02116 (chan->pickupgroup & cur->callgroup) && 02117 ((cur->_state == AST_STATE_RINGING) || 02118 (cur->_state == AST_STATE_RING))) { 02119 break; 02120 } 02121 ast_channel_unlock(cur); 02122 } 02123 if (cur) { 02124 if (option_debug) 02125 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 02126 res = ast_answer(chan); 02127 if (res) 02128 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 02129 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 02130 if (res) 02131 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 02132 res = ast_channel_masquerade(cur, chan); 02133 if (res) 02134 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 02135 ast_channel_unlock(cur); 02136 } else { 02137 if (option_debug) 02138 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 02139 } 02140 return res; 02141 }
| 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 894 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.
00895 { 00896 if (!feature) { 00897 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 00898 return; 00899 } 00900 00901 AST_LIST_LOCK(&feature_list); 00902 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry); 00903 AST_LIST_UNLOCK(&feature_list); 00904 00905 if (option_verbose >= 2) 00906 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 00907 }
| 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 910 of file res_features.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.
00911 { 00912 if (!feature) 00913 return; 00914 00915 AST_LIST_LOCK(&feature_list); 00916 AST_LIST_REMOVE(&feature_list,feature,feature_entry); 00917 AST_LIST_UNLOCK(&feature_list); 00918 free(feature); 00919 }
1.5.1