Sun Dec 18 20:55:50 2011

Asterisk developer's documentation


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.

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_autoanswer_login (struct ast_channel *chan, void *data)
int ast_bridge_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
 Bridge a call, optionally allowing redirection.
struct ast_channelast_get_holded_call (char *uniqueid)
int ast_hold_call (struct ast_channel *chan, struct ast_channel *host)
int ast_masq_autoanswer_login (struct ast_channel *rchan, void *data)
int ast_masq_hold_call (struct ast_channel *rchan, struct ast_channel *host)
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
int ast_retrieve_call (struct ast_channel *chan, char *uniqueid)
int ast_retrieve_call_to_death (char *uniqueid)
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_MOH_LEN   80

Definition at line 32 of file features.h.

Referenced by load_config().

#define FEATURE_SNAME_LEN   32

Definition at line 30 of file features.h.

Referenced by load_config().


Function Documentation

int ast_autoanswer_login ( struct ast_channel chan,
void *  data 
)

Definition at line 2767 of file res_features.c.

References ast_channel::_state, ast_channel::appl, ast_add_extension2(), ast_answer(), ast_context_create(), ast_context_find(), ast_hangup(), ast_log(), AST_MAX_EXTENSION, ast_moh_start(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, ast_strdupa, ast_verbose(), aauser::chan, aauser::context, ast_channel::data, EVENT_FLAG_CALL, aauser::exten, exten, free, LOG_ERROR, LOG_NOTICE, LOG_WARNING, malloc, manager_event(), aauser::next, option_verbose, s, aauser::start, strdup, strsep(), and VERBOSE_PREFIX_2.

Referenced by ast_masq_autoanswer_login(), and autoanswer_exec().

02768 {
02769    /* We put the user in the parking list, then wake up the parking thread to be sure it looks
02770       after these channels too */
02771    struct ast_context *con;
02772    char exten[AST_MAX_EXTENSION];
02773    struct aauser *pu,*pl = NULL;
02774    char *s, *stringp, *aacontext, *aaexten = NULL;
02775 
02776    s = ast_strdupa((void *) data);
02777    stringp=s;
02778    aacontext = strsep(&stringp, "|");
02779    aaexten = strsep(&stringp, "|");
02780    if (!aaexten) {
02781        aaexten = aacontext;
02782        aacontext = NULL;
02783    }
02784    if (!aaexten) {
02785       ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
02786       return -1;
02787    } else {
02788       if (!aacontext) {
02789          aacontext = "default";
02790       }
02791    }
02792 
02793    ast_mutex_lock(&autoanswer_lock);
02794    pu = aalot;
02795    while(pu) {
02796       if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
02797          if (pl)
02798             pl->next = pu->next;
02799          else
02800             aalot = pu->next;
02801          break;
02802       }
02803       pl = pu;
02804       pu = pu->next;
02805    }
02806    ast_mutex_unlock(&autoanswer_lock);
02807    if (pu) {
02808        ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
02809        manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
02810                                "Channel: %s\r\n"
02811                                "Uniqueid: %s\r\n"
02812                                "Context: %s\r\n"
02813                                "Exten: %s\r\n"
02814                            ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
02815        ast_hangup(pu->chan);
02816        free(pu);
02817    }
02818    pu = malloc(sizeof(struct aauser));
02819    if (pu) {
02820       memset(pu, 0, sizeof(pu));
02821       ast_mutex_lock(&autoanswer_lock);
02822       chan->appl = "Autoanswer";
02823       chan->data = NULL;
02824 
02825       pu->chan = chan;
02826       if (chan->_state != AST_STATE_UP) {
02827           ast_answer(chan);
02828       }
02829 
02830       /* Start music on hold */
02831       ast_moh_start(pu->chan, NULL, NULL);
02832       gettimeofday(&pu->start, NULL);
02833       strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
02834       strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
02835       pu->next = aalot;
02836       aalot = pu;
02837       con = ast_context_find(aacontext);
02838       if (!con) {
02839          con = ast_context_create(NULL,aacontext, registrar);
02840          if (!con) {
02841             ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
02842          }
02843       }
02844       if (con) {
02845          snprintf(exten, sizeof(exten), "%s", aaexten);
02846          ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
02847       }
02848 
02849       ast_mutex_unlock(&autoanswer_lock);
02850       /* Wake up the (presumably select()ing) thread */
02851       pthread_kill(autoanswer_thread, SIGURG);
02852       if (option_verbose > 1)
02853          ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
02854          manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
02855                                 "Channel: %s\r\n"
02856                                 "Uniqueid: %s\r\n"
02857                "Context: %s\r\n"
02858                         "Exten: %s\r\n"
02859                         ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
02860 
02861          return 0;
02862    } else {
02863       ast_log(LOG_WARNING, "Out of memory\n");
02864       return -1;
02865    }
02866    return 0;
02867 }

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.

Todo:
XXX how do we guarantee the latter ?

Definition at line 1437 of file res_features.c.

References ast_channel::appl, ast_answer(), ast_cdr_alloc(), ast_cdr_appenduserfield(), ast_cdr_discard(), AST_CDR_FLAG_LOCKED, ast_cdr_init(), ast_cdr_merge(), ast_cdr_setdestchan(), ast_cdr_setuserfield(), ast_cdr_start(), ast_channel_bridge(), ast_channel_lock, ast_channel_setoption(), ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OPTION, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_dtmf_stream(), ast_feature_interpret(), AST_FEATURE_PLAY_WARNING, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, ast_frfree, ast_indicate(), ast_indicate_data(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_FLAG_REQUEST, AST_OPTION_RELAXDTMF, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, ast_cdr::channel, ast_option_header::data, ast_frame::data, ast_channel::data, ast_frame::datalen, ast_cdr::dstchannel, ast_bridge_config::end_sound, f, FEATURE_MAX_LEN, FEATURE_RETURN_PASSDIGITS, FEATURE_RETURN_SUCCESS, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_bridge_config::feature_timer, 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, ast_option_header::option, option_debug, 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 app_exec(), ast_bridge_call_thread(), ast_retrieve_call(), autoanswer_exec(), bridge_exec(), builtin_atxfer(), park_exec(), and try_calling().

01438 {
01439    /* Copy voice back and forth between the two channels.  Give the peer
01440       the ability to transfer calls with '#<extension' syntax. */
01441    struct ast_frame *f;
01442    struct ast_channel *who;
01443    char chan_featurecode[FEATURE_MAX_LEN + 1]="";
01444    char peer_featurecode[FEATURE_MAX_LEN + 1]="";
01445    int res;
01446    int diff;
01447    int hasfeatures=0;
01448    int hadfeatures=0;
01449    struct ast_option_header *aoh;
01450    struct ast_bridge_config backup_config;
01451    struct ast_cdr *bridge_cdr;
01452 
01453    memset(&backup_config, 0, sizeof(backup_config));
01454 
01455    config->start_time = ast_tvnow();
01456 
01457    if (chan && peer) {
01458       pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
01459       pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
01460    } else if (chan)
01461       pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
01462 
01463    if (monitor_ok) {
01464       const char *monitor_exec;
01465       struct ast_channel *src = NULL;
01466       if (!monitor_app) { 
01467          if (!(monitor_app = pbx_findapp("Monitor")))
01468             monitor_ok=0;
01469       }
01470       if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
01471          src = chan;
01472       else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
01473          src = peer;
01474       if (monitor_app && src) {
01475          char *tmp = ast_strdupa(monitor_exec);
01476          pbx_exec(src, monitor_app, tmp);
01477       }
01478    }
01479    
01480    set_config_flags(chan, peer, config);
01481    config->firstpass = 1;
01482 
01483    /* Answer if need be */
01484    if (ast_answer(chan))
01485       return -1;
01486    peer->appl = "Bridged Call";
01487    peer->data = chan->name;
01488 
01489    /* copy the userfield from the B-leg to A-leg if applicable */
01490    if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
01491       char tmp[256];
01492       if (!ast_strlen_zero(chan->cdr->userfield)) {
01493          snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
01494          ast_cdr_appenduserfield(chan, tmp);
01495       } else
01496          ast_cdr_setuserfield(chan, peer->cdr->userfield);
01497       /* free the peer's cdr without ast_cdr_free complaining */
01498       free(peer->cdr);
01499       peer->cdr = NULL;
01500    }
01501 
01502    for (;;) {
01503       struct ast_channel *other; /* used later */
01504 
01505       res = ast_channel_bridge(chan, peer, config, &f, &who);
01506 
01507       if (config->feature_timer) {
01508          /* Update time limit for next pass */
01509          diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
01510          config->feature_timer -= diff;
01511          if (hasfeatures) {
01512             /* Running on backup config, meaning a feature might be being
01513                activated, but that's no excuse to keep things going 
01514                indefinitely! */
01515             if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
01516                if (option_debug)
01517                   ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
01518                config->feature_timer = 0;
01519                who = chan;
01520                if (f)
01521                   ast_frfree(f);
01522                f = NULL;
01523                res = 0;
01524             } else if (config->feature_timer <= 0) {
01525                /* Not *really* out of time, just out of time for
01526                   digits to come in for features. */
01527                if (option_debug)
01528                   ast_log(LOG_DEBUG, "Timed out for feature!\n");
01529                if (!ast_strlen_zero(peer_featurecode)) {
01530                   ast_dtmf_stream(chan, peer, peer_featurecode, 0);
01531                   memset(peer_featurecode, 0, sizeof(peer_featurecode));
01532                }
01533                if (!ast_strlen_zero(chan_featurecode)) {
01534                   ast_dtmf_stream(peer, chan, chan_featurecode, 0);
01535                   memset(chan_featurecode, 0, sizeof(chan_featurecode));
01536                }
01537                if (f)
01538                   ast_frfree(f);
01539                hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01540                if (!hasfeatures) {
01541                   /* Restore original (possibly time modified) bridge config */
01542                   memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01543                   memset(&backup_config, 0, sizeof(backup_config));
01544                }
01545                hadfeatures = hasfeatures;
01546                /* Continue as we were */
01547                continue;
01548             } else if (!f) {
01549                /* The bridge returned without a frame and there is a feature in progress.
01550                 * However, we don't think the feature has quite yet timed out, so just
01551                 * go back into the bridge. */
01552                continue;
01553             }
01554          } else {
01555             if (config->feature_timer <=0) {
01556                /* We ran out of time */
01557                config->feature_timer = 0;
01558                who = chan;
01559                if (f)
01560                   ast_frfree(f);
01561                f = NULL;
01562                res = 0;
01563             }
01564          }
01565       }
01566       if (res < 0) {
01567          if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
01568             ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
01569          return -1;
01570       }
01571       
01572       if (!f || (f->frametype == AST_FRAME_CONTROL &&
01573             (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 
01574                f->subclass == AST_CONTROL_CONGESTION ) ) ) {
01575          res = -1;
01576          break;
01577       }
01578       /* many things should be sent to the 'other' channel */
01579       other = (who == chan) ? peer : chan;
01580       if (f->frametype == AST_FRAME_CONTROL) {
01581          switch (f->subclass) {
01582          case AST_CONTROL_RINGING:
01583          case AST_CONTROL_FLASH:
01584          case -1:
01585             ast_indicate(other, f->subclass);
01586             break;
01587          case AST_CONTROL_HOLD:
01588          case AST_CONTROL_UNHOLD:
01589             ast_indicate_data(other, f->subclass, f->data, f->datalen);
01590             break;
01591          case AST_CONTROL_OPTION:
01592             aoh = f->data;
01593             /* Forward option Requests, but only ones we know are safe
01594              * These are ONLY sent by chan_iax2 and I'm not convinced that
01595              * they are useful. I haven't deleted them entirely because I
01596              * just am not sure of the ramifications of removing them. */
01597             if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
01598                   switch (ntohs(aoh->option)) {
01599                case AST_OPTION_TONE_VERIFY:
01600                case AST_OPTION_TDD:
01601                case AST_OPTION_RELAXDTMF:
01602                case AST_OPTION_AUDIO_MODE:
01603                   ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 
01604                      f->datalen - sizeof(struct ast_option_header), 0);
01605                }
01606             }
01607             break;
01608          }
01609       } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
01610          /* eat it */
01611       } else if (f->frametype == AST_FRAME_DTMF) {
01612          char *featurecode;
01613          int sense;
01614 
01615          hadfeatures = hasfeatures;
01616          /* This cannot overrun because the longest feature is one shorter than our buffer */
01617          if (who == chan) {
01618             sense = FEATURE_SENSE_CHAN;
01619             featurecode = chan_featurecode;
01620          } else  {
01621             sense = FEATURE_SENSE_PEER;
01622             featurecode = peer_featurecode;
01623          }
01624          /*! append the event to featurecode. we rely on the string being zero-filled, and
01625           * not overflowing it. 
01626           * \todo XXX how do we guarantee the latter ?
01627           */
01628          featurecode[strlen(featurecode)] = f->subclass;
01629          /* Get rid of the frame before we start doing "stuff" with the channels */
01630          ast_frfree(f);
01631          f = NULL;
01632          config->feature_timer = backup_config.feature_timer;
01633          res = ast_feature_interpret(chan, peer, config, featurecode, sense);
01634          switch(res) {
01635          case FEATURE_RETURN_PASSDIGITS:
01636             ast_dtmf_stream(other, who, featurecode, 0);
01637             /* Fall through */
01638          case FEATURE_RETURN_SUCCESS:
01639             memset(featurecode, 0, sizeof(chan_featurecode));
01640             break;
01641          }
01642          if (res >= FEATURE_RETURN_PASSDIGITS) {
01643             res = 0;
01644          } else 
01645             break;
01646          hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01647          if (hadfeatures && !hasfeatures) {
01648             /* Restore backup */
01649             memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01650             memset(&backup_config, 0, sizeof(struct ast_bridge_config));
01651          } else if (hasfeatures) {
01652             if (!hadfeatures) {
01653                /* Backup configuration */
01654                memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
01655                /* Setup temporary config options */
01656                config->play_warning = 0;
01657                ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
01658                ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
01659                config->warning_freq = 0;
01660                config->warning_sound = NULL;
01661                config->end_sound = NULL;
01662                config->start_sound = NULL;
01663                config->firstpass = 0;
01664             }
01665             config->start_time = ast_tvnow();
01666             config->feature_timer = featuredigittimeout;
01667             if (option_debug)
01668                ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
01669          }
01670       }
01671       if (f)
01672          ast_frfree(f);
01673 
01674    }
01675 
01676    /* arrange the cdrs */
01677    bridge_cdr = ast_cdr_alloc();
01678    if (bridge_cdr) {
01679       if (chan->cdr && peer->cdr) { /* both of them? merge */
01680          ast_channel_lock(chan);  /* lock the channel before modifing cdrs */
01681          ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the  destination as a base, but, really, it's random */
01682          ast_cdr_start(bridge_cdr); /* now is the time to start */
01683 
01684          /* absorb the channel cdr */
01685          ast_cdr_merge(bridge_cdr, chan->cdr);
01686          if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) 
01687             ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
01688 
01689          chan->cdr = NULL; /* remove pointer to freed memory before releasing the lock */
01690 
01691          ast_channel_unlock(chan);
01692          
01693          /* absorb the peer cdr */
01694          ast_channel_lock(peer);
01695          ast_cdr_merge(bridge_cdr, peer->cdr);
01696          if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
01697             ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */
01698          
01699          peer->cdr = NULL;
01700          ast_channel_unlock(peer);
01701 
01702          ast_channel_lock(chan);
01703          chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
01704          ast_channel_unlock(chan);
01705 
01706       } else if (chan->cdr) {
01707 
01708          ast_channel_lock(chan); /* Lock before modifying CDR */
01709          /* take the cdr from the channel - literally */
01710          ast_cdr_init(bridge_cdr,chan);
01711          /* absorb this data */
01712          ast_cdr_merge(bridge_cdr, chan->cdr);
01713          if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
01714             ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
01715          chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
01716          ast_channel_unlock(chan);
01717       } else if (peer->cdr) {
01718          ast_channel_lock(peer); /* Lock before modifying CDR */
01719          /* take the cdr from the peer - literally */
01720          ast_cdr_init(bridge_cdr,peer);
01721          /* absorb this data */
01722          ast_cdr_merge(bridge_cdr, peer->cdr);
01723          if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
01724             ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
01725          peer->cdr = NULL;
01726          peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
01727          ast_channel_unlock(peer);
01728       } else {
01729          ast_channel_lock(chan); /* Lock before modifying CDR */
01730          /* make up a new cdr */
01731          ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
01732          chan->cdr = bridge_cdr; /*  */
01733          ast_channel_unlock(chan);
01734       }
01735       if (ast_strlen_zero(bridge_cdr->dstchannel)) {
01736          if (strcmp(bridge_cdr->channel, peer->name) != 0)
01737             ast_cdr_setdestchan(bridge_cdr, peer->name);
01738          else
01739             ast_cdr_setdestchan(bridge_cdr, chan->name);
01740       }
01741    }
01742    return res;
01743 }

struct ast_channel* ast_get_holded_call ( char *  uniqueid  )  [read]

Definition at line 2252 of file res_features.c.

References ast_get_channel_by_uniqueid_locked(), ast_log(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, LOG_WARNING, holdeduser::next, option_verbose, holdeduser::uniqueid, and VERBOSE_PREFIX_3.

Referenced by ast_retrieve_call(), and ast_retrieve_call_to_death().

02253 {
02254    int res=-1;
02255    struct ast_channel *peer=NULL;
02256    struct holdeduser *pu, *pl=NULL;
02257 
02258    ast_mutex_lock(&holding_lock);
02259    pu = holdlist;
02260    while(pu) {
02261       if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
02262          if (pl)
02263             pl->next = pu->next;
02264          else
02265             holdlist = pu->next;
02266          break;
02267       }
02268       pl = pu;
02269       pu = pu->next;
02270    }
02271    ast_mutex_unlock(&holding_lock);
02272    if (pu) {
02273       peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
02274       free(pu);
02275       if (peer) {
02276           res=0;
02277           if (option_verbose > 2)
02278          ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
02279           ast_moh_stop(peer);
02280           return peer;
02281       } else {
02282           if (option_verbose > 2)
02283          ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
02284           return NULL;
02285       }
02286    } else {
02287       ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
02288    }
02289    return NULL;
02290 }

int ast_hold_call ( struct ast_channel chan,
struct ast_channel host 
)

Definition at line 2110 of file res_features.c.

References ast_channel::appl, ast_log(), ast_moh_start(), ast_mutex_lock(), ast_mutex_unlock(), holdeduser::chan, ast_channel::data, EVENT_FLAG_CALL, LOG_WARNING, malloc, manager_event(), holdeduser::next, holdeduser::start, holdeduser::uniqueid, and holdeduser::uniqueidpeer.

Referenced by ast_masq_hold_call().

02111 {
02112    /* We put the user in the parking list, then wake up the parking thread to be sure it looks
02113       after these channels too */
02114    struct holdeduser *pu;
02115    pu = malloc(sizeof(struct holdeduser));
02116    if (pu) {
02117       memset(pu, 0, sizeof(pu));
02118       ast_mutex_lock(&holding_lock);
02119       chan->appl = "Holded Call";
02120       chan->data = NULL;
02121 
02122       pu->chan = chan;
02123       strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
02124       strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
02125       /* Start music on hold */
02126       ast_moh_start(pu->chan, NULL, NULL);
02127       gettimeofday(&pu->start, NULL);
02128       pu->next = holdlist;
02129       holdlist = pu;
02130       ast_mutex_unlock(&holding_lock);
02131       /* Wake up the (presumably select()ing) thread */
02132       pthread_kill(holding_thread, SIGURG);
02133 
02134       manager_event(EVENT_FLAG_CALL, "HoldedCall",
02135                          "Channel1: %s\r\n"
02136                          "Channel2: %s\r\n"
02137                       "Uniqueid1: %s\r\n"
02138                       "Uniqueid2: %s\r\n"
02139                              ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
02140 
02141    } else {
02142       ast_log(LOG_WARNING, "Out of memory\n");
02143       return -1;
02144    }
02145    return 0;
02146 }

int ast_masq_autoanswer_login ( struct ast_channel rchan,
void *  data 
)

Definition at line 2721 of file res_features.c.

References ast_autoanswer_login(), ast_channel_alloc(), ast_channel_masquerade(), ast_frfree, ast_log(), ast_read(), AST_STATE_DOWN, ast_string_field_build, ast_channel::context, ast_channel::exten, f, LOG_WARNING, name, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.

Referenced by autoanswer_login_exec().

02722 {
02723    struct ast_channel *chan;
02724    struct ast_frame *f;
02725    /* Make a new, fake channel that we'll use to masquerade in the real one */
02726    chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name);
02727    if (chan) {
02728       /* Let us keep track of the channel name */
02729       ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name);
02730       /* Make formats okay */
02731       chan->readformat = rchan->readformat;
02732       chan->writeformat = rchan->writeformat;
02733       ast_channel_masquerade(chan, rchan);
02734       /* Setup the extensions and such */
02735       strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
02736       strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
02737       chan->priority = rchan->priority;
02738       /* might be dirty but we want trackable channels */
02739       ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
02740       /* Make the masq execute */
02741       f = ast_read(chan);
02742       if (f)
02743          ast_frfree(f);
02744       ast_autoanswer_login(chan, data);
02745    } else {
02746       ast_log(LOG_WARNING, "Unable to create aa channel\n");
02747       return -1;
02748    }
02749    return 0;
02750 }

int ast_masq_hold_call ( struct ast_channel rchan,
struct ast_channel host 
)

Definition at line 2148 of file res_features.c.

References ast_channel_alloc(), ast_channel_masquerade(), ast_frfree, ast_hold_call(), ast_log(), ast_read(), AST_STATE_DOWN, ast_string_field_build, ast_channel::context, ast_channel::exten, f, LOG_WARNING, name, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.

02149 {
02150    struct ast_channel *chan;
02151    struct ast_frame *f;
02152    /* Make a new, fake channel that we'll use to masquerade in the real one */
02153    chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name);
02154    if (chan) {
02155       /* Let us keep track of the channel name */
02156       ast_string_field_build(chan, name, "Onhold/%s",rchan->name);
02157       /* Make formats okay */
02158       chan->readformat = rchan->readformat;
02159       chan->writeformat = rchan->writeformat;
02160       ast_channel_masquerade(chan, rchan);
02161       /* Setup the extensions and such */
02162       strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
02163       strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
02164       chan->priority = rchan->priority;
02165       /* this might be dirty, but we need to preserve the uniqueid */
02166       ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
02167       /* Make the masq execute */
02168       f = ast_read(chan);
02169       if (f)
02170          ast_frfree(f);
02171       ast_hold_call(chan, peer);
02172       return -1;
02173    } else {
02174       ast_log(LOG_WARNING, "Unable to create holded channel\n");
02175       return -1;
02176    }
02177    return 0;
02178 }

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 538 of file res_features.c.

References ast_channel::amaflags, ast_channel_alloc(), ast_channel_masquerade(), ast_frfree, ast_log(), ast_read(), AST_STATE_DOWN, ast_strdupa, ast_channel::context, ast_channel::exten, f, LOG_WARNING, park_call_full(), 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().

00539 {
00540    struct ast_channel *chan;
00541    struct ast_frame *f;
00542    char *orig_chan_name = NULL;
00543 
00544    /* Make a new, fake channel that we'll use to masquerade in the real one */
00545    if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
00546       ast_log(LOG_WARNING, "Unable to create parked channel\n");
00547       return -1;
00548    }
00549 
00550    /* Make formats okay */
00551    chan->readformat = rchan->readformat;
00552    chan->writeformat = rchan->writeformat;
00553    ast_channel_masquerade(chan, rchan);
00554 
00555    /* Setup the extensions and such */
00556    set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
00557 
00558    /* Make the masq execute */
00559    f = ast_read(chan);
00560    if (f)
00561       ast_frfree(f);
00562 
00563    orig_chan_name = ast_strdupa(chan->name);
00564 
00565    park_call_full(chan, peer, timeout, extout, orig_chan_name);
00566 
00567    return 0;
00568 }

int ast_park_call ( struct ast_channel chan,
struct ast_channel peer,
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
Park a call and read back parked location.

Note:
We put the user in the parking list, then wake up the parking thread to be sure it looks after these channels too

Definition at line 533 of file res_features.c.

References park_call_full().

Referenced by builtin_blindtransfer(), builtin_parkcall(), iax_park_thread(), and sip_park_thread().

00534 {
00535    return park_call_full(chan, peer, timeout, extout, NULL);
00536 }

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 218 of file res_features.c.

Referenced by builtin_blindtransfer(), dp_lookup(), handle_request_refer(), load_config(), mgcp_ss(), socket_process(), and ss_thread().

00219 {
00220    return parking_ext;
00221 }

int ast_pickup_call ( struct ast_channel chan  ) 

Pickup a call.

Definition at line 3109 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().

03110 {
03111    struct ast_channel *cur = NULL;
03112    int res = -1;
03113 
03114    while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
03115       if (!cur->pbx && 
03116          (cur != chan) &&
03117          (chan->pickupgroup & cur->callgroup) &&
03118          ((cur->_state == AST_STATE_RINGING) ||
03119           (cur->_state == AST_STATE_RING))) {
03120             break;
03121       }
03122       ast_channel_unlock(cur);
03123    }
03124    if (cur) {
03125       if (option_debug)
03126          ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
03127       res = ast_answer(chan);
03128       if (res)
03129          ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
03130       res = ast_queue_control(chan, AST_CONTROL_ANSWER);
03131       if (res)
03132          ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
03133       res = ast_channel_masquerade(cur, chan);
03134       if (res)
03135          ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);     /* Done */
03136       ast_channel_unlock(cur);
03137    } else   {
03138       if (option_debug)
03139          ast_log(LOG_DEBUG, "No call pickup possible...\n");
03140    }
03141    return res;
03142 }

char* ast_pickup_ext ( void   ) 

Determine system call pickup extension.

Definition at line 223 of file res_features.c.

Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().

00224 {
00225    return pickup_ext;
00226 }

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

01007 {
01008    if (!feature) {
01009       ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
01010          return;
01011    }
01012   
01013    AST_LIST_LOCK(&feature_list);
01014    AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
01015    AST_LIST_UNLOCK(&feature_list);
01016 
01017    if (option_verbose >= 2) 
01018       ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
01019 }

int ast_retrieve_call ( struct ast_channel chan,
char *  uniqueid 
)

Definition at line 2180 of file res_features.c.

References ast_channel::_state, ast_answer(), ast_bridge_call(), ast_channel_make_compatible(), AST_FEATURE_REDIRECT, ast_get_holded_call(), ast_hangup(), ast_log(), ast_moh_stop(), ast_mutex_unlock(), AST_PBX_NO_HANGUP_PEER, ast_set_flag, AST_STATE_UP, ast_streamfile(), ast_verbose(), ast_waitstream(), ast_bridge_config::features_callee, ast_bridge_config::features_caller, LOG_WARNING, option_verbose, ast_bridge_config::play_warning, ast_bridge_config::timelimit, VERBOSE_PREFIX_3, ast_bridge_config::warning_freq, and ast_bridge_config::warning_sound.

Referenced by retrieve_call_exec().

02181 {
02182    int res=-1, dres=-1;
02183    struct ast_channel *peer=NULL;
02184    struct ast_bridge_config config;
02185 
02186    peer = ast_get_holded_call(uniqueid);
02187 
02188    /* JK02: it helps to answer the channel if not already up */
02189    if (chan->_state != AST_STATE_UP) {
02190       ast_answer(chan);
02191    }
02192 
02193    if (peer) {
02194       ast_mutex_unlock(&peer->lock);
02195       ast_moh_stop(peer);
02196       res = ast_channel_make_compatible(chan, peer);
02197       if (res < 0) {
02198          ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
02199          ast_hangup(peer);
02200          return -1;
02201       }
02202       /* This runs sorta backwards, since we give the incoming channel control, as if it
02203          were the person called. */
02204       if (option_verbose > 2)
02205          ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
02206 
02207       memset(&config,0,sizeof(struct ast_bridge_config));
02208       ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02209       ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02210       config.timelimit = 0;
02211       config.play_warning = 0;
02212       config.warning_freq = 0;
02213       config.warning_sound=NULL;
02214       res = ast_bridge_call(chan,peer,&config);
02215 
02216       /* Simulate the PBX hanging up */
02217       if (res != AST_PBX_NO_HANGUP_PEER)
02218          ast_hangup(peer);
02219       return res;
02220    } else {
02221       /* XXX Play a message XXX */
02222      dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
02223      if (!dres)
02224        dres = ast_waitstream(chan, "");
02225      else {
02226        ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
02227        dres = 0;
02228      }
02229    }
02230    return res;
02231 }

int ast_retrieve_call_to_death ( char *  uniqueid  ) 

Definition at line 2233 of file res_features.c.

References ast_get_holded_call(), ast_hangup(), ast_log(), ast_mutex_unlock(), ast_verbose(), ast_channel::lock, LOG_WARNING, option_verbose, and VERBOSE_PREFIX_3.

02234 {
02235    int res=-1;
02236    struct ast_channel *peer=NULL;
02237 
02238    peer = ast_get_holded_call(uniqueid);
02239 
02240    if (peer) {
02241       res=0;
02242       if (option_verbose > 2)
02243          ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
02244       ast_mutex_unlock(&peer->lock);
02245       ast_hangup(peer);
02246    } else {
02247       ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
02248    }
02249    return res;
02250 }

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 1022 of file res_features.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.

01023 {
01024    if (!feature)
01025       return;
01026 
01027    AST_LIST_LOCK(&feature_list);
01028    AST_LIST_REMOVE(&feature_list,feature,feature_entry);
01029    AST_LIST_UNLOCK(&feature_list);
01030    free(feature);
01031 }


Generated on Sun Dec 18 20:55:50 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6