Wed Jan 8 2020 09:50:12

Asterisk developer's documentation


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"

Go to the source code of this file.

Data Structures

struct  ast_call_feature
 

Macros

#define AST_FEATURE_RETURN_HANGUP   -1
 
#define AST_FEATURE_RETURN_KEEPTRYING   24
 
#define AST_FEATURE_RETURN_NO_HANGUP_PEER   AST_PBX_NO_HANGUP_PEER
 
#define AST_FEATURE_RETURN_PARKFAILED   25
 
#define AST_FEATURE_RETURN_PASSDIGITS   21
 
#define AST_FEATURE_RETURN_PBX_KEEPALIVE   AST_PBX_KEEPALIVE
 
#define AST_FEATURE_RETURN_STOREDIGITS   22
 
#define AST_FEATURE_RETURN_SUCCESS   23
 
#define AST_FEATURE_RETURN_SUCCESSBREAK   0
 
#define DEFAULT_PARKINGLOT   "default"
 
#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 /* same as MAX_MUSICCLASS from channel.h */
 
#define FEATURE_SENSE_CHAN   (1 << 0)
 
#define FEATURE_SENSE_PEER   (1 << 1)
 
#define FEATURE_SNAME_LEN   32
 

Typedefs

typedef int(* ast_feature_operation )(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 

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_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
 Bridge a call, optionally allowing redirection. More...
 
void ast_bridge_end_dtmf (struct ast_channel *chan, char digit, struct timeval start, const char *why)
 Simulate a DTMF end on a broken bridge channel. More...
 
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 More...
 
int ast_can_pickup (struct ast_channel *chan)
 Test if a channel can be picked up. More...
 
int ast_do_pickup (struct ast_channel *chan, struct ast_channel *target)
 Pickup a call target. More...
 
int ast_feature_detect (struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature)
 detect a feature before bridging More...
 
int ast_features_reload (void)
 Reload call features from features.conf. More...
 
struct ast_call_featureast_find_call_feature (const char *name)
 look for a call feature entry by its sname More...
 
int ast_masq_park_call (struct ast_channel *park_me, struct ast_channel *parker, int timeout, int *extout)
 Park a call via a masqueraded channel. More...
 
int ast_masq_park_call_exten (struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
 Park a call via a masqueraded channel. More...
 
int ast_park_call (struct ast_channel *park_me, struct ast_channel *parker, int timeout, const char *park_exten, int *extout)
 Park a call and read back parked location. More...
 
int ast_park_call_exten (struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
 Park a call and read back parked location. More...
 
int ast_parking_ext_valid (const char *exten_str, struct ast_channel *chan, const char *context)
 Determine if parking extension exists in a given context. More...
 
int ast_pickup_call (struct ast_channel *chan)
 Pickup a call. More...
 
const char * ast_pickup_ext (void)
 Determine system call pickup extension. More...
 
void ast_rdlock_call_features (void)
 
void ast_register_feature (struct ast_call_feature *feature)
 register new feature into feature_set More...
 
void ast_unlock_call_features (void)
 
void ast_unregister_feature (struct ast_call_feature *feature)
 unregister feature from feature_set More...
 

Detailed Description

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

Definition in file features.h.

Macro Definition Documentation

#define AST_FEATURE_RETURN_HANGUP   -1

Definition at line 39 of file features.h.

Referenced by builtin_disconnect().

#define AST_FEATURE_RETURN_KEEPTRYING   24

Definition at line 46 of file features.h.

Referenced by feature_exec_app(), and feature_interpret_helper().

#define AST_FEATURE_RETURN_NO_HANGUP_PEER   AST_PBX_NO_HANGUP_PEER

Definition at line 42 of file features.h.

#define AST_FEATURE_RETURN_PARKFAILED   25

Definition at line 47 of file features.h.

#define AST_FEATURE_RETURN_PASSDIGITS   21

Definition at line 43 of file features.h.

Referenced by ast_bridge_call(), and feature_interpret_helper().

#define AST_FEATURE_RETURN_PBX_KEEPALIVE   AST_PBX_KEEPALIVE

Definition at line 41 of file features.h.

#define AST_FEATURE_RETURN_STOREDIGITS   22

Definition at line 44 of file features.h.

Referenced by detect_disconnect(), and feature_interpret_helper().

#define AST_FEATURE_RETURN_SUCCESSBREAK   0

Definition at line 40 of file features.h.

Referenced by builtin_blindtransfer(), and feature_exec_app().

#define DEFAULT_PARKINGLOT   "default"

Default parking lot

Definition at line 37 of file features.h.

Referenced by build_parkinglot(), load_config(), process_config(), and reload_config().

#define FEATURE_APP_ARGS_LEN   256

Definition at line 32 of file features.h.

Referenced by process_applicationmap_line().

#define FEATURE_APP_LEN   64

Definition at line 31 of file features.h.

Referenced by process_applicationmap_line().

#define FEATURE_EXTEN_LEN   32

Definition at line 34 of file features.h.

Referenced by process_applicationmap_line().

#define FEATURE_MAX_LEN   11

Definition at line 30 of file features.h.

Referenced by ast_bridge_call(), and wait_for_answer().

#define FEATURE_MOH_LEN   80 /* same as MAX_MUSICCLASS from channel.h */

Definition at line 35 of file features.h.

Referenced by process_applicationmap_line().

#define FEATURE_SENSE_CHAN   (1 << 0)

Definition at line 49 of file features.h.

Referenced by ast_bridge_call(), feature_exec_app(), and feature_interpret().

#define FEATURE_SENSE_PEER   (1 << 1)

Definition at line 50 of file features.h.

Referenced by ast_bridge_call(), and set_peers().

#define FEATURE_SNAME_LEN   32

Definition at line 33 of file features.h.

Referenced by process_applicationmap_line().

Typedef Documentation

typedef int(* ast_feature_operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)

Definition at line 52 of 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 56 of file features.h.

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.

Bridge a call, optionally allowing redirection.

Parameters
chanThe bridge considers this channel the caller.
peerThe bridge considers this channel the callee.
configConfiguration for this bridge.

Set start time, check for two channels,check if monitor on check for feature activation, create new CDR

Return values
reson success.
-1on failure to bridge.

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 3960 of file features.c.

References ast_channel::_softhangup, ast_channel::_state, ast_cdr::accountcode, ast_channel::accountcode, add_features_datastores(), ast_cdr::amaflags, ast_channel::amaflags, ast_cdr::answer, ast_channel::appl, ast_bridge_end_dtmf(), AST_BRIDGE_RETRY, ast_bridged_channel(), ast_cdr_alloc(), ast_cdr_answer(), AST_CDR_ANSWERED, ast_cdr_appenduserfield(), ast_cdr_copy_vars(), ast_cdr_detach(), ast_cdr_discard(), ast_cdr_dup_unique_swap(), ast_cdr_end(), AST_CDR_FLAG_BRIDGED, AST_CDR_FLAG_DIALED, AST_CDR_FLAG_MAIN, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NULL, ast_cdr_setaccount(), ast_cdr_setanswer(), ast_cdr_setcid(), ast_cdr_setdisposition(), ast_cdr_setuserfield(), ast_cdr_specialized_reset(), ast_cdr_start(), ast_cdr_update(), AST_CEL_BRIDGE_END, AST_CEL_BRIDGE_START, ast_cel_report_event(), ast_channel_bridge(), ast_channel_connected_line_macro(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_lock_both, ast_channel_log(), AST_CHANNEL_NAME, ast_channel_redirecting_macro(), ast_channel_set_linkgroup(), ast_channel_setoption(), ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_channel_unlock, ast_channel_unref, ast_check_hangup(), ast_clear_flag, AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OPTION, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_default_amaflags, ast_dtmf_stream(), ast_exists_extension(), AST_FEATURE_NO_H_EXTEN, AST_FEATURE_RETURN_PASSDIGITS, AST_FEATURE_RETURN_SUCCESS, AST_FEATURE_WARNING_ACTIVE, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT, AST_FLAG_BRIDGE_HANGUP_DONT, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frfree, ast_indicate(), ast_indicate_data(), ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_opt_end_cdr_before_h_exten, ast_opt_transmit_silence, AST_OPTION_AUDIO_MODE, AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, AST_OPTION_FLAG_REQUEST, AST_OPTION_RELAXDTMF, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_raw_answer(), ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_UNBRIDGE, ast_spawn_extension(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_verb, ast_write(), ast_channel::caller, ast_channel::cdr, ast_cdr::channel, clear_dialed_interfaces(), ast_channel::context, ast_frame::data, ast_option_header::data, ast_channel::data, ast_frame::datalen, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_bridge_config::end_bridge_callback, ast_bridge_config::end_bridge_callback_data, ast_channel::exten, f, feature_check(), feature_interpret(), FEATURE_MAX_LEN, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_bridge_config::feature_start_time, ast_bridge_config::feature_timer, featuredigittimeout, ast_bridge_config::features_callee, ast_bridge_config::features_caller, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, ast_cdr::lastapp, ast_cdr::lastdata, LOG_DEBUG, LOG_WARNING, ast_channel::macrocontext, monitor_app, monitor_ok, ast_channel::name, ast_cdr::next, ast_party_id::number, option_debug, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), pick_unlocked_cdr(), ast_channel::priority, ast_frame::ptr, S_COR, S_OR, ast_channel::sending_dtmf_digit, ast_channel::sending_dtmf_tv, set_bridge_features_on_config(), set_config_flags(), ast_cdr::start, ast_party_number::str, ast_frame::subclass, ast_bridge_config::timelimit, ast_cdr::uniqueid, ast_channel::uniqueid, ast_cdr::userfield, ast_party_number::valid, and ast_channel::visible_indication.

Referenced by app_exec(), bridge_call_thread(), bridge_exec(), builtin_atxfer(), dial_exec_full(), parked_call_exec(), and try_calling().

3961 {
3962  /* Copy voice back and forth between the two channels. Give the peer
3963  the ability to transfer calls with '#<extension' syntax. */
3964  struct ast_frame *f;
3965  struct ast_channel *who;
3966  char chan_featurecode[FEATURE_MAX_LEN + 1]="";
3967  char peer_featurecode[FEATURE_MAX_LEN + 1]="";
3968  char orig_channame[AST_CHANNEL_NAME];
3969  char orig_peername[AST_CHANNEL_NAME];
3970  int res;
3971  int diff;
3972  int hasfeatures=0;
3973  int hadfeatures=0;
3974  int autoloopflag;
3975  int sendingdtmfdigit = 0;
3976  int we_disabled_peer_cdr = 0;
3977  struct ast_option_header *aoh;
3978  struct ast_cdr *bridge_cdr = NULL;
3979  struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */
3980  struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
3981  struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
3982  struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
3983  struct ast_silence_generator *silgen = NULL;
3984  const char *h_context;
3985 
3986  pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
3987  pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
3988 
3989  /* Clear any BLINDTRANSFER since the transfer has completed. */
3990  pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
3991  pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", NULL);
3992 
3993  set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
3994  add_features_datastores(chan, peer, config);
3995 
3996  /* This is an interesting case. One example is if a ringing channel gets redirected to
3997  * an extension that picks up a parked call. This will make sure that the call taken
3998  * out of parking gets told that the channel it just got bridged to is still ringing. */
4001  }
4002 
4003  if (monitor_ok) {
4004  const char *monitor_exec;
4005  struct ast_channel *src = NULL;
4006  if (!monitor_app) {
4007  if (!(monitor_app = pbx_findapp("Monitor")))
4008  monitor_ok=0;
4009  }
4010  if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
4011  src = chan;
4012  else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
4013  src = peer;
4014  if (monitor_app && src) {
4015  char *tmp = ast_strdupa(monitor_exec);
4016  pbx_exec(src, monitor_app, tmp);
4017  }
4018  }
4019 
4020  set_config_flags(chan, peer, config);
4021 
4022  /* Answer if need be */
4023  if (chan->_state != AST_STATE_UP) {
4024  if (ast_raw_answer(chan, 1)) {
4025  return -1;
4026  }
4027  }
4028 
4029 #ifdef FOR_DEBUG
4030  /* show the two channels and cdrs involved in the bridge for debug & devel purposes */
4031  ast_channel_log("Pre-bridge CHAN Channel info", chan);
4032  ast_channel_log("Pre-bridge PEER Channel info", peer);
4033 #endif
4034  /* two channels are being marked as linked here */
4035  ast_channel_set_linkgroup(chan,peer);
4036 
4037  /* copy the userfield from the B-leg to A-leg if applicable */
4038  if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
4039  char tmp[256];
4040 
4041  ast_channel_lock(chan);
4042  if (!ast_strlen_zero(chan->cdr->userfield)) {
4043  snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
4044  ast_cdr_appenduserfield(chan, tmp);
4045  } else {
4046  ast_cdr_setuserfield(chan, peer->cdr->userfield);
4047  }
4048  ast_channel_unlock(chan);
4049  /* Don't delete the CDR; just disable it. */
4051  we_disabled_peer_cdr = 1;
4052  }
4053  ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
4054  ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
4055 
4056  if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
4057  ast_channel_lock_both(chan, peer);
4058  if (chan_cdr) {
4059  ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
4060  ast_cdr_update(chan);
4061  bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr);
4062  /* rip any forked CDR's off of the chan_cdr and attach
4063  * them to the bridge_cdr instead */
4064  bridge_cdr->next = chan_cdr->next;
4065  chan_cdr->next = NULL;
4066  ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
4067  ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
4068  if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) {
4069  ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
4070  }
4071  ast_cdr_setaccount(peer, chan->accountcode);
4072  } else {
4073  /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
4074  bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
4075  ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
4076  ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
4077  ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
4078  ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
4079  ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
4080  ast_cdr_setcid(bridge_cdr, chan);
4081  bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL;
4082  bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags;
4083  ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
4084  /* Destination information */
4085  ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
4086  ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
4087  if (peer_cdr) {
4088  bridge_cdr->start = peer_cdr->start;
4089  ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
4090  } else {
4091  ast_cdr_start(bridge_cdr);
4092  }
4093  }
4094  ast_channel_unlock(chan);
4095  ast_channel_unlock(peer);
4096 
4097  ast_debug(4,"bridge answer set, chan answer set\n");
4098  /* peer_cdr->answer will be set when a macro runs on the peer;
4099  in that case, the bridge answer will be delayed while the
4100  macro plays on the peer channel. The peer answered the call
4101  before the macro started playing. To the phone system,
4102  this is billable time for the call, even tho the caller
4103  hears nothing but ringing while the macro does its thing. */
4104 
4105  /* Another case where the peer cdr's time will be set, is when
4106  A self-parks by pickup up phone and dialing 700, then B
4107  picks up A by dialing its parking slot; there may be more
4108  practical paths that get the same result, tho... in which
4109  case you get the previous answer time from the Park... which
4110  is before the bridge's start time, so I added in the
4111  tvcmp check to the if below */
4112 
4113  if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) {
4114  ast_cdr_setanswer(bridge_cdr, peer_cdr->answer);
4115  ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition);
4116  if (chan_cdr) {
4117  ast_cdr_setanswer(chan_cdr, peer_cdr->answer);
4118  ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition);
4119  }
4120  } else {
4121  ast_cdr_answer(bridge_cdr);
4122  if (chan_cdr) {
4123  ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
4124  }
4125  }
4126  if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
4127  if (chan_cdr) {
4129  }
4130  if (peer_cdr) {
4132  }
4133  }
4134  /* the DIALED flag may be set if a dialed channel is transferred
4135  * and then bridged to another channel. In order for the
4136  * bridge CDR to be written, the DIALED flag must not be
4137  * present. */
4138  ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED);
4139  }
4140  ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, peer);
4141 
4142  /* If we are bridging a call, stop worrying about forwarding loops. We presume that if
4143  * a call is being bridged, that the humans in charge know what they're doing. If they
4144  * don't, well, what can we do about that? */
4147 
4148  for (;;) {
4149  struct ast_channel *other; /* used later */
4150 
4151  res = ast_channel_bridge(chan, peer, config, &f, &who);
4152 
4153  if (ast_test_flag(chan, AST_FLAG_ZOMBIE)
4154  || ast_test_flag(peer, AST_FLAG_ZOMBIE)) {
4155  /* Zombies are present time to leave! */
4156  res = -1;
4157  if (f) {
4158  ast_frfree(f);
4159  }
4160  goto before_you_go;
4161  }
4162 
4163  /* When frame is not set, we are probably involved in a situation
4164  where we've timed out.
4165  When frame is set, we'll come this code twice; once for DTMF_BEGIN
4166  and also for DTMF_END. If we flow into the following 'if' for both, then
4167  our wait times are cut in half, as both will subtract from the
4168  feature_timer. Not good!
4169  */
4170  if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
4171  /* Update feature timer for next pass */
4172  diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time);
4173  if (res == AST_BRIDGE_RETRY) {
4174  /* The feature fully timed out but has not been updated. Skip
4175  * the potential round error from the diff calculation and
4176  * explicitly set to expired. */
4177  config->feature_timer = -1;
4178  } else {
4179  config->feature_timer -= diff;
4180  }
4181 
4182  if (hasfeatures) {
4183  if (config->feature_timer <= 0) {
4184  /* Not *really* out of time, just out of time for
4185  digits to come in for features. */
4186  ast_debug(1, "Timed out for feature!\n");
4187  if (!ast_strlen_zero(peer_featurecode)) {
4188  ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
4189  memset(peer_featurecode, 0, sizeof(peer_featurecode));
4190  }
4191  if (!ast_strlen_zero(chan_featurecode)) {
4192  ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
4193  memset(chan_featurecode, 0, sizeof(chan_featurecode));
4194  }
4195  if (f)
4196  ast_frfree(f);
4197  hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
4198  if (!hasfeatures) {
4199  /* No more digits expected - reset the timer */
4200  config->feature_timer = 0;
4201  }
4202  hadfeatures = hasfeatures;
4203  /* Continue as we were */
4204  continue;
4205  } else if (!f) {
4206  /* The bridge returned without a frame and there is a feature in progress.
4207  * However, we don't think the feature has quite yet timed out, so just
4208  * go back into the bridge. */
4209  continue;
4210  }
4211  } else {
4212  if (config->feature_timer <=0) {
4213  /* We ran out of time */
4214  config->feature_timer = 0;
4215  who = chan;
4216  if (f)
4217  ast_frfree(f);
4218  f = NULL;
4219  res = 0;
4220  }
4221  }
4222  }
4223  if (res < 0) {
4224  if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) {
4225  ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
4226  }
4227  goto before_you_go;
4228  }
4229 
4230  if (!f || (f->frametype == AST_FRAME_CONTROL &&
4233  res = -1;
4234  break;
4235  }
4236  /* many things should be sent to the 'other' channel */
4237  other = (who == chan) ? peer : chan;
4238  if (f->frametype == AST_FRAME_CONTROL) {
4239  switch (f->subclass.integer) {
4240  case AST_CONTROL_RINGING:
4241  case AST_CONTROL_FLASH:
4242  case -1:
4243  ast_indicate(other, f->subclass.integer);
4244  break;
4246  if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
4247  break;
4248  }
4249  ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
4250  break;
4252  if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
4253  break;
4254  }
4255  ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
4256  break;
4257  case AST_CONTROL_AOC:
4258  case AST_CONTROL_HOLD:
4259  case AST_CONTROL_UNHOLD:
4260  ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
4261  break;
4262  case AST_CONTROL_OPTION:
4263  aoh = f->data.ptr;
4264  /* Forward option Requests, but only ones we know are safe
4265  * These are ONLY sent by chan_iax2 and I'm not convinced that
4266  * they are useful. I haven't deleted them entirely because I
4267  * just am not sure of the ramifications of removing them. */
4268  if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
4269  switch (ntohs(aoh->option)) {
4271  case AST_OPTION_TDD:
4272  case AST_OPTION_RELAXDTMF:
4273  case AST_OPTION_AUDIO_MODE:
4275  case AST_OPTION_FAX_DETECT:
4276  ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
4277  f->datalen - sizeof(struct ast_option_header), 0);
4278  }
4279  }
4280  break;
4281  }
4282  } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
4283  struct ast_flags *cfg;
4284  char dtmfcode[2] = { f->subclass.integer, };
4285  size_t featurelen;
4286 
4287  if (who == chan) {
4288  featurelen = strlen(chan_featurecode);
4289  cfg = &(config->features_caller);
4290  } else {
4291  featurelen = strlen(peer_featurecode);
4292  cfg = &(config->features_callee);
4293  }
4294  /* Take a peek if this (possibly) matches a feature. If not, just pass this
4295  * DTMF along untouched. If this is not the first digit of a multi-digit code
4296  * then we need to fall through and stream the characters if it matches */
4297  if (featurelen == 0
4298  && feature_check(chan, cfg, &dtmfcode[0]) == AST_FEATURE_RETURN_PASSDIGITS) {
4299  if (option_debug > 3) {
4300  ast_log(LOG_DEBUG, "Passing DTMF through, since it is not a feature code\n");
4301  }
4302  ast_write(other, f);
4303  sendingdtmfdigit = 1;
4304  } else {
4305  /* If ast_opt_transmit_silence is set, then we need to make sure we are
4306  * transmitting something while we hold on to the DTMF waiting for a
4307  * feature. */
4308  if (!silgen && ast_opt_transmit_silence) {
4309  silgen = ast_channel_start_silence_generator(other);
4310  }
4311  if (option_debug > 3) {
4312  ast_log(LOG_DEBUG, "Not passing DTMF through, since it may be a feature code\n");
4313  }
4314  }
4315  } else if (f->frametype == AST_FRAME_DTMF_END) {
4316  char *featurecode;
4317  int sense;
4318 
4319  hadfeatures = hasfeatures;
4320  /* This cannot overrun because the longest feature is one shorter than our buffer */
4321  if (who == chan) {
4322  sense = FEATURE_SENSE_CHAN;
4323  featurecode = chan_featurecode;
4324  } else {
4325  sense = FEATURE_SENSE_PEER;
4326  featurecode = peer_featurecode;
4327  }
4328 
4329  if (sendingdtmfdigit == 1) {
4330  /* We let the BEGIN go through happily, so let's not bother with the END,
4331  * since we already know it's not something we bother with */
4332  ast_write(other, f);
4333  sendingdtmfdigit = 0;
4334  } else {
4335  /*! append the event to featurecode. we rely on the string being zero-filled, and
4336  * not overflowing it.
4337  * \todo XXX how do we guarantee the latter ?
4338  */
4339  featurecode[strlen(featurecode)] = f->subclass.integer;
4340  /* Get rid of the frame before we start doing "stuff" with the channels */
4341  ast_frfree(f);
4342  f = NULL;
4343  if (silgen) {
4344  ast_channel_stop_silence_generator(other, silgen);
4345  silgen = NULL;
4346  }
4347  config->feature_timer = 0;
4348  res = feature_interpret(chan, peer, config, featurecode, sense);
4349  switch(res) {
4351  ast_dtmf_stream(other, who, featurecode, 0, 0);
4352  /* Fall through */
4354  memset(featurecode, 0, sizeof(chan_featurecode));
4355  break;
4356  }
4357  if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
4358  res = 0;
4359  } else {
4360  break;
4361  }
4362  hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
4363  if (hadfeatures && !hasfeatures) {
4364  /* Feature completed or timed out */
4365  config->feature_timer = 0;
4366  } else if (hasfeatures) {
4367  if (config->timelimit) {
4368  /* No warning next time - we are waiting for feature code */
4370  }
4371  config->feature_start_time = ast_tvnow();
4373  ast_debug(1, "Set feature timer to %ld ms\n", config->feature_timer);
4374  }
4375  }
4376  }
4377  if (f)
4378  ast_frfree(f);
4379  }
4380  ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, peer);
4381 
4382 before_you_go:
4383  if (chan->sending_dtmf_digit) {
4385  "bridge end");
4386  }
4387  if (peer->sending_dtmf_digit) {
4389  "bridge end");
4390  }
4391 
4392  /* Just in case something weird happened and we didn't clean up the silence generator... */
4393  if (silgen) {
4394  ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen);
4395  silgen = NULL;
4396  }
4397 
4398  /* Wait for any dual redirect to complete. */
4400  sched_yield();
4401  }
4402 
4404  ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
4405  if (bridge_cdr) {
4406  ast_cdr_discard(bridge_cdr);
4407  /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */
4408  }
4409  return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */
4410  }
4411 
4412  if (config->end_bridge_callback) {
4414  }
4415 
4416  /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation
4417  * if it were, then chan belongs to a different thread now, and might have been hung up long
4418  * ago.
4419  */
4421  /*
4422  * If the bridge was broken for a hangup that isn't real,
4423  * then don't run the h extension, because the channel isn't
4424  * really hung up. This should really only happen with AST_SOFTHANGUP_ASYNCGOTO,
4425  * but it doesn't hurt to check AST_SOFTHANGUP_UNBRIDGE either.
4426  */
4427  h_context = NULL;
4428  } else if (ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) {
4429  h_context = NULL;
4430  } else if (ast_exists_extension(chan, chan->context, "h", 1,
4431  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
4432  h_context = chan->context;
4433  } else if (!ast_strlen_zero(chan->macrocontext)
4434  && ast_exists_extension(chan, chan->macrocontext, "h", 1,
4435  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
4436  h_context = chan->macrocontext;
4437  } else {
4438  h_context = NULL;
4439  }
4440  if (h_context) {
4441  struct ast_cdr *swapper = NULL;
4442  char savelastapp[AST_MAX_EXTENSION];
4443  char savelastdata[AST_MAX_EXTENSION];
4444  char save_context[AST_MAX_CONTEXT];
4445  char save_exten[AST_MAX_EXTENSION];
4446  int save_prio;
4447  int found = 0; /* set if we find at least one match */
4448  int spawn_error = 0;
4449 
4450  /*
4451  * Make sure that the channel is marked as hungup since we are
4452  * going to run the "h" exten on it.
4453  */
4455 
4456  autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
4458  if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
4459  ast_cdr_end(bridge_cdr);
4460  }
4461 
4462  /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
4463  dialplan code operate on it */
4464  ast_channel_lock(chan);
4465  if (bridge_cdr) {
4466  swapper = chan->cdr;
4467  ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
4468  ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
4469  chan->cdr = bridge_cdr;
4470  }
4471  ast_copy_string(save_context, chan->context, sizeof(save_context));
4472  ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
4473  save_prio = chan->priority;
4474  if (h_context != chan->context) {
4475  ast_copy_string(chan->context, h_context, sizeof(chan->context));
4476  }
4477  ast_copy_string(chan->exten, "h", sizeof(chan->exten));
4478  chan->priority = 1;
4479  ast_channel_unlock(chan);
4480 
4481  while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten,
4482  chan->priority,
4483  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
4484  &found, 1)) == 0) {
4485  chan->priority++;
4486  }
4487  if (found && spawn_error) {
4488  /* Something bad happened, or a hangup has been requested. */
4489  ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
4490  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
4491  }
4492 
4493  /* swap it back */
4494  ast_channel_lock(chan);
4495  ast_copy_string(chan->context, save_context, sizeof(chan->context));
4496  ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
4497  chan->priority = save_prio;
4498  if (bridge_cdr) {
4499  if (chan->cdr == bridge_cdr) {
4500  chan->cdr = swapper;
4501  } else {
4502  bridge_cdr = NULL;
4503  }
4504  }
4505  /* An "h" exten has been run, so indicate that one has been run. */
4507  ast_channel_unlock(chan);
4508 
4509  /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
4510  if (bridge_cdr) {
4511  ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
4512  ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
4513  }
4514  ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
4515  }
4516 
4517  /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
4518  new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
4519  /* If the channel CDR has been modified during the call, record the changes in the bridge cdr,
4520  * BUT, if we've gone through the h extension block above, the CDR got swapped so don't overwrite
4521  * what was done in the h extension. What a mess. This is why you never touch CDR code. */
4522  if (new_chan_cdr && bridge_cdr && !h_context) {
4523  ast_cdr_copy_vars(bridge_cdr, new_chan_cdr);
4524  ast_copy_string(bridge_cdr->userfield, new_chan_cdr->userfield, sizeof(bridge_cdr->userfield));
4525  bridge_cdr->amaflags = new_chan_cdr->amaflags;
4526  ast_copy_string(bridge_cdr->accountcode, new_chan_cdr->accountcode, sizeof(bridge_cdr->accountcode));
4527  if (ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) {
4529  }
4530  }
4531 
4532  /* we can post the bridge CDR at this point */
4533  if (bridge_cdr) {
4534  ast_cdr_end(bridge_cdr);
4535  ast_cdr_detach(bridge_cdr);
4536  }
4537 
4538  /* do a specialized reset on the beginning channel
4539  CDR's, if they still exist, so as not to mess up
4540  issues in future bridges;
4541 
4542  Here are the rules of the game:
4543  1. The chan and peer channel pointers will not change
4544  during the life of the bridge.
4545  2. But, in transfers, the channel names will change.
4546  between the time the bridge is started, and the
4547  time the channel ends.
4548  Usually, when a channel changes names, it will
4549  also change CDR pointers.
4550  3. Usually, only one of the two channels (chan or peer)
4551  will change names.
4552  4. Usually, if a channel changes names during a bridge,
4553  it is because of a transfer. Usually, in these situations,
4554  it is normal to see 2 bridges running simultaneously, and
4555  it is not unusual to see the two channels that change
4556  swapped between bridges.
4557  5. After a bridge occurs, we have 2 or 3 channels' CDRs
4558  to attend to; if the chan or peer changed names,
4559  we have the before and after attached CDR's.
4560  */
4561 
4562  if (new_chan_cdr) {
4563  struct ast_channel *chan_ptr = NULL;
4564 
4565  if (strcasecmp(orig_channame, chan->name) != 0) {
4566  /* old channel */
4567  if ((chan_ptr = ast_channel_get_by_name(orig_channame))) {
4568  ast_channel_lock(chan_ptr);
4569  if (!ast_bridged_channel(chan_ptr)) {
4570  struct ast_cdr *cur;
4571  for (cur = chan_ptr->cdr; cur; cur = cur->next) {
4572  if (cur == chan_cdr) {
4573  break;
4574  }
4575  }
4576  if (cur) {
4577  ast_cdr_specialized_reset(chan_cdr, 0);
4578  }
4579  }
4580  ast_channel_unlock(chan_ptr);
4581  chan_ptr = ast_channel_unref(chan_ptr);
4582  }
4583  /* new channel */
4584  ast_cdr_specialized_reset(new_chan_cdr, 0);
4585  } else {
4586  ast_cdr_specialized_reset(chan->cdr, 0); /* nothing changed, reset the chan cdr */
4587  }
4588  }
4589 
4590  {
4591  struct ast_channel *chan_ptr = NULL;
4592  new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
4593  if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED))
4594  ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
4595  if (strcasecmp(orig_peername, peer->name) != 0) {
4596  /* old channel */
4597  if ((chan_ptr = ast_channel_get_by_name(orig_peername))) {
4598  ast_channel_lock(chan_ptr);
4599  if (!ast_bridged_channel(chan_ptr)) {
4600  struct ast_cdr *cur;
4601  for (cur = chan_ptr->cdr; cur; cur = cur->next) {
4602  if (cur == peer_cdr) {
4603  break;
4604  }
4605  }
4606  if (cur) {
4607  ast_cdr_specialized_reset(peer_cdr, 0);
4608  }
4609  }
4610  ast_channel_unlock(chan_ptr);
4611  chan_ptr = ast_channel_unref(chan_ptr);
4612  }
4613  /* new channel */
4614  if (new_peer_cdr) {
4615  ast_cdr_specialized_reset(new_peer_cdr, 0);
4616  }
4617  } else {
4618  if (we_disabled_peer_cdr) {
4620  }
4621  ast_cdr_specialized_reset(peer->cdr, 0); /* nothing changed, reset the peer cdr */
4622  }
4623  }
4624 
4625  return res;
4626 }
union ast_frame_subclass subclass
Definition: frame.h:146
#define ast_channel_lock(chan)
Definition: channel.h:2466
void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
Simulate a DTMF end on a broken bridge channel.
Definition: features.c:3927
Main Channel structure associated with a channel.
Definition: channel.h:742
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:114
long feature_timer
Definition: channel.h:980
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_OPTION_AUDIO_MODE
Definition: frame.h:453
struct timeval feature_start_time
Definition: channel.h:979
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
int priority
Definition: channel.h:841
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
const ast_string_field uniqueid
Definition: channel.h:787
struct ast_flags features_callee
Definition: channel.h:976
static void clear_dialed_interfaces(struct ast_channel *chan)
Definition: features.c:3911
int visible_indication
Definition: channel.h:861
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:94
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
int option_debug
Definition: asterisk.c:182
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
void ast_cdr_end(struct ast_cdr *cdr)
End a call.
Definition: cdr.c:933
void * ptr
Definition: frame.h:160
static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
Definition: features.c:3897
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield)
Append to CDR user field for channel (stored in CDR)
Definition: cdr.c:1069
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
Report a channel event.
Definition: cel.c:645
struct ast_cdr * next
Definition: cdr.h:132
a bridge is established
Definition: cel.h:62
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:90
#define ast_opt_end_cdr_before_h_exten
Definition: options.h:122
int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
Set account code, will generate AMI event.
Definition: cdr.c:990
#define AST_OPTION_DIGIT_DETECT
Definition: frame.h:508
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
#define AST_OPTION_TDD
Definition: frame.h:445
char uniqueid[150]
Definition: cdr.h:121
static int monitor_ok
Definition: features.c:640
void ast_cdr_setdisposition(struct ast_cdr *cdr, long int disposition)
Set the disposition for a call.
Definition: cdr.c:847
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4447
#define FEATURE_MAX_LEN
Definition: features.h:30
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define AST_OPTION_TONE_VERIFY
Definition: frame.h:441
struct ast_cdr * cdr
Definition: channel.h:766
#define ast_opt_transmit_silence
Definition: options.h:120
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
static struct ast_cdr * pick_unlocked_cdr(struct ast_cdr *cdr)
return the first unlocked cdr in a possible chain
Definition: features.c:3854
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
Run a connected line interception macro and update a channel&#39;s connected line information.
Definition: channel.c:9618
const char * data
Definition: channel.h:755
int ast_default_amaflags
Definition: cdr.c:59
#define LOG_DEBUG
Definition: logger.h:122
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7795
#define ast_verb(level,...)
Definition: logger.h:243
const char * appl
Definition: channel.h:754
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:1057
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
Definition: cdr.c:883
int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
Bridge two channels together.
Definition: channel.c:7506
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:98
static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Definition: features.c:3449
long int amaflags
Definition: cdr.h:112
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_raw_answer(struct ast_channel *chan, int cdr_answer)
Answer a channel.
Definition: channel.c:2930
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_MAX_EXTENSION
Definition: channel.h:135
int datalen
Definition: frame.h:148
void ast_cdr_answer(struct ast_cdr *cdr)
Answer a call.
Definition: cdr.c:737
void * end_bridge_callback_data
Definition: channel.h:989
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
void ast_cdr_setanswer(struct ast_cdr *cdr, struct timeval t)
Set the answer time for a call.
Definition: cdr.c:834
#define AST_FEATURE_RETURN_PASSDIGITS
Definition: features.h:43
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:88
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
void ast_channel_set_linkgroup(struct ast_channel *chan, struct ast_channel *peer)
propagate the linked id between chan and peer
Definition: channel.c:6387
char sending_dtmf_digit
Definition: channel.h:873
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
static struct ast_app * monitor_app
Definition: features.c:639
struct ast_cdr * ast_cdr_dup_unique_swap(struct ast_cdr *cdr)
Duplicate a record and increment the sequence number of the old record.
Definition: cdr.c:200
int ast_cdr_update(struct ast_channel *chan)
Update CDR on a channel.
Definition: cdr.c:1083
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define AST_OPTION_FAX_DETECT
Definition: frame.h:512
struct ast_flags features_caller
Definition: channel.h:975
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8309
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
struct timeval answer
Definition: cdr.h:102
Responsible for call detail data.
Definition: cdr.h:82
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:96
void ast_cdr_start(struct ast_cdr *cdr)
Start a call.
Definition: cdr.c:727
#define AST_OPTION_FLAG_REQUEST
Definition: frame.h:431
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:120
static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code)
Check if a feature exists.
Definition: features.c:3440
#define AST_OPTION_RELAXDTMF
Definition: frame.h:449
struct timeval sending_dtmf_tv
Definition: channel.h:874
void ast_cdr_detach(struct ast_cdr *cdr)
Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other...
Definition: cdr.c:1328
enum ast_channel_state _state
Definition: channel.h:839
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
const ast_string_field name
Definition: channel.h:787
void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Definition: cdr.c:1192
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int _softhangup
Definition: channel.h:832
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8355
struct timeval start
Definition: cdr.h:100
#define AST_MAX_CONTEXT
Definition: channel.h:136
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
#define AST_CHANNEL_NAME
Definition: channel.h:137
int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
Definition: cdr.c:383
static int featuredigittimeout
Definition: features.c:615
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
Structure used to handle boolean flags.
Definition: utils.h:200
#define ast_clear_flag(p, flag)
Definition: utils.h:77
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
Definition: pbx.c:5425
uint8_t data[0]
Definition: frame.h:545
#define FEATURE_SENSE_PEER
Definition: features.h:50
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2473
void ast_cdr_discard(struct ast_cdr *cdr)
Discard and free a CDR record.
Definition: cdr.c:488
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
const ast_string_field accountcode
Definition: channel.h:787
Data structure associated with a single frame of data.
Definition: frame.h:142
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
Definition: features.c:3865
enum ast_frame_type frametype
Definition: frame.h:144
long int disposition
Definition: cdr.h:110
#define ast_frfree(fr)
Definition: frame.h:583
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send DTMF to a channel.
Definition: app.c:501
void(* end_bridge_callback)(void *)
Definition: channel.h:988
void ast_channel_log(char *title, struct ast_channel *chan)
Definition: features.c:3832
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
int amaflags
Definition: channel.h:843
union ast_frame::@172 data
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:499
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define FEATURE_SENSE_CHAN
Definition: features.h:49
a bridge is torn down
Definition: cel.h:64
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame)
Run a redirecting interception macro and update a channel&#39;s redirecting information.
Definition: channel.c:9663
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:125
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense)
Check the dynamic features.
Definition: features.c:3403
void ast_bridge_end_dtmf ( struct ast_channel chan,
char  digit,
struct timeval  start,
const char *  why 
)

Simulate a DTMF end on a broken bridge channel.

Parameters
chanChannel sending DTMF that has not ended.
digitDTMF digit to stop.
startDTMF digit start time.
whyReason bridge broken.
Returns
Nothing

Definition at line 3927 of file features.c.

References ast_channel::_softhangup, ast_channel_lock, ast_channel_unlock, AST_FLAG_ZOMBIE, ast_log(), ast_senddigit_end(), AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_UNBRIDGE, ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), LOG_DTMF, and ast_channel::name.

Referenced by ast_bridge_call(), and ast_do_masquerade().

3928 {
3929  int dead;
3930  long duration;
3931 
3932  ast_channel_lock(chan);
3933  dead = ast_test_flag(chan, AST_FLAG_ZOMBIE)
3934  || (chan->_softhangup
3936  ast_channel_unlock(chan);
3937  if (dead) {
3938  /* Channel is a zombie or a real hangup. */
3939  return;
3940  }
3941 
3942  duration = ast_tvdiff_ms(ast_tvnow(), start);
3943  ast_senddigit_end(chan, digit, duration);
3944  ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
3945  digit, chan->name, why, duration);
3946 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration)
Send a DTMF digit to a channel.
Definition: channel.c:4755
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int _softhangup
Definition: channel.h:832
#define ast_channel_unlock(chan)
Definition: channel.h:2467
struct timeval start
Definition: cdr.h:100
long int duration
Definition: cdr.h:106
#define LOG_DTMF
Definition: logger.h:177
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 7532 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, 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().

7534 {
7535  char *stringp = ast_strdupa(parse);
7536  char *limit_str, *warning_str, *warnfreq_str;
7537  const char *var;
7538  int play_to_caller = 0, play_to_callee = 0;
7539  int delta;
7540 
7541  limit_str = strsep(&stringp, ":");
7542  warning_str = strsep(&stringp, ":");
7543  warnfreq_str = strsep(&stringp, ":");
7544 
7545  config->timelimit = atol(limit_str);
7546  if (warning_str)
7547  config->play_warning = atol(warning_str);
7548  if (warnfreq_str)
7549  config->warning_freq = atol(warnfreq_str);
7550 
7551  if (!config->timelimit) {
7552  ast_log(LOG_WARNING, "Bridge does not accept L(%s), hanging up.\n", limit_str);
7553  config->timelimit = config->play_warning = config->warning_freq = 0;
7554  config->warning_sound = NULL;
7555  return -1; /* error */
7556  } else if ( (delta = config->play_warning - config->timelimit) > 0) {
7557  int w = config->warning_freq;
7558 
7559  /*
7560  * If the first warning is requested _after_ the entire call
7561  * would end, and no warning frequency is requested, then turn
7562  * off the warning. If a warning frequency is requested, reduce
7563  * the 'first warning' time by that frequency until it falls
7564  * within the call's total time limit.
7565  *
7566  * Graphically:
7567  * timelim->| delta |<-playwarning
7568  * 0__________________|_________________|
7569  * | w | | | |
7570  *
7571  * so the number of intervals to cut is 1+(delta-1)/w
7572  */
7573  if (w == 0) {
7574  config->play_warning = 0;
7575  } else {
7576  config->play_warning -= w * ( 1 + (delta-1)/w );
7577  if (config->play_warning < 1)
7578  config->play_warning = config->warning_freq = 0;
7579  }
7580  }
7581 
7582  ast_channel_lock(chan);
7583 
7584  var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
7585  play_to_caller = var ? ast_true(var) : 1;
7586 
7587  var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
7588  play_to_callee = var ? ast_true(var) : 0;
7589 
7590  if (!play_to_caller && !play_to_callee)
7591  play_to_caller = 1;
7592 
7593  var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
7594  config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
7595 
7596  /* The code looking at config wants a NULL, not just "", to decide
7597  * that the message should not be played, so we replace "" with NULL.
7598  * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
7599  * not found.
7600  */
7601 
7602  var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
7603  config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
7604 
7605  var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
7606  config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
7607 
7608  ast_channel_unlock(chan);
7609 
7610  /* undo effect of S(x) in case they are both used */
7611  calldurationlimit->tv_sec = 0;
7612  calldurationlimit->tv_usec = 0;
7613 
7614  /* more efficient to do it like S(x) does since no advanced opts */
7615  if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
7616  calldurationlimit->tv_sec = config->timelimit / 1000;
7617  calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
7618  ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
7619  calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
7620  config->timelimit = play_to_caller = play_to_callee =
7621  config->play_warning = config->warning_freq = 0;
7622  } else {
7623  ast_verb(4, "Limit Data for this call:\n");
7624  ast_verb(4, "timelimit = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0);
7625  ast_verb(4, "play_warning = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0);
7626  ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
7627  ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
7628  ast_verb(4, "warning_freq = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0);
7629  ast_verb(4, "start_sound = %s\n", S_OR(config->start_sound, ""));
7630  ast_verb(4, "warning_sound = %s\n", config->warning_sound);
7631  ast_verb(4, "end_sound = %s\n", S_OR(config->end_sound, ""));
7632  }
7633  if (play_to_caller)
7635  if (play_to_callee)
7637  return 0;
7638 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
char * strsep(char **str, const char *delims)
struct ast_flags features_callee
Definition: channel.h:976
#define ast_strdup(a)
Definition: astmm.h:109
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
#define var
Definition: ast_expr2f.c:606
#define ast_verb(level,...)
Definition: logger.h:243
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
const char * start_sound
Definition: channel.h:986
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const char * end_sound
Definition: channel.h:985
struct ast_flags features_caller
Definition: channel.h:975
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
const char * warning_sound
Definition: channel.h:984
int ast_can_pickup ( struct ast_channel chan)

Test if a channel can be picked up.

Parameters
chanChannel to test if can be picked up.
Note
This function assumes that chan is locked.
Returns
TRUE if channel can be picked up.

Definition at line 7338 of file features.c.

References ast_channel::_state, ast_channel_datastore_find(), AST_FLAG_ZOMBIE, AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, ast_test_flag, ast_channel::masq, and ast_channel::pbx.

Referenced by find_by_mark(), find_by_part(), find_channel_by_group(), pickup_by_exten(), and pickup_by_name_cb().

7339 {
7340  if (!chan->pbx && !chan->masq && !ast_test_flag(chan, AST_FLAG_ZOMBIE)
7341  && (chan->_state == AST_STATE_RINGING
7342  || chan->_state == AST_STATE_RING
7343  /*
7344  * Check the down state as well because some SIP devices do not
7345  * give 180 ringing when they can just give 183 session progress
7346  * instead. Issue 14005. (Some ISDN switches as well for that
7347  * matter.)
7348  */
7349  || chan->_state == AST_STATE_DOWN)
7350  && !ast_channel_datastore_find(chan, &pickup_active, NULL)) {
7351  return 1;
7352  }
7353  return 0;
7354 }
struct ast_channel * masq
Definition: channel.h:751
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
static struct ast_datastore_info pickup_active
Definition: features.c:7334
enum ast_channel_state _state
Definition: channel.h:839
struct ast_pbx * pbx
Definition: channel.h:761
int ast_do_pickup ( struct ast_channel chan,
struct ast_channel target 
)

Pickup a call target.

Parameters
chanchannel that initiated pickup.
targetchannel to be picked up.
Note
This function assumes that target is locked.
Return values
0on success.
-1on failure.

< A masquerade changes channel names.

< A masquerade changes channel names.

Definition at line 7414 of file features.c.

References ast_answer(), AST_CEL_PICKUP, ast_cel_report_event(), ast_channel_connected_line_macro(), ast_channel_datastore_add(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_masquerade(), ast_channel_queue_connected_line_update(), ast_channel_unlock, ast_channel_update_connected_line(), ast_connected_line_copy_from_caller(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, ast_datastore_alloc(), ast_datastore_free(), ast_debug, ast_do_masquerade(), AST_FLAG_ANSWERED_ELSEWHERE, ast_log(), ast_manager_event_multichan, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_queue_control(), ast_set_flag, ast_strdupa, ast_channel::caller, ast_channel::connected, EVENT_FLAG_CALL, LOG_WARNING, ast_channel::name, and ast_party_connected_line::source.

Referenced by ast_pickup_call(), pickup_by_channel(), pickup_by_exten(), pickup_by_group(), pickup_by_mark(), and pickup_by_part().

7415 {
7416  struct ast_party_connected_line connected_caller;
7417  struct ast_channel *chans[2] = { chan, target };
7418  struct ast_datastore *ds_pickup;
7419  const char *chan_name;/*!< A masquerade changes channel names. */
7420  const char *target_name;/*!< A masquerade changes channel names. */
7421  int res = -1;
7422 
7423  target_name = ast_strdupa(target->name);
7424  ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, chan->name);
7425 
7426  /* Mark the target to block any call pickup race. */
7427  ds_pickup = ast_datastore_alloc(&pickup_active, NULL);
7428  if (!ds_pickup) {
7430  "Unable to create channel datastore on '%s' for call pickup\n", target_name);
7431  return -1;
7432  }
7433  ast_channel_datastore_add(target, ds_pickup);
7434 
7435  ast_party_connected_line_init(&connected_caller);
7436  ast_party_connected_line_copy(&connected_caller, &target->connected);
7437  ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */
7438  connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
7439  if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
7440  ast_channel_update_connected_line(chan, &connected_caller, NULL);
7441  }
7442  ast_party_connected_line_free(&connected_caller);
7443 
7444  ast_channel_lock(chan);
7445  chan_name = ast_strdupa(chan->name);
7446  ast_connected_line_copy_from_caller(&connected_caller, &chan->caller);
7447  ast_channel_unlock(chan);
7448  connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
7449 
7450  ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan);
7451 
7452  if (ast_answer(chan)) {
7453  ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
7454  goto pickup_failed;
7455  }
7456 
7458  ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
7459  goto pickup_failed;
7460  }
7461 
7462  ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
7463 
7464  /* setting this flag to generate a reason header in the cancel message to the ringing channel */
7466 
7467  if (ast_channel_masquerade(target, chan)) {
7468  ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan_name,
7469  target_name);
7470  goto pickup_failed;
7471  }
7472 
7473  /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
7474  ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
7475  "Channel: %s\r\n"
7476  "TargetChannel: %s\r\n",
7477  chan_name, target_name);
7478 
7479  /* Do the masquerade manually to make sure that it is completed. */
7480  ast_do_masquerade(target);
7481  res = 0;
7482 
7483 pickup_failed:
7484  ast_channel_lock(target);
7485  if (!ast_channel_datastore_remove(target, ds_pickup)) {
7486  ast_datastore_free(ds_pickup);
7487  }
7488  ast_party_connected_line_free(&connected_caller);
7489 
7490  return res;
7491 }
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2308
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
Definition: channel.c:1601
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
Report a channel event.
Definition: cel.c:645
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
Definition: channel.c:9085
#define EVENT_FLAG_CALL
Definition: manager.h:72
Structure for a data store object.
Definition: datastore.h:54
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2353
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
Run a connected line interception macro and update a channel&#39;s connected line information.
Definition: channel.c:9618
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
Definition: channel.c:9098
static struct ast_datastore_info pickup_active
Definition: features.c:7334
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
Connected Line/Party information.
Definition: channel.h:401
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:2316
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8443
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
#define ast_manager_event_multichan(category, event, nchans, chans, contents,...)
Definition: manager.h:226
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
a directed pickup was performed on this channel
Definition: cel.h:96
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2599
int ast_do_masquerade(struct ast_channel *chan)
Start masquerading a channel.
Definition: channel.c:6546
int ast_feature_detect ( struct ast_channel chan,
struct ast_flags features,
const char *  code,
struct ast_call_feature feature 
)

detect a feature before bridging

Parameters
chan
featuresan ast_flags ptr
codeptr of input code
feature
Return values
ast_call_featureptr to be set if found

Definition at line 3434 of file features.c.

References FEATURE_INTERPRET_DETECT, and feature_interpret_helper().

Referenced by detect_disconnect().

3434  {
3435 
3436  return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature);
3437 }
static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf, struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
Helper function for feature_interpret and ast_feature_detect.
Definition: features.c:3286
int ast_features_reload ( void  )

Reload call features from features.conf.

Definition at line 6879 of file features.c.

References ast_context_destroy(), ast_context_find(), ast_mutex_lock, ast_mutex_unlock, features_reload_lock, load_config(), parking_con_dial, and registrar.

Referenced by handle_features_reload().

6880 {
6881  struct ast_context *con;
6882  int res;
6883 
6884  ast_mutex_lock(&features_reload_lock);/* Searialize reloading features.conf */
6885 
6886  /*
6887  * Always destroy the parking_con_dial context to remove buildup
6888  * of recalled extensions in the context. At worst, the parked
6889  * call gets hungup attempting to run an invalid extension when
6890  * we are trying to callback the parker or the preset return
6891  * extension. This is a small window of opportunity on an
6892  * execution chain that is not expected to happen very often.
6893  */
6895  if (con) {
6897  }
6898 
6899  res = load_config(1);
6901 
6902  return res;
6903 }
static ast_mutex_t features_reload_lock
Definition: features.c:610
#define ast_mutex_lock(a)
Definition: lock.h:155
static char parking_con_dial[]
Context for parking dialback to parker.
Definition: features.c:607
static char * registrar
Definition: features.c:623
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context (or ANY context if NULL)
Definition: pbx.c:9875
static int load_config(int reload)
Definition: features.c:6717
ast_context: An extension context
Definition: pbx.c:955
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2971
#define ast_mutex_unlock(a)
Definition: lock.h:156
struct ast_call_feature* ast_find_call_feature ( const char *  name)

look for a call feature entry by its sname

Parameters
namea string ptr, should match "automon", "blindxfer", "atxfer", etc.

Definition at line 3160 of file features.c.

References FEATURES_COUNT, and ast_call_feature::sname.

Referenced by action_atxfer(), handle_request_info(), and process_config().

3161 {
3162  int x;
3163  for (x = 0; x < FEATURES_COUNT; x++) {
3164  if (!strcasecmp(name, builtin_features[x].sname))
3165  return &builtin_features[x];
3166  }
3167  return NULL;
3168 }
#define FEATURES_COUNT
Definition: features.c:2977
static const char name[]
static struct ast_call_feature builtin_features[]
Definition: features.c:2981
int ast_masq_park_call ( struct ast_channel park_me,
struct ast_channel parker,
int  timeout,
int *  extout 
)

Park a call via a masqueraded channel.

Parameters
park_meChannel to be parked.
parkerChannel parking the call.
timeoutis a timeout in milliseconds
extoutis a parameter to an int that will hold the parked location, or NULL if you want.

Masquerade the park_me channel into a new, empty channel which is then parked.

Note
Use ast_masq_park_call_exten() instead.
Return values
0on success.
-1on failure.

Definition at line 1857 of file features.c.

References ast_strdupa, ast_park_call_args::extout, masq_park_call(), ast_channel::name, ast_park_call_args::orig_chan_name, and ast_park_call_args::timeout.

Referenced by handle_soft_key_event_message(), handle_stimulus_message(), and parkandannounce_exec().

1858 {
1859  struct ast_park_call_args args = {
1860  .timeout = timeout,
1861  .extout = extout,
1862  };
1863 
1864  if (peer) {
1865  args.orig_chan_name = ast_strdupa(peer->name);
1866  }
1867  return masq_park_call(rchan, peer, &args);
1868 }
const char * orig_chan_name
Definition: features.c:1144
static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
Park call via masqueraded channel and announce parking spot on peer channel.
Definition: features.c:1726
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
int ast_masq_park_call_exten ( struct ast_channel park_me,
struct ast_channel parker,
const char *  park_exten,
const char *  park_context,
int  timeout,
int *  extout 
)

Park a call via a masqueraded channel.

Since
1.8.9
Parameters
park_meChannel to be parked.
parkerChannel parking the call.
park_extenParking lot access extension
park_contextParking lot context
timeoutis a timeout in milliseconds
extoutis a parameter to an int that will hold the parked location, or NULL if you want.

Masquerade the park_me channel into a new, empty channel which is then parked.

Return values
0on success.
-1on failure.

Definition at line 1803 of file features.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_get_extension_app_data(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), create_dynamic_parkinglot(), feature_group_exten::exten, ast_park_call_args::extout, find_parkinglot(), get_parking_exten(), masq_park_call(), ast_channel::name, ast_park_call_args::orig_chan_name, parkeddynamic, ast_park_call_args::parkinglot, parkinglot_unref(), parse(), park_app_args::pl_name, and ast_park_call_args::timeout.

Referenced by __analog_ss_thread(), analog_ss_thread(), and mgcp_ss().

1804 {
1805  int res;
1806  char *parse;
1807  const char *app_data;
1808  struct ast_exten *exten;
1809  struct park_app_args app_args;
1810  struct ast_park_call_args args = {
1811  .timeout = timeout,
1812  .extout = extout,
1813  };
1814 
1815  if (parker) {
1816  args.orig_chan_name = ast_strdupa(parker->name);
1817  }
1818  if (!park_exten || !park_context) {
1819  return masq_park_call(park_me, parker, &args);
1820  }
1821 
1822  /*
1823  * Determiine if the specified park extension has an exclusive
1824  * parking lot to use.
1825  */
1826  if (parker && parker != park_me) {
1827  ast_autoservice_start(park_me);
1828  }
1829  exten = get_parking_exten(park_exten, parker, park_context);
1830  if (exten) {
1831  app_data = ast_get_extension_app_data(exten);
1832  if (!app_data) {
1833  app_data = "";
1834  }
1835  parse = ast_strdupa(app_data);
1836  AST_STANDARD_APP_ARGS(app_args, parse);
1837 
1838  if (!ast_strlen_zero(app_args.pl_name)) {
1839  /* Find the specified exclusive parking lot */
1840  args.parkinglot = find_parkinglot(app_args.pl_name);
1841  if (!args.parkinglot && parkeddynamic) {
1842  args.parkinglot = create_dynamic_parkinglot(app_args.pl_name, park_me);
1843  }
1844  }
1845  }
1846  if (parker && parker != park_me) {
1847  ast_autoservice_stop(park_me);
1848  }
1849 
1850  res = masq_park_call(park_me, parker, &args);
1851  if (args.parkinglot) {
1853  }
1854  return res;
1855 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
const char * orig_chan_name
Definition: features.c:1144
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:11146
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
static struct ast_exten * get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
Definition: features.c:823
static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
Park call via masqueraded channel and announce parking spot on peer channel.
Definition: features.c:1726
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int parkeddynamic
Definition: features.c:588
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
const ast_string_field name
Definition: channel.h:787
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static struct ast_parkinglot * create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
Definition: features.c:1165
struct ast_parkinglot * parkinglot
Parkinglot to be parked in.
Definition: features.c:1152
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
Definition: features.c:5017
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
int ast_park_call ( struct ast_channel park_me,
struct ast_channel parker,
int  timeout,
const char *  park_exten,
int *  extout 
)

Park a call and read back parked location.

Parameters
park_meChannel to be parked.
parkerChannel parking the call.
timeoutis a timeout in milliseconds
park_extenParking lot access extension (Not used)
extoutis a parameter to an int that will hold the parked location, or NULL if you want.

Park the park_me channel, and read back the parked location to the parker channel. 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).

Note
Use ast_park_call_exten() instead.
Return values
0on success.
-1on failure.

Definition at line 1706 of file features.c.

References ast_park_call_args::extout, park_call_full(), and ast_park_call_args::timeout.

1707 {
1708  struct ast_park_call_args args = {
1709  .timeout = timeout,
1710  .extout = extout,
1711  };
1712 
1713  return park_call_full(park_me, parker, &args);
1714 }
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
Definition: features.c:1470
static struct @350 args
int ast_park_call_exten ( struct ast_channel park_me,
struct ast_channel parker,
const char *  park_exten,
const char *  park_context,
int  timeout,
int *  extout 
)

Park a call and read back parked location.

Since
1.8.9
Parameters
park_meChannel to be parked.
parkerChannel parking the call.
park_extenParking lot access extension
park_contextParking lot context
timeoutis a timeout in milliseconds
extoutis a parameter to an int that will hold the parked location, or NULL if you want.

Park the park_me channel, and read back the parked location to the parker channel. 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).

Return values
0on success.
-1on failure.

Definition at line 1655 of file features.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_get_extension_app_data(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), create_dynamic_parkinglot(), feature_group_exten::exten, ast_park_call_args::extout, find_parkinglot(), get_parking_exten(), park_call_full(), parkeddynamic, ast_park_call_args::parkinglot, parkinglot_unref(), parse(), park_app_args::pl_name, and ast_park_call_args::timeout.

Referenced by iax_park_thread(), and sip_park_thread().

1656 {
1657  int res;
1658  char *parse;
1659  const char *app_data;
1660  struct ast_exten *exten;
1661  struct park_app_args app_args;
1662  struct ast_park_call_args args = {
1663  .timeout = timeout,
1664  .extout = extout,
1665  };
1666 
1667  if (!park_exten || !park_context) {
1668  return park_call_full(park_me, parker, &args);
1669  }
1670 
1671  /*
1672  * Determiine if the specified park extension has an exclusive
1673  * parking lot to use.
1674  */
1675  if (parker && parker != park_me) {
1676  ast_autoservice_start(park_me);
1677  }
1678  exten = get_parking_exten(park_exten, parker, park_context);
1679  if (exten) {
1680  app_data = ast_get_extension_app_data(exten);
1681  if (!app_data) {
1682  app_data = "";
1683  }
1684  parse = ast_strdupa(app_data);
1685  AST_STANDARD_APP_ARGS(app_args, parse);
1686 
1687  if (!ast_strlen_zero(app_args.pl_name)) {
1688  /* Find the specified exclusive parking lot */
1689  args.parkinglot = find_parkinglot(app_args.pl_name);
1690  if (!args.parkinglot && parkeddynamic) {
1691  args.parkinglot = create_dynamic_parkinglot(app_args.pl_name, park_me);
1692  }
1693  }
1694  }
1695  if (parker && parker != park_me) {
1696  ast_autoservice_stop(park_me);
1697  }
1698 
1699  res = park_call_full(park_me, parker, &args);
1700  if (args.parkinglot) {
1702  }
1703  return res;
1704 }
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
Definition: features.c:1470
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:11146
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
static struct ast_exten * get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
Definition: features.c:823
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int parkeddynamic
Definition: features.c:588
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static struct ast_parkinglot * create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
Definition: features.c:1165
struct ast_parkinglot * parkinglot
Parkinglot to be parked in.
Definition: features.c:1152
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
Definition: features.c:5017
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
int ast_parking_ext_valid ( const char *  exten_str,
struct ast_channel chan,
const char *  context 
)

Determine if parking extension exists in a given context.

Return values
0if extension does not exist
1if extension does exist

Definition at line 844 of file features.c.

References get_parking_exten().

Referenced by __analog_ss_thread(), analog_ss_thread(), dp_lookup(), handle_request_refer(), mgcp_ss(), and socket_process().

845 {
846  return get_parking_exten(exten_str, chan, context) ? 1 : 0;
847 }
static struct ast_exten * get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
Definition: features.c:823
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int ast_pickup_call ( struct ast_channel chan)

Pickup a call.

Parameters
chanchannel that initiated pickup.

Walk list of channels, checking it is not itself, channel is pbx one, check that the callgroup for both channels are the same and the channel is ringing. Answer calling channel, flag channel as answered on queue, masq channels together.

< Potential pickup target

Definition at line 7380 of file features.c.

References ast_answer(), ast_channel_callback(), ast_channel_unlock, ast_channel_unref, ast_debug, ast_do_pickup(), ast_log(), ast_stream_and_wait(), ast_strlen_zero(), find_channel_by_group(), LOG_NOTICE, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), pickupfailsound, and pickupsound.

Referenced by __analog_ss_thread(), analog_ss_thread(), cb_events(), mgcp_ss(), and sip_pickup_thread().

7381 {
7382  struct ast_channel *target;/*!< Potential pickup target */
7383  int res = -1;
7384  ast_debug(1, "pickup attempt by %s\n", chan->name);
7385 
7386  /* The found channel is already locked. */
7387  target = ast_channel_callback(find_channel_by_group, NULL, chan, 0);
7388  if (target) {
7389  ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", target->name, chan->name);
7390 
7391  res = ast_do_pickup(chan, target);
7392  ast_channel_unlock(target);
7393  if (!res) {
7394  if (!ast_strlen_zero(pickupsound)) {
7395  pbx_builtin_setvar_helper(target, "BRIDGE_PLAY_SOUND", pickupsound);
7396  }
7397  } else {
7398  ast_log(LOG_WARNING, "pickup %s failed by %s\n", target->name, chan->name);
7399  }
7400  target = ast_channel_unref(target);
7401  }
7402 
7403  if (res < 0) {
7404  ast_debug(1, "No call pickup possible... for %s\n", chan->name);
7406  ast_answer(chan);
7408  }
7409  }
7410 
7411  return res;
7412 }
Main Channel structure associated with a channel.
Definition: channel.h:742
static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
Definition: features.c:7356
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define LOG_WARNING
Definition: logger.h:144
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static char pickupsound[256]
Definition: features.c:592
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct ast_channel * ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Call a function with every active channel.
Definition: channel.c:1634
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define ast_channel_unlock(chan)
Definition: channel.h:2467
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
Definition: features.c:7414
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
static char pickupfailsound[256]
Definition: features.c:593
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
const char* ast_pickup_ext ( void  )

Determine system call pickup extension.

Definition at line 849 of file features.c.

References pickup_ext.

Referenced by __analog_ss_thread(), analog_canmatch_featurecode(), analog_ss_thread(), canmatch_featurecode(), cb_events(), get_destination(), handle_feature_show(), handle_request_invite(), and mgcp_ss().

850 {
851  return pickup_ext;
852 }
static char pickup_ext[AST_MAX_EXTENSION]
Definition: features.c:421
void ast_rdlock_call_features ( void  )

Definition at line 3150 of file features.c.

References ast_rwlock_rdlock, and features_lock.

Referenced by handle_request_info().

3151 {
3153 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
static ast_rwlock_t features_lock
Definition: features.c:2979
void ast_register_feature ( struct ast_call_feature feature)

register new feature into feature_set

Parameters
featurean ast_call_feature object which contains a keysequence and a callback function which is called when this keysequence is pressed during a call.

register new feature into feature_set

Definition at line 2994 of file features.c.

References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_call_feature::feature_entry, LOG_NOTICE, and ast_call_feature::sname.

Referenced by process_applicationmap_line().

2995 {
2996  if (!feature) {
2997  ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
2998  return;
2999  }
3000 
3002  AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
3004 
3005  ast_verb(2, "Registered Feature '%s'\n",feature->sname);
3006 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_verb(level,...)
Definition: logger.h:243
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:703
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
char sname[FEATURE_SNAME_LEN]
Definition: features.h:68
void ast_unlock_call_features ( void  )

Definition at line 3155 of file features.c.

References ast_rwlock_unlock, and features_lock.

Referenced by handle_request_info().

3156 {
3158 }
static ast_rwlock_t features_lock
Definition: features.c:2979
#define ast_rwlock_unlock(a)
Definition: lock.h:200
void ast_unregister_feature ( struct ast_call_feature feature)

unregister feature from feature_set

Parameters
featurethe ast_call_feature object which was registered before

Definition at line 3074 of file features.c.

References ast_free, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

3075 {
3076  if (!feature) {
3077  return;
3078  }
3079 
3081  AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
3083 
3084  ast_free(feature);
3085 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_free(a)
Definition: astmm.h:97
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:870