Sun Aug 6 15:10:42 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

features.h File Reference

Call Parking and Pickup API Includes code and algorithms from the Zapata library. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

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


Detailed Description

Call Parking and Pickup API Includes code and algorithms from the Zapata library.

Definition in file features.h.


Define Documentation

#define FEATURE_APP_ARGS_LEN   256
 

Definition at line 29 of file features.h.

Referenced by load_config().

#define FEATURE_APP_LEN   64
 

Definition at line 28 of file features.h.

Referenced by load_config().

#define FEATURE_EXTEN_LEN   32
 

Definition at line 31 of file features.h.

Referenced by load_config().

#define FEATURE_MAX_LEN   11
 

Definition at line 27 of file features.h.

Referenced by ast_bridge_call().

#define FEATURE_SNAME_LEN   32
 

Definition at line 30 of file features.h.

Referenced by load_config().


Function Documentation

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 1261 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, ast_channel::data, ast_frame::data, ast_option_header::data, ast_frame::datalen, ast_bridge_config::end_sound, FEATURE_MAX_LEN, FEATURE_RETURN_PASSDIGITS, FEATURE_RETURN_SUCCESS, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_bridge_config::feature_timer, featuredigittimeout, ast_bridge_config::features_callee, ast_bridge_config::features_caller, ast_bridge_config::firstpass, ast_option_header::flag, ast_frame::frametype, free, LOG_DEBUG, LOG_WARNING, monitor_ok, ast_channel::name, ast_option_header::option, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), ast_bridge_config::play_warning, set_config_flags(), ast_bridge_config::start_sound, ast_bridge_config::start_time, ast_frame::subclass, ast_cdr::userfield, ast_bridge_config::warning_freq, and ast_bridge_config::warning_sound.

Referenced by ast_bridge_call_thread(), builtin_atxfer(), dial_exec_full(), park_exec(), and try_calling().

01262 {
01263    /* Copy voice back and forth between the two channels.  Give the peer
01264       the ability to transfer calls with '#<extension' syntax. */
01265    struct ast_frame *f;
01266    struct ast_channel *who;
01267    char chan_featurecode[FEATURE_MAX_LEN + 1]="";
01268    char peer_featurecode[FEATURE_MAX_LEN + 1]="";
01269    int res;
01270    int diff;
01271    int hasfeatures=0;
01272    int hadfeatures=0;
01273    struct ast_option_header *aoh;
01274    struct timeval start = { 0 , 0 };
01275    struct ast_bridge_config backup_config;
01276    char *monitor_exec;
01277 
01278    memset(&backup_config, 0, sizeof(backup_config));
01279 
01280    config->start_time = ast_tvnow();
01281 
01282    if (chan && peer) {
01283       pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
01284       pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
01285    } else if (chan)
01286       pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
01287 
01288    if (monitor_ok) {
01289       if (!monitor_app) { 
01290          if (!(monitor_app = pbx_findapp("Monitor")))
01291             monitor_ok=0;
01292       }
01293       if (monitor_app) {
01294          if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
01295             pbx_exec(chan, monitor_app, monitor_exec, 1);
01296          else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
01297             pbx_exec(peer, monitor_app, monitor_exec, 1);
01298       }
01299    }
01300    
01301    set_config_flags(chan, peer, config);
01302    config->firstpass = 1;
01303 
01304    /* Answer if need be */
01305    if (ast_answer(chan))
01306       return -1;
01307    peer->appl = "Bridged Call";
01308    peer->data = chan->name;
01309 
01310    /* copy the userfield from the B-leg to A-leg if applicable */
01311    if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
01312       char tmp[256];
01313       if (!ast_strlen_zero(chan->cdr->userfield)) {
01314          snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
01315          ast_cdr_appenduserfield(chan, tmp);
01316       } else
01317          ast_cdr_setuserfield(chan, peer->cdr->userfield);
01318       /* free the peer's cdr without ast_cdr_free complaining */
01319       free(peer->cdr);
01320       peer->cdr = NULL;
01321    }
01322    for (;;) {
01323       if (config->feature_timer)
01324          start = ast_tvnow();
01325 
01326       res = ast_channel_bridge(chan, peer, config, &f, &who);
01327 
01328       if (config->feature_timer) {
01329          /* Update time limit for next pass */
01330          diff = ast_tvdiff_ms(ast_tvnow(), start);
01331          config->feature_timer -= diff;
01332          if (hasfeatures) {
01333             /* Running on backup config, meaning a feature might be being
01334                activated, but that's no excuse to keep things going 
01335                indefinitely! */
01336             if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
01337                ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
01338                config->feature_timer = 0;
01339                who = chan;
01340                if (f)
01341                   ast_frfree(f);
01342                f = NULL;
01343                res = 0;
01344             } else if (config->feature_timer <= 0) {
01345                /* Not *really* out of time, just out of time for
01346                   digits to come in for features. */
01347                ast_log(LOG_DEBUG, "Timed out for feature!\n");
01348                if (!ast_strlen_zero(peer_featurecode)) {
01349                   ast_dtmf_stream(chan, peer, peer_featurecode, 0);
01350                   memset(peer_featurecode, 0, sizeof(peer_featurecode));
01351                }
01352                if (!ast_strlen_zero(chan_featurecode)) {
01353                   ast_dtmf_stream(peer, chan, chan_featurecode, 0);
01354                   memset(chan_featurecode, 0, sizeof(chan_featurecode));
01355                }
01356                if (f)
01357                   ast_frfree(f);
01358                hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01359                if (!hasfeatures) {
01360                   /* Restore original (possibly time modified) bridge config */
01361                   memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01362                   memset(&backup_config, 0, sizeof(backup_config));
01363                }
01364                hadfeatures = hasfeatures;
01365                /* Continue as we were */
01366                continue;
01367             }
01368          } else {
01369             if (config->feature_timer <=0) {
01370                /* We ran out of time */
01371                config->feature_timer = 0;
01372                who = chan;
01373                if (f)
01374                   ast_frfree(f);
01375                f = NULL;
01376                res = 0;
01377             }
01378          }
01379       }
01380       if (res < 0) {
01381          ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
01382          return -1;
01383       }
01384       
01385       if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 
01386          (f->subclass == AST_CONTROL_CONGESTION)))) {
01387             res = -1;
01388             break;
01389       }
01390       if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
01391          if (who == chan)
01392             ast_indicate(peer, AST_CONTROL_RINGING);
01393          else
01394             ast_indicate(chan, AST_CONTROL_RINGING);
01395       }
01396       if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) {
01397          if (who == chan)
01398             ast_indicate(peer, -1);
01399          else
01400             ast_indicate(chan, -1);
01401       }
01402       if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) {
01403          if (who == chan)
01404             ast_indicate(peer, AST_CONTROL_FLASH);
01405          else
01406             ast_indicate(chan, AST_CONTROL_FLASH);
01407       }
01408       if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
01409          aoh = f->data;
01410          /* Forward option Requests */
01411          if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
01412             if (who == chan)
01413                ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
01414             else
01415                ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
01416          }
01417       }
01418       /* check for '*', if we find it it's time to disconnect */
01419       if (f && (f->frametype == AST_FRAME_DTMF)) {
01420          char *featurecode;
01421          int sense;
01422          struct ast_channel *other;
01423 
01424          hadfeatures = hasfeatures;
01425          /* This cannot overrun because the longest feature is one shorter than our buffer */
01426          if (who == chan) {
01427             other = peer;
01428             sense = FEATURE_SENSE_CHAN;
01429             featurecode = chan_featurecode;
01430          } else  {
01431             other = chan;
01432             sense = FEATURE_SENSE_PEER;
01433             featurecode = peer_featurecode;
01434          }
01435          featurecode[strlen(featurecode)] = f->subclass;
01436          /* Get rid of the frame before we start doing "stuff" with the channels */
01437          ast_frfree(f);
01438          f = NULL;
01439          config->feature_timer = backup_config.feature_timer;
01440          res = ast_feature_interpret(chan, peer, config, featurecode, sense);
01441          switch(res) {
01442          case FEATURE_RETURN_PASSDIGITS:
01443             ast_dtmf_stream(other, who, featurecode, 0);
01444             /* Fall through */
01445          case FEATURE_RETURN_SUCCESS:
01446             memset(featurecode, 0, sizeof(chan_featurecode));
01447             break;
01448          }
01449          if (res >= FEATURE_RETURN_PASSDIGITS) {
01450             res = 0;
01451          } else 
01452             break;
01453          hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01454          if (hadfeatures && !hasfeatures) {
01455             /* Restore backup */
01456             memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01457             memset(&backup_config, 0, sizeof(struct ast_bridge_config));
01458          } else if (hasfeatures) {
01459             if (!hadfeatures) {
01460                /* Backup configuration */
01461                memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
01462                /* Setup temporary config options */
01463                config->play_warning = 0;
01464                ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
01465                ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
01466                config->warning_freq = 0;
01467                config->warning_sound = NULL;
01468                config->end_sound = NULL;
01469                config->start_sound = NULL;
01470                config->firstpass = 0;
01471             }
01472             config->feature_timer = featuredigittimeout;
01473             ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
01474          }
01475       }
01476       if (f)
01477          ast_frfree(f);
01478    }
01479    return res;
01480 }

int ast_masq_park_call struct ast_channel rchan,
struct ast_channel host,
int  timeout,
int *  extout
 

Park a call via a masqueraded channel.

Parameters:
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.

Parameters:
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(), adsipark, 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, parkedcall, parkfindnext, parking_con, parking_offset, parking_start, parking_stop, parking_thread, parkeduser::parkingnum, parkeduser::parkingtime, parkingtime, parkeduser::peername, parkeduser::priority, ast_channel::priority, registrar, 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.

References parking_ext.

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 1926 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().

01927 {
01928    struct ast_channel *cur = NULL;
01929    int res = -1;
01930 
01931    while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
01932       if (!cur->pbx && 
01933          (cur != chan) &&
01934          (chan->pickupgroup & cur->callgroup) &&
01935          ((cur->_state == AST_STATE_RINGING) ||
01936           (cur->_state == AST_STATE_RING))) {
01937             break;
01938       }
01939       ast_mutex_unlock(&cur->lock);
01940    }
01941    if (cur) {
01942       if (option_debug)
01943          ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
01944       res = ast_answer(chan);
01945       if (res)
01946          ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
01947       res = ast_queue_control(chan, AST_CONTROL_ANSWER);
01948       if (res)
01949          ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
01950       res = ast_channel_masquerade(cur, chan);
01951       if (res)
01952          ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);     /* Done */
01953       ast_mutex_unlock(&cur->lock);
01954    } else   {
01955       if (option_debug)
01956          ast_log(LOG_DEBUG, "No call pickup possible...\n");
01957    }
01958    return res;
01959 }

char* ast_pickup_ext void   ) 
 

Determine system call pickup extension.

Definition at line 168 of file res_features.c.

References pickup_ext.

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

Parameters:
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 872 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().

00873 {
00874    if (!feature) {
00875       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
00876          return;
00877    }
00878   
00879    AST_LIST_LOCK(&feature_list);
00880    AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
00881    AST_LIST_UNLOCK(&feature_list);
00882 
00883    if (option_verbose >= 2) 
00884       ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
00885 }

void ast_unregister_feature struct ast_call_feature feature  ) 
 

unregister feature from feature_set

Parameters:
feature the ast_call_feature object which was registered before

Definition at line 888 of file res_features.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.

00889 {
00890    if (!feature) return;
00891 
00892    AST_LIST_LOCK(&feature_list);
00893    AST_LIST_REMOVE(&feature_list,feature,feature_entry);
00894    AST_LIST_UNLOCK(&feature_list);
00895    free(feature);
00896 }


Generated on Sun Aug 6 15:10:43 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2