Sat Sep 16 07:28:17 2006

Asterisk developer's documentation


features.h File Reference

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

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


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

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

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 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 }

int ast_park_metermaid_add ( void(*)(char *exten, char *context maid,
char *  context 
)

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

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 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

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


Generated on Sat Sep 16 07:28:17 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7