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_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 |
#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 1264 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, featuredigittimeout, ast_option_header::flag, ast_frame::frametype, free, LOG_DEBUG, LOG_WARNING, monitor_app, monitor_ok, 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().
01265 { 01266 /* Copy voice back and forth between the two channels. Give the peer 01267 the ability to transfer calls with '#<extension' syntax. */ 01268 struct ast_frame *f; 01269 struct ast_channel *who; 01270 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 01271 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 01272 int res; 01273 int diff; 01274 int hasfeatures=0; 01275 int hadfeatures=0; 01276 struct ast_option_header *aoh; 01277 struct timeval start = { 0 , 0 }; 01278 struct ast_bridge_config backup_config; 01279 char *monitor_exec; 01280 01281 memset(&backup_config, 0, sizeof(backup_config)); 01282 01283 config->start_time = ast_tvnow(); 01284 01285 if (chan && peer) { 01286 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 01287 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 01288 } else if (chan) 01289 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 01290 01291 if (monitor_ok) { 01292 if (!monitor_app) { 01293 if (!(monitor_app = pbx_findapp("Monitor"))) 01294 monitor_ok=0; 01295 } 01296 if (monitor_app) { 01297 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 01298 pbx_exec(chan, monitor_app, monitor_exec, 1); 01299 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 01300 pbx_exec(peer, monitor_app, monitor_exec, 1); 01301 } 01302 } 01303 01304 set_config_flags(chan, peer, config); 01305 config->firstpass = 1; 01306 01307 /* Answer if need be */ 01308 if (ast_answer(chan)) 01309 return -1; 01310 peer->appl = "Bridged Call"; 01311 peer->data = chan->name; 01312 01313 /* copy the userfield from the B-leg to A-leg if applicable */ 01314 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) { 01315 char tmp[256]; 01316 if (!ast_strlen_zero(chan->cdr->userfield)) { 01317 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield); 01318 ast_cdr_appenduserfield(chan, tmp); 01319 } else 01320 ast_cdr_setuserfield(chan, peer->cdr->userfield); 01321 /* free the peer's cdr without ast_cdr_free complaining */ 01322 free(peer->cdr); 01323 peer->cdr = NULL; 01324 } 01325 for (;;) { 01326 if (config->feature_timer) 01327 start = ast_tvnow(); 01328 01329 res = ast_channel_bridge(chan, peer, config, &f, &who); 01330 01331 if (config->feature_timer) { 01332 /* Update time limit for next pass */ 01333 diff = ast_tvdiff_ms(ast_tvnow(), start); 01334 config->feature_timer -= diff; 01335 if (hasfeatures) { 01336 /* Running on backup config, meaning a feature might be being 01337 activated, but that's no excuse to keep things going 01338 indefinitely! */ 01339 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 01340 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 01341 config->feature_timer = 0; 01342 who = chan; 01343 if (f) 01344 ast_frfree(f); 01345 f = NULL; 01346 res = 0; 01347 } else if (config->feature_timer <= 0) { 01348 /* Not *really* out of time, just out of time for 01349 digits to come in for features. */ 01350 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 01351 if (!ast_strlen_zero(peer_featurecode)) { 01352 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 01353 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 01354 } 01355 if (!ast_strlen_zero(chan_featurecode)) { 01356 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 01357 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 01358 } 01359 if (f) 01360 ast_frfree(f); 01361 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01362 if (!hasfeatures) { 01363 /* Restore original (possibly time modified) bridge config */ 01364 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01365 memset(&backup_config, 0, sizeof(backup_config)); 01366 } 01367 hadfeatures = hasfeatures; 01368 /* Continue as we were */ 01369 continue; 01370 } 01371 } else { 01372 if (config->feature_timer <=0) { 01373 /* We ran out of time */ 01374 config->feature_timer = 0; 01375 who = chan; 01376 if (f) 01377 ast_frfree(f); 01378 f = NULL; 01379 res = 0; 01380 } 01381 } 01382 } 01383 if (res < 0) { 01384 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 01385 return -1; 01386 } 01387 01388 if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 01389 (f->subclass == AST_CONTROL_CONGESTION)))) { 01390 res = -1; 01391 break; 01392 } 01393 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) { 01394 if (who == chan) 01395 ast_indicate(peer, AST_CONTROL_RINGING); 01396 else 01397 ast_indicate(chan, AST_CONTROL_RINGING); 01398 } 01399 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) { 01400 if (who == chan) 01401 ast_indicate(peer, -1); 01402 else 01403 ast_indicate(chan, -1); 01404 } 01405 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) { 01406 if (who == chan) 01407 ast_indicate(peer, AST_CONTROL_FLASH); 01408 else 01409 ast_indicate(chan, AST_CONTROL_FLASH); 01410 } 01411 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) { 01412 aoh = f->data; 01413 /* Forward option Requests */ 01414 if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) { 01415 if (who == chan) 01416 ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0); 01417 else 01418 ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0); 01419 } 01420 } 01421 /* check for '*', if we find it it's time to disconnect */ 01422 if (f && (f->frametype == AST_FRAME_DTMF)) { 01423 char *featurecode; 01424 int sense; 01425 struct ast_channel *other; 01426 01427 hadfeatures = hasfeatures; 01428 /* This cannot overrun because the longest feature is one shorter than our buffer */ 01429 if (who == chan) { 01430 other = peer; 01431 sense = FEATURE_SENSE_CHAN; 01432 featurecode = chan_featurecode; 01433 } else { 01434 other = chan; 01435 sense = FEATURE_SENSE_PEER; 01436 featurecode = peer_featurecode; 01437 } 01438 featurecode[strlen(featurecode)] = f->subclass; 01439 /* Get rid of the frame before we start doing "stuff" with the channels */ 01440 ast_frfree(f); 01441 f = NULL; 01442 config->feature_timer = backup_config.feature_timer; 01443 res = ast_feature_interpret(chan, peer, config, featurecode, sense); 01444 switch(res) { 01445 case FEATURE_RETURN_PASSDIGITS: 01446 ast_dtmf_stream(other, who, featurecode, 0); 01447 /* Fall through */ 01448 case FEATURE_RETURN_SUCCESS: 01449 memset(featurecode, 0, sizeof(chan_featurecode)); 01450 break; 01451 } 01452 if (res >= FEATURE_RETURN_PASSDIGITS) { 01453 res = 0; 01454 } else 01455 break; 01456 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 01457 if (hadfeatures && !hasfeatures) { 01458 /* Restore backup */ 01459 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 01460 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 01461 } else if (hasfeatures) { 01462 if (!hadfeatures) { 01463 /* Backup configuration */ 01464 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 01465 /* Setup temporary config options */ 01466 config->play_warning = 0; 01467 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 01468 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 01469 config->warning_freq = 0; 01470 config->warning_sound = NULL; 01471 config->end_sound = NULL; 01472 config->start_sound = NULL; 01473 config->firstpass = 0; 01474 } 01475 config->start_time = ast_tvnow(); 01476 config->feature_timer = featuredigittimeout; 01477 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 01478 } 01479 } 01480 if (f) 01481 ast_frfree(f); 01482 } 01483 return res; 01484 }
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 401 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().
00402 { 00403 struct ast_channel *chan; 00404 struct ast_frame *f; 00405 00406 /* Make a new, fake channel that we'll use to masquerade in the real one */ 00407 chan = ast_channel_alloc(0); 00408 if (chan) { 00409 /* Let us keep track of the channel name */ 00410 snprintf(chan->name, sizeof (chan->name), "Parked/%s",rchan->name); 00411 00412 /* Make formats okay */ 00413 chan->readformat = rchan->readformat; 00414 chan->writeformat = rchan->writeformat; 00415 ast_channel_masquerade(chan, rchan); 00416 00417 /* Setup the extensions and such */ 00418 ast_copy_string(chan->context, rchan->context, sizeof(chan->context)); 00419 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten)); 00420 chan->priority = rchan->priority; 00421 00422 /* Make the masq execute */ 00423 f = ast_read(chan); 00424 if (f) 00425 ast_frfree(f); 00426 ast_park_call(chan, peer, timeout, extout); 00427 } else { 00428 ast_log(LOG_WARNING, "Unable to create parked channel\n"); 00429 return -1; 00430 } 00431 return 0; 00432 }
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 278 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, 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().
00279 { 00280 struct parkeduser *pu, *cur; 00281 int i,x,parking_range; 00282 char exten[AST_MAX_EXTENSION]; 00283 struct ast_context *con; 00284 00285 pu = malloc(sizeof(struct parkeduser)); 00286 if (!pu) { 00287 ast_log(LOG_WARNING, "Out of memory\n"); 00288 return -1; 00289 } 00290 memset(pu, 0, sizeof(struct parkeduser)); 00291 ast_mutex_lock(&parking_lock); 00292 parking_range = parking_stop - parking_start+1; 00293 for (i = 0; i < parking_range; i++) { 00294 x = (i + parking_offset) % parking_range + parking_start; 00295 cur = parkinglot; 00296 while(cur) { 00297 if (cur->parkingnum == x) 00298 break; 00299 cur = cur->next; 00300 } 00301 if (!cur) 00302 break; 00303 } 00304 00305 if (!(i < parking_range)) { 00306 ast_log(LOG_WARNING, "No more parking spaces\n"); 00307 free(pu); 00308 ast_mutex_unlock(&parking_lock); 00309 return -1; 00310 } 00311 if (parkfindnext) 00312 parking_offset = x - parking_start + 1; 00313 chan->appl = "Parked Call"; 00314 chan->data = NULL; 00315 00316 pu->chan = chan; 00317 /* Start music on hold */ 00318 if (chan != peer) { 00319 ast_indicate(pu->chan, AST_CONTROL_HOLD); 00320 ast_moh_start(pu->chan, NULL); 00321 } 00322 pu->start = ast_tvnow(); 00323 pu->parkingnum = x; 00324 if (timeout > 0) 00325 pu->parkingtime = timeout; 00326 else 00327 pu->parkingtime = parkingtime; 00328 if (extout) 00329 *extout = x; 00330 if (peer) 00331 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername)); 00332 00333 /* Remember what had been dialed, so that if the parking 00334 expires, we try to come back to the same place */ 00335 if (!ast_strlen_zero(chan->macrocontext)) 00336 ast_copy_string(pu->context, chan->macrocontext, sizeof(pu->context)); 00337 else 00338 ast_copy_string(pu->context, chan->context, sizeof(pu->context)); 00339 if (!ast_strlen_zero(chan->macroexten)) 00340 ast_copy_string(pu->exten, chan->macroexten, sizeof(pu->exten)); 00341 else 00342 ast_copy_string(pu->exten, chan->exten, sizeof(pu->exten)); 00343 if (chan->macropriority) 00344 pu->priority = chan->macropriority; 00345 else 00346 pu->priority = chan->priority; 00347 pu->next = parkinglot; 00348 parkinglot = pu; 00349 /* If parking a channel directly, don't quiet yet get parking running on it */ 00350 if (peer == chan) 00351 pu->notquiteyet = 1; 00352 ast_mutex_unlock(&parking_lock); 00353 /* Wake up the (presumably select()ing) thread */ 00354 pthread_kill(parking_thread, SIGURG); 00355 if (option_verbose > 1) 00356 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)); 00357 00358 manager_event(EVENT_FLAG_CALL, "ParkedCall", 00359 "Exten: %d\r\n" 00360 "Channel: %s\r\n" 00361 "From: %s\r\n" 00362 "Timeout: %ld\r\n" 00363 "CallerID: %s\r\n" 00364 "CallerIDName: %s\r\n" 00365 ,pu->parkingnum, pu->chan->name, peer ? peer->name : "" 00366 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL) 00367 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>") 00368 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>") 00369 ); 00370 00371 if (peer) { 00372 if (adsipark && adsi_available(peer)) { 00373 adsi_announce_park(peer, pu->parkingnum); 00374 } 00375 if (adsipark && adsi_available(peer)) { 00376 adsi_unload_session(peer); 00377 } 00378 } 00379 con = ast_context_find(parking_con); 00380 if (!con) { 00381 con = ast_context_create(NULL, parking_con, registrar); 00382 if (!con) { 00383 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con); 00384 } 00385 } 00386 if (con) { 00387 snprintf(exten, sizeof(exten), "%d", x); 00388 ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar); 00389 } 00390 if (peer) 00391 ast_say_digits(peer, pu->parkingnum, "", peer->language); 00392 if (pu->notquiteyet) { 00393 /* Wake up parking thread if we're really done */ 00394 ast_moh_start(pu->chan, NULL); 00395 pu->notquiteyet = 0; 00396 pthread_kill(parking_thread, SIGURG); 00397 } 00398 return 0; 00399 }
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 163 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().
00164 { 00165 return parking_ext; 00166 }
int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 1930 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().
01931 { 01932 struct ast_channel *cur = NULL; 01933 int res = -1; 01934 01935 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 01936 if (!cur->pbx && 01937 (cur != chan) && 01938 (chan->pickupgroup & cur->callgroup) && 01939 ((cur->_state == AST_STATE_RINGING) || 01940 (cur->_state == AST_STATE_RING))) { 01941 break; 01942 } 01943 ast_mutex_unlock(&cur->lock); 01944 } 01945 if (cur) { 01946 if (option_debug) 01947 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name); 01948 res = ast_answer(chan); 01949 if (res) 01950 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 01951 res = ast_queue_control(chan, AST_CONTROL_ANSWER); 01952 if (res) 01953 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 01954 res = ast_channel_masquerade(cur, chan); 01955 if (res) 01956 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */ 01957 ast_mutex_unlock(&cur->lock); 01958 } else { 01959 if (option_debug) 01960 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 01961 } 01962 return res; 01963 }
char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 168 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().
00169 { 00170 return pickup_ext; 00171 }
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 875 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().
00876 { 00877 if (!feature) { 00878 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 00879 return; 00880 } 00881 00882 AST_LIST_LOCK(&feature_list); 00883 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry); 00884 AST_LIST_UNLOCK(&feature_list); 00885 00886 if (option_verbose >= 2) 00887 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 00888 }
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 891 of file res_features.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.
00892 { 00893 if (!feature) return; 00894 00895 AST_LIST_LOCK(&feature_list); 00896 AST_LIST_REMOVE(&feature_list,feature,feature_entry); 00897 AST_LIST_UNLOCK(&feature_list); 00898 free(feature); 00899 }