features.h File Reference

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

#include "asterisk/pbx.h"
#include "asterisk/linkedlists.h"
#include "asterisk/bridge.h"

Include dependency graph for features.h:

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

Go to the source code of this file.

Enumerations

enum  {
  AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0), AST_FEATURE_FLAG_ONPEER = (1 << 1), AST_FEATURE_FLAG_ONSELF = (1 << 2), AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
  AST_FEATURE_FLAG_BYCALLER = (1 << 4), AST_FEATURE_FLAG_BYBOTH = (3 << 3)
}
 main call feature structure More...

Functions

int ast_bridge_add_channel (struct ast_bridge *bridge, struct ast_channel *chan, struct ast_bridge_features *features, int play_tone, const char *xfersound)
 Add an arbitrary channel to a bridge.
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_bridge_call_with_flags (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, unsigned int flags)
 Bridge a call, and add additional flags to the bridge.
int ast_bridge_timelimit (struct ast_channel *chan, struct ast_bridge_config *config, char *parse, struct timeval *calldurationlimit)
 parse L option and read associated channel variables to set warning, warning frequency, and timelimit


Detailed Description

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

Definition in file features.h.


Enumeration Type Documentation

anonymous enum

main call feature structure

Enumerator:
AST_FEATURE_FLAG_NEEDSDTMF 
AST_FEATURE_FLAG_ONPEER 
AST_FEATURE_FLAG_ONSELF 
AST_FEATURE_FLAG_BYCALLEE 
AST_FEATURE_FLAG_BYCALLER 
AST_FEATURE_FLAG_BYBOTH 

Definition at line 33 of file features.h.

00033      {
00034    AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
00035    AST_FEATURE_FLAG_ONPEER =    (1 << 1),
00036    AST_FEATURE_FLAG_ONSELF =    (1 << 2),
00037    AST_FEATURE_FLAG_BYCALLEE =  (1 << 3),
00038    AST_FEATURE_FLAG_BYCALLER =  (1 << 4),
00039    AST_FEATURE_FLAG_BYBOTH  =   (3 << 3),
00040 };


Function Documentation

int ast_bridge_add_channel ( struct ast_bridge bridge,
struct ast_channel chan,
struct ast_bridge_features features,
int  play_tone,
const char *  xfersound 
)

Add an arbitrary channel to a bridge.

Since:
12.0.0
The channel that is being added to the bridge can be in any state: unbridged, bridged, answered, unanswered, etc. The channel will be added asynchronously, meaning that when this function returns once the channel has been added to the bridge, not once the channel has been removed from the bridge.

In addition, a tone can optionally be played to the channel once the channel is placed into the bridge.

Note:
When this function returns, there is no guarantee that the channel that was passed in is valid any longer. Do not attempt to operate on the channel after this function returns.
Parameters:
bridge Bridge to which the channel should be added
chan The channel to add to the bridge
features Features for this channel in the bridge
play_tone Indicates if a tone should be played to the channel
xfersound Sound that should be used to indicate transfer with play_tone
Return values:
0 Success
-1 Failure

Definition at line 2291 of file bridge.c.

References ao2_cleanup, ast_answer(), ast_assert, ast_bridge_channel_queue_playfile(), ast_bridge_features_destroy(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_bridge_lock_both, ast_bridge_unlock, ast_channel_get_bridge(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_channel_yank(), ast_hangup(), ast_log, AST_STATE_UP, ast_strlen_zero, bridge_dissolve_check_stolen(), bridge_find_channel(), bridge_move_locked(), LOG_WARNING, NULL, and RAII_VAR.

Referenced by action_bridge(), bridge_exec(), and manager_park_unbridged().

02293 {
02294    RAII_VAR(struct ast_bridge *, chan_bridge, NULL, ao2_cleanup);
02295    RAII_VAR(struct ast_channel *, yanked_chan, NULL, ao2_cleanup);
02296 
02297    ast_channel_lock(chan);
02298    chan_bridge = ast_channel_get_bridge(chan);
02299    ast_channel_unlock(chan);
02300 
02301    if (chan_bridge) {
02302       struct ast_bridge_channel *bridge_channel;
02303 
02304       ast_bridge_lock_both(bridge, chan_bridge);
02305       bridge_channel = bridge_find_channel(chan_bridge, chan);
02306 
02307       if (bridge_move_locked(bridge, chan_bridge, chan, NULL, 1)) {
02308          ast_bridge_unlock(chan_bridge);
02309          ast_bridge_unlock(bridge);
02310          return -1;
02311       }
02312 
02313       /*
02314        * bridge_move_locked() will implicitly ensure that
02315        * bridge_channel is not NULL.
02316        */
02317       ast_assert(bridge_channel != NULL);
02318 
02319       /*
02320        * Additional checks if the channel we just stole dissolves the
02321        * original bridge.
02322        */
02323       bridge_dissolve_check_stolen(chan_bridge, bridge_channel);
02324       ast_bridge_unlock(chan_bridge);
02325       ast_bridge_unlock(bridge);
02326 
02327       /* The channel was in a bridge so it is not getting any new features. */
02328       ast_bridge_features_destroy(features);
02329    } else {
02330       /* Slightly less easy case. We need to yank channel A from
02331        * where he currently is and impart him into our bridge.
02332        */
02333       yanked_chan = ast_channel_yank(chan);
02334       if (!yanked_chan) {
02335          ast_log(LOG_WARNING, "Could not gain control of channel %s\n", ast_channel_name(chan));
02336          return -1;
02337       }
02338       if (ast_channel_state(yanked_chan) != AST_STATE_UP) {
02339          ast_answer(yanked_chan);
02340       }
02341       ast_channel_ref(yanked_chan);
02342       if (ast_bridge_impart(bridge, yanked_chan, NULL, features,
02343          AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
02344          /* It is possible for us to yank a channel and have some other
02345           * thread start a PBX on the channl after we yanked it. In particular,
02346           * this can theoretically happen on the ;2 of a Local channel if we
02347           * yank it prior to the ;1 being answered. Make sure that it isn't
02348           * executing a PBX before hanging it up.
02349           */
02350          if (ast_channel_pbx(yanked_chan)) {
02351             ast_channel_unref(yanked_chan);
02352          } else {
02353             ast_hangup(yanked_chan);
02354          }
02355          return -1;
02356       }
02357    }
02358 
02359    if (play_tone && !ast_strlen_zero(xfersound)) {
02360       struct ast_channel *play_chan = yanked_chan ?: chan;
02361       RAII_VAR(struct ast_bridge_channel *, play_bridge_channel, NULL, ao2_cleanup);
02362 
02363       ast_channel_lock(play_chan);
02364       play_bridge_channel = ast_channel_get_bridge_channel(play_chan);
02365       ast_channel_unlock(play_chan);
02366 
02367       if (!play_bridge_channel) {
02368          ast_log(LOG_WARNING, "Unable to play tone for channel %s. No longer in a bridge.\n",
02369             ast_channel_name(play_chan));
02370       } else {
02371          ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, xfersound, NULL);
02372       }
02373    }
02374    return 0;
02375 }

int ast_bridge_call ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config 
)

Bridge a call, optionally allowing redirection.

Note:
The function caller is assumed to have already done the COLP exchange for the initial bridging of the two channels if it was desired.
Bridge a call, optionally allowing redirection.

Parameters:
chan The bridge considers this channel the caller.
peer The bridge considers this channel the callee.
config Configuration for this bridge.
Set start time, check for two channels,check if monitor on check for feature activation, create new CDR
Return values:
res on success.
-1 on failure to bridge.

Definition at line 718 of file features.c.

References ast_bridge_call_with_flags().

Referenced by app_exec(), and dial_exec_full().

00719 {
00720    return ast_bridge_call_with_flags(chan, peer, config, 0);
00721 }

int ast_bridge_call_with_flags ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
unsigned int  flags 
)

Bridge a call, and add additional flags to the bridge.

This does the same thing as ast_bridge_call, except that once the bridge is created, the provided flags are set on the bridge. The provided flags are added to the bridge's flags; they will not clear any flags already set.

Parameters:
chan The calling channel
peer The called channel
config Bridge configuration for the channels
flags Additional flags to set on the created bridge
Note:
The function caller is assumed to have already done the COLP exchange for the initial bridging of the two channels if it was desired.

Definition at line 636 of file features.c.

References ast_bridge_basic_new(), ast_bridge_basic_set_flags(), ast_bridge_destroy(), ast_bridge_features_cleanup(), ast_bridge_features_destroy(), ast_bridge_features_init(), ast_bridge_features_new(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP, ast_bridge_join(), AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP, AST_BRIDGE_JOIN_PASS_REFERENCE, ast_channel_lock, ast_channel_softhangup_internal_flag(), ast_channel_unlock, AST_SOFTHANGUP_ASYNCGOTO, bridge_failed_peer_goto(), ast_bridge_config::end_bridge_callback, ast_bridge_config::end_bridge_callback_data, NULL, and pre_bridge_setup().

Referenced by ast_bridge_call(), and try_calling().

00637 {
00638    int res;
00639    struct ast_bridge *bridge;
00640    struct ast_bridge_features chan_features;
00641    struct ast_bridge_features *peer_features;
00642 
00643    /* Setup features. */
00644    res = ast_bridge_features_init(&chan_features);
00645    peer_features = ast_bridge_features_new();
00646    if (res || !peer_features) {
00647       ast_bridge_features_destroy(peer_features);
00648       ast_bridge_features_cleanup(&chan_features);
00649       bridge_failed_peer_goto(chan, peer);
00650       return -1;
00651    }
00652 
00653    if (pre_bridge_setup(chan, peer, config, &chan_features, peer_features)) {
00654       ast_bridge_features_destroy(peer_features);
00655       ast_bridge_features_cleanup(&chan_features);
00656       bridge_failed_peer_goto(chan, peer);
00657       return -1;
00658    }
00659 
00660    /* Create bridge */
00661    bridge = ast_bridge_basic_new();
00662    if (!bridge) {
00663       ast_bridge_features_destroy(peer_features);
00664       ast_bridge_features_cleanup(&chan_features);
00665       bridge_failed_peer_goto(chan, peer);
00666       return -1;
00667    }
00668 
00669    ast_bridge_basic_set_flags(bridge, flags);
00670 
00671    /* Put peer into the bridge */
00672    if (ast_bridge_impart(bridge, peer, NULL, peer_features,
00673       AST_BRIDGE_IMPART_CHAN_INDEPENDENT | AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP)) {
00674       ast_bridge_destroy(bridge, 0);
00675       ast_bridge_features_cleanup(&chan_features);
00676       bridge_failed_peer_goto(chan, peer);
00677       return -1;
00678    }
00679 
00680    /* Join bridge */
00681    ast_bridge_join(bridge, chan, NULL, &chan_features, NULL,
00682       AST_BRIDGE_JOIN_PASS_REFERENCE | AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP);
00683 
00684    /*
00685     * If the bridge was broken for a hangup that isn't real, then
00686     * don't run the h extension, because the channel isn't really
00687     * hung up.  This should really only happen with
00688     * AST_SOFTHANGUP_ASYNCGOTO.
00689     */
00690    res = -1;
00691    ast_channel_lock(chan);
00692    if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
00693       res = 0;
00694    }
00695    ast_channel_unlock(chan);
00696 
00697    ast_bridge_features_cleanup(&chan_features);
00698 
00699    if (res && config->end_bridge_callback) {
00700       config->end_bridge_callback(config->end_bridge_callback_data);
00701    }
00702 
00703    return res;
00704 }

int ast_bridge_timelimit ( struct ast_channel chan,
struct ast_bridge_config config,
char *  parse,
struct timeval *  calldurationlimit 
)

parse L option and read associated channel variables to set warning, warning frequency, and timelimit

Note:
caller must be aware of freeing memory for warning_sound, end_sound, and start_sound

Definition at line 888 of file features.c.

References ast_channel_lock, ast_channel_unlock, AST_FEATURE_PLAY_WARNING, ast_log, ast_set_flag, ast_strdup, ast_strdupa, ast_strlen_zero, ast_true(), ast_verb, ast_bridge_config::end_sound, ast_bridge_config::features_callee, ast_bridge_config::features_caller, LOG_WARNING, NULL, pbx_builtin_getvar_helper(), ast_bridge_config::play_warning, S_OR, ast_bridge_config::start_sound, strsep(), ast_bridge_config::timelimit, var, ast_bridge_config::warning_freq, and ast_bridge_config::warning_sound.

Referenced by bridge_exec(), and dial_exec_full().

00890 {
00891    char *stringp = ast_strdupa(parse);
00892    char *limit_str, *warning_str, *warnfreq_str;
00893    const char *var;
00894    int play_to_caller = 0, play_to_callee = 0;
00895    int delta;
00896 
00897    limit_str = strsep(&stringp, ":");
00898    warning_str = strsep(&stringp, ":");
00899    warnfreq_str = strsep(&stringp, ":");
00900 
00901    config->timelimit = atol(limit_str);
00902    if (warning_str)
00903       config->play_warning = atol(warning_str);
00904    if (warnfreq_str)
00905       config->warning_freq = atol(warnfreq_str);
00906 
00907    if (!config->timelimit) {
00908       ast_log(LOG_WARNING, "Bridge does not accept L(%s), hanging up.\n", limit_str);
00909       config->timelimit = config->play_warning = config->warning_freq = 0;
00910       config->warning_sound = NULL;
00911       return -1; /* error */
00912    } else if ( (delta = config->play_warning - config->timelimit) > 0) {
00913       int w = config->warning_freq;
00914 
00915       /*
00916        * If the first warning is requested _after_ the entire call
00917        * would end, and no warning frequency is requested, then turn
00918        * off the warning. If a warning frequency is requested, reduce
00919        * the 'first warning' time by that frequency until it falls
00920        * within the call's total time limit.
00921        *
00922        * Graphically:
00923        *                timelim->|    delta        |<-playwarning
00924        *      0__________________|_________________|
00925        *                       | w  |    |    |    |
00926        *
00927        * so the number of intervals to cut is 1+(delta-1)/w
00928        */
00929       if (w == 0) {
00930          config->play_warning = 0;
00931       } else {
00932          config->play_warning -= w * ( 1 + (delta-1)/w );
00933          if (config->play_warning < 1)
00934             config->play_warning = config->warning_freq = 0;
00935       }
00936    }
00937 
00938    ast_channel_lock(chan);
00939 
00940    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
00941    play_to_caller = var ? ast_true(var) : 1;
00942 
00943    var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
00944    play_to_callee = var ? ast_true(var) : 0;
00945 
00946    if (!play_to_caller && !play_to_callee)
00947       play_to_caller = 1;
00948 
00949    var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
00950    config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
00951 
00952    /* The code looking at config wants a NULL, not just "", to decide
00953     * that the message should not be played, so we replace "" with NULL.
00954     * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
00955     * not found.
00956     */
00957 
00958    var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
00959    config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
00960 
00961    var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
00962    config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
00963 
00964    ast_channel_unlock(chan);
00965 
00966    /* undo effect of S(x) in case they are both used */
00967    calldurationlimit->tv_sec = 0;
00968    calldurationlimit->tv_usec = 0;
00969 
00970    /* more efficient to do it like S(x) does since no advanced opts */
00971    if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
00972       calldurationlimit->tv_sec = config->timelimit / 1000;
00973       calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
00974       ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
00975          calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
00976       play_to_caller = 0;
00977       play_to_callee = 0;
00978       config->timelimit = 0;
00979       config->play_warning = 0;
00980       config->warning_freq = 0;
00981    } else {
00982       ast_verb(4, "Limit Data for this call:\n");
00983       ast_verb(4, "timelimit      = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0);
00984       ast_verb(4, "play_warning   = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0);
00985       ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
00986       ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
00987       ast_verb(4, "warning_freq   = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0);
00988       ast_verb(4, "start_sound    = %s\n", S_OR(config->start_sound, ""));
00989       ast_verb(4, "warning_sound  = %s\n", config->warning_sound);
00990       ast_verb(4, "end_sound      = %s\n", S_OR(config->end_sound, ""));
00991    }
00992    if (play_to_caller)
00993       ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
00994    if (play_to_callee)
00995       ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
00996    return 0;
00997 }


Generated on Thu Apr 16 06:30:58 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6