Wed Jan 8 2020 09:50:11

Asterisk developer's documentation


features.c File Reference

Routines implementing call features as call pickup, parking and transfer. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/causes.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
#include "asterisk/say.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/utils.h"
#include "asterisk/adsi.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
#include "asterisk/audiohook.h"
#include "asterisk/global_datastores.h"
#include "asterisk/astobj2.h"
#include "asterisk/cel.h"
#include "asterisk/test.h"

Go to the source code of this file.

Data Structures

struct  ast_bridge_thread_obj
 
struct  ast_dial_features
 
struct  ast_park_call_args
 
struct  ast_parkinglot
 Structure for parking lots which are put in a container. More...
 
struct  feature_group
 
struct  feature_group_exten
 
struct  feature_groups
 
struct  feature_list
 
struct  park_app_args
 
struct  parkeduser
 Description of one parked call, added to a list while active, then removed. The list belongs to a parkinglot. More...
 
struct  parking_dp_context
 
struct  parking_dp_map
 
struct  parking_dp_ramp
 
struct  parking_dp_ramp_map
 
struct  parking_dp_space_map
 
struct  parking_dp_spaces
 
struct  parkinglot_cfg
 
struct  ast_parkinglot::parkinglot_parklist
 

Macros

#define AST_MAX_WATCHERS   256
 
#define DEFAULT_ATXFER_CALLBACK_RETRIES   2
 
#define DEFAULT_ATXFER_DROP_CALL   0
 
#define DEFAULT_ATXFER_LOOP_DELAY   10000
 
#define DEFAULT_FEATURE_DIGIT_TIMEOUT   1000
 
#define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER   15000
 
#define DEFAULT_PARK_EXTENSION   "700"
 
#define DEFAULT_PARK_TIME   45000
 
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT   3000
 
#define FEATURES_COUNT   ARRAY_LEN(builtin_features)
 
#define HFS_FORMAT   "%-25s %-7s %-7s\n"
 
#define MAX_DIAL_FEATURE_OPTIONS   30
 

Enumerations

enum  {
  BRIDGE_OPT_PLAYTONE = (1 << 0), OPT_CALLEE_HANGUP = (1 << 1), OPT_CALLER_HANGUP = (1 << 2), OPT_DURATION_LIMIT = (1 << 3),
  OPT_DURATION_STOP = (1 << 4), OPT_CALLEE_TRANSFER = (1 << 5), OPT_CALLER_TRANSFER = (1 << 6), OPT_CALLEE_MONITOR = (1 << 7),
  OPT_CALLER_MONITOR = (1 << 8), OPT_CALLEE_PARK = (1 << 9), OPT_CALLER_PARK = (1 << 10), OPT_CALLEE_KILL = (1 << 11)
}
 
enum  { OPT_ARG_DURATION_LIMIT = 0, OPT_ARG_DURATION_STOP, OPT_ARG_ARRAY_SIZE }
 
enum  ast_park_call_options { AST_PARK_OPT_RINGING = (1 << 0), AST_PARK_OPT_RANDOMIZE = (1 << 1), AST_PARK_OPT_SILENCE = (1 << 2) }
 
enum  feature_interpret_op { FEATURE_INTERPRET_DETECT, FEATURE_INTERPRET_DO, FEATURE_INTERPRET_CHECK }
 

Functions

static int action_bridge (struct mansession *s, const struct message *m)
 Bridge channels together. More...
 
static int add_features_datastore (struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
 
static void add_features_datastores (struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
 
static int adsi_announce_park (struct ast_channel *chan, char *parkingexten)
 Announce call parking by ADSI. More...
 
int ast_bridge_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
 bridge the call and set CDR 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...
 
void ast_channel_log (char *title, struct ast_channel *chan)
 
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_init (void)
 
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 *rchan, struct ast_channel *peer, 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_list More...
 
void ast_unlock_call_features (void)
 
void ast_unregister_feature (struct ast_call_feature *feature)
 unregister feature from feature_set More...
 
static void ast_unregister_features (void)
 Remove all features in the list. More...
 
static void ast_unregister_groups (void)
 Remove all feature groups in the list. More...
 
static void atxfer_fail_cleanup (struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
 
static void * bridge_call_thread (void *data)
 bridge the call More...
 
static void bridge_call_thread_launch (struct ast_bridge_thread_obj *data)
 create thread for the parked call More...
 
static int bridge_exec (struct ast_channel *chan, const char *data)
 Bridge channels. More...
 
static struct parking_dp_contextbuild_dialplan_useage_context (struct ast_parkinglot *lot)
 
static int build_dialplan_useage_map (struct parking_dp_map *usage_map, int complain)
 
static struct parking_dp_rampbuild_dialplan_useage_ramp (const char *exten, int exclusive)
 
static struct parking_dp_spacesbuild_dialplan_useage_spaces (int start, int stop)
 
static struct ast_parkinglotbuild_parkinglot (const char *pl_name, struct ast_variable *var)
 Build parkinglot from configuration and chain it in if it doesn't already exist. More...
 
static int builtin_atxfer (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 Attended transfer. More...
 
static int builtin_automixmonitor (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 
static int builtin_automonitor (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 Monitor a channel by DTMF. More...
 
static int builtin_blindtransfer (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 Blind transfer user to another extension. More...
 
static int builtin_disconnect (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 
static int builtin_parkcall (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 support routing for one touch call parking More...
 
static char * callback_dialoptions (struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
 
static int check_compat (struct ast_channel *c, struct ast_channel *newchan)
 make channels compatible More...
 
static void check_goto_on_transfer (struct ast_channel *chan)
 Check goto on transfer. More...
 
static void clear_dialed_interfaces (struct ast_channel *chan)
 
static struct ast_parkinglotcopy_parkinglot (const char *name, const struct ast_parkinglot *parkinglot)
 Copy parkinglot and store it with new name. More...
 
static struct ast_parkinglotcreate_dynamic_parkinglot (const char *name, struct ast_channel *chan)
 
static struct ast_parkinglotcreate_parkinglot (const char *name)
 Allocate parking lot structure. More...
 
static void destroy_dialplan_usage_context (struct parking_dp_context *doomed)
 
static void destroy_dialplan_usage_map (struct parking_dp_map *doomed)
 
static void destroy_space (const char *context, int space)
 
static void dial_features_destroy (void *data)
 
static void * dial_features_duplicate (void *data)
 
static int dialplan_usage_add_parkinglot (struct parking_dp_map *usage_map, struct ast_parkinglot *lot, int complain)
 
static int dialplan_usage_add_parkinglot_data (struct parking_dp_context *ctx_node, struct ast_parkinglot *lot, int complain)
 
static int do_bridge_masquerade (struct ast_channel *chan, struct ast_channel *tmpchan)
 Actual bridge. More...
 
static void * do_parking_thread (void *ignore)
 Take care of parked calls and unpark them if needed. More...
 
static int feature_check (struct ast_channel *chan, struct ast_flags *features, char *code)
 Check if a feature exists. More...
 
static int feature_exec_app (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 exec an app by feature More...
 
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. More...
 
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. More...
 
static struct ast_channelfeature_request_and_dial (struct ast_channel *caller, const char *caller_name, struct ast_channel *requestor, struct ast_channel *transferee, const char *type, format_t format, void *data, int timeout, int *outstate, const char *language)
 
static void features_shutdown (void)
 
static int find_channel_by_group (void *obj, void *arg, void *data, int flags)
 
static struct ast_call_featurefind_dynamic_feature (const char *name)
 find a call feature by name More...
 
static struct feature_groupfind_group (const char *name)
 Find a group by name. More...
 
static struct ast_parkinglotfind_parkinglot (const char *name)
 Find parkinglot by name. More...
 
static const char * findparkinglotname (struct ast_channel *chan)
 Find parking lot name from channel. More...
 
static int finishup (struct ast_channel *chan)
 
static struct ast_extenget_parking_exten (const char *exten_str, struct ast_channel *chan, const char *context)
 
static char * handle_feature_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list configured features. More...
 
static char * handle_features_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_parkedcalls (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list parked calls. More...
 
static int load_config (int reload)
 
static int manage_parked_call (struct parkeduser *pu, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
 
static void manage_parkinglot (struct ast_parkinglot *curlot, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
 Run management on parkinglots, called once per parkinglot. More...
 
static int manager_park (struct mansession *s, const struct message *m)
 Create manager event for parked calls. More...
 
static int manager_parking_status (struct mansession *s, const struct message *m)
 Dump parking lot status. More...
 
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. More...
 
static enum ast_device_state metermaidstate (const char *data)
 metermaids callback from devicestate.c More...
 
static void notify_metermaids (const char *exten, char *context, enum ast_device_state state)
 Notify metermaids that we've changed an extension. More...
 
static void park_add_hints (const char *context, int start, int stop)
 Add parking hints for all defined parking spaces. More...
 
static int park_call_exec (struct ast_channel *chan, const char *data)
 Park a call. More...
 
static int park_call_full (struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
 
static void park_space_abort (struct parkeduser *pu)
 
static struct parkeduserpark_space_reserve (struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
 
static int parked_call_exec (struct ast_channel *chan, const char *data)
 Pickup parked call. More...
 
static int parkinglot_activate (struct ast_parkinglot *parkinglot)
 
static int parkinglot_activate_cb (void *obj, void *arg, int flags)
 
static struct ast_parkinglotparkinglot_addref (struct ast_parkinglot *parkinglot)
 
static int parkinglot_cmp_cb (void *obj, void *arg, int flags)
 
static int parkinglot_config_read (const char *pl_name, struct parkinglot_cfg *cfg, struct ast_variable *var)
 
static void parkinglot_destroy (void *obj)
 Destroy a parking lot. More...
 
static void parkinglot_feature_flag_cfg (const char *pl_name, int *param, struct ast_variable *var)
 
static int parkinglot_hash_cb (const void *obj, const int flags)
 
static int parkinglot_is_marked_cb (void *obj, void *arg, int flags)
 
static int parkinglot_markall_cb (void *obj, void *arg, int flags)
 
static void parkinglot_unref (struct ast_parkinglot *parkinglot)
 Unreference parkinglot object. More...
 
static struct ast_cdrpick_unlocked_cdr (struct ast_cdr *cdr)
 return the first unlocked cdr in a possible chain More...
 
static int play_message_in_bridged_call (struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
 Play message to both caller and callee in bridged call, plays synchronously, autoservicing the other channel during the message, so please don't use this for very long messages. More...
 
static int play_message_on_chan (struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
 
static int play_message_to_chans (struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
 
static void post_manager_event (const char *s, struct parkeduser *pu)
 Output parking event to manager. More...
 
static void process_applicationmap_line (struct ast_variable *var)
 
static int process_config (struct ast_config *cfg)
 
static const char * real_ctx (struct ast_channel *transferer, struct ast_channel *transferee)
 Find the context for the transfer. More...
 
static struct feature_groupregister_group (const char *fgname)
 Add new feature group. More...
 
static void register_group_feature (struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
 Add feature to group. More...
 
static int remap_feature (const char *name, const char *value)
 
static void remove_dead_context_usage (const char *context, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
 
static void remove_dead_dialplan_useage (struct parking_dp_map *old_map, struct parking_dp_map *new_map)
 
static void remove_dead_ramp_usage (const char *context, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
 
static void remove_dead_spaces_usage (const char *context, struct parking_dp_space_map *old_spaces, struct parking_dp_space_map *new_spaces, void(*destroy_space)(const char *context, int space))
 
static void remove_exten_if_exist (const char *context, const char *exten, int priority)
 
static void set_bridge_features_on_config (struct ast_bridge_config *config, const char *features)
 
static void set_c_e_p (struct ast_channel *chan, const char *context, const char *ext, int pri)
 store context, extension and priority More...
 
static int set_chan_app_data (struct ast_channel *chan, const char *src_app_data)
 
static void set_config_flags (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
 
static void set_peers (struct ast_channel **caller, struct ast_channel **callee, struct ast_channel *peer, struct ast_channel *chan, int sense)
 set caller and callee according to the direction More...
 
static void unmap_features (void)
 
static int usage_context_add_ramp (struct parking_dp_ramp_map *ramp_map, const char *exten, int exclusive, struct ast_parkinglot *lot, int complain)
 
static int usage_context_add_spaces (struct parking_dp_space_map *space_map, int start, int stop, struct ast_parkinglot *lot, int complain)
 
static int xfer_park_call_helper (struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
 

Variables

static int adsipark
 
static char * app_bridge = "Bridge"
 
static unsigned int atxfercallbackretries
 
static unsigned int atxferdropcall
 
static unsigned int atxferloopdelay
 
static int atxfernoanswertimeout
 
static struct ast_app_option bridge_exec_options [128] = { [ 'p' ] = { .flag = BRIDGE_OPT_PLAYTONE }, [ 'h' ] = { .flag = OPT_CALLEE_HANGUP }, [ 'H' ] = { .flag = OPT_CALLER_HANGUP }, [ 'k' ] = { .flag = OPT_CALLEE_PARK }, [ 'K' ] = { .flag = OPT_CALLER_PARK }, [ 'L' ] = { .flag = OPT_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, [ 'S' ] = { .flag = OPT_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 't' ] = { .flag = OPT_CALLEE_TRANSFER }, [ 'T' ] = { .flag = OPT_CALLER_TRANSFER }, [ 'w' ] = { .flag = OPT_CALLEE_MONITOR }, [ 'W' ] = { .flag = OPT_CALLER_MONITOR }, [ 'x' ] = { .flag = OPT_CALLEE_KILL }, }
 
static struct ast_call_feature builtin_features []
 
static struct ast_datastore_info channel_app_data_datastore
 
static struct ast_cli_entry cli_features []
 
static int comebacktoorigin = 1
 
static char courtesytone [256]
 
static struct ast_parkinglotdefault_parkinglot
 Default parking lot. More...
 
static struct ast_datastore_info dial_features_info
 
static struct feature_groups feature_groups = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
 
static struct feature_list feature_list = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
 
static int featuredigittimeout
 
static ast_rwlock_t features_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 }
 
static ast_mutex_t features_reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 
static int force_reload_load
 
static struct ast_appmixmonitor_app = NULL
 
static int mixmonitor_ok = 1
 
static struct ast_appmonitor_app = NULL
 
static int monitor_ok = 1
 
static struct ast_app_option park_call_options [128] = { [ 'r' ] = { .flag = AST_PARK_OPT_RINGING }, [ 'R' ] = { .flag = AST_PARK_OPT_RANDOMIZE }, [ 's' ] = { .flag = AST_PARK_OPT_SILENCE }, }
 
static const char * parkcall = "Park"
 
static const char * parkedcall = "ParkedCall"
 
static int parkeddynamic = 0
 
static int parkedplay = 0
 
static char parking_con_dial [] = "park-dial"
 Context for parking dialback to parker. More...
 
static pthread_t parking_thread
 
static struct parkinglot_cfg parkinglot_cfg_default
 
static struct parkinglot_cfg parkinglot_cfg_default_default
 
static struct ao2_containerparkinglots
 The configured parking lots container. Always at least one - the default parking lot. More...
 
static char parkingretalertinfo [256]
 
static char parkingretcidname [256]
 
static char parkingretdahdiring [3]
 
static struct ast_datastore_info pickup_active
 
static char pickup_ext [AST_MAX_EXTENSION]
 
static char pickupfailsound [256]
 
static char pickupsound [256]
 
static char * registrar = "features"
 
static struct ast_appstopmixmonitor_app = NULL
 
static int stopmixmonitor_ok = 1
 
static int transferdigittimeout
 
static char xferfailsound [256]
 
static char xfersound [256]
 

Detailed Description

Routines implementing call features as call pickup, parking and transfer.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file features.c.

Macro Definition Documentation

#define AST_MAX_WATCHERS   256

Definition at line 392 of file features.c.

#define DEFAULT_ATXFER_CALLBACK_RETRIES   2

Definition at line 390 of file features.c.

Referenced by process_config().

#define DEFAULT_ATXFER_DROP_CALL   0

Do not drop call.

Definition at line 388 of file features.c.

Referenced by process_config().

#define DEFAULT_ATXFER_LOOP_DELAY   10000

ms

Definition at line 389 of file features.c.

Referenced by process_config().

#define DEFAULT_FEATURE_DIGIT_TIMEOUT   1000

ms

Definition at line 386 of file features.c.

Referenced by process_config().

#define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER   15000

ms

Definition at line 387 of file features.c.

Referenced by process_config().

#define DEFAULT_PARK_EXTENSION   "700"

Definition at line 384 of file features.c.

#define DEFAULT_PARK_TIME   45000

ms

Definition at line 383 of file features.c.

#define DEFAULT_TRANSFER_DIGIT_TIMEOUT   3000

ms

Definition at line 385 of file features.c.

Referenced by process_config().

#define HFS_FORMAT   "%-25s %-7s %-7s\n"

Referenced by handle_feature_show().

#define MAX_DIAL_FEATURE_OPTIONS   30

Definition at line 393 of file features.c.

Referenced by manage_parked_call().

Enumeration Type Documentation

anonymous enum
Enumerator
BRIDGE_OPT_PLAYTONE 
OPT_CALLEE_HANGUP 
OPT_CALLER_HANGUP 
OPT_DURATION_LIMIT 
OPT_DURATION_STOP 
OPT_CALLEE_TRANSFER 
OPT_CALLER_TRANSFER 
OPT_CALLEE_MONITOR 
OPT_CALLER_MONITOR 
OPT_CALLEE_PARK 
OPT_CALLER_PARK 
OPT_CALLEE_KILL 

Definition at line 7495 of file features.c.

7495  {
7496  BRIDGE_OPT_PLAYTONE = (1 << 0),
7497  OPT_CALLEE_HANGUP = (1 << 1),
7498  OPT_CALLER_HANGUP = (1 << 2),
7499  OPT_DURATION_LIMIT = (1 << 3),
7500  OPT_DURATION_STOP = (1 << 4),
7501  OPT_CALLEE_TRANSFER = (1 << 5),
7502  OPT_CALLER_TRANSFER = (1 << 6),
7503  OPT_CALLEE_MONITOR = (1 << 7),
7504  OPT_CALLER_MONITOR = (1 << 8),
7505  OPT_CALLEE_PARK = (1 << 9),
7506  OPT_CALLER_PARK = (1 << 10),
7507  OPT_CALLEE_KILL = (1 << 11),
7508 };
anonymous enum
Enumerator
OPT_ARG_DURATION_LIMIT 
OPT_ARG_DURATION_STOP 
OPT_ARG_ARRAY_SIZE 

Definition at line 7510 of file features.c.

7510  {
7513  /* note: this entry _MUST_ be the last one in the enum */
7515 };

Options to pass to park_call_full

Enumerator
AST_PARK_OPT_RINGING 

Provide ringing to the parked caller instead of music on hold

AST_PARK_OPT_RANDOMIZE 

Randomly choose a parking spot for the caller instead of choosing the first one that is available.

AST_PARK_OPT_SILENCE 

Do not announce the parking number

Definition at line 1125 of file features.c.

1125  {
1126  /*! Provide ringing to the parked caller instead of music on hold */
1127  AST_PARK_OPT_RINGING = (1 << 0),
1128  /*! Randomly choose a parking spot for the caller instead of choosing
1129  * the first one that is available. */
1130  AST_PARK_OPT_RANDOMIZE = (1 << 1),
1131  /*! Do not announce the parking number */
1132  AST_PARK_OPT_SILENCE = (1 << 2),
1133 };
Enumerator
FEATURE_INTERPRET_DETECT 
FEATURE_INTERPRET_DO 
FEATURE_INTERPRET_CHECK 

Definition at line 413 of file features.c.

413  {
414  FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
415  FEATURE_INTERPRET_DO, /* Used by feature_interpret */
416  FEATURE_INTERPRET_CHECK, /* Used by feature_check */
feature_interpret_op
Definition: features.c:413

Function Documentation

static int action_bridge ( struct mansession s,
const struct message m 
)
static

Bridge channels together.

Parameters
s
mMake sure valid channels were specified, send errors if any of the channels could not be found/locked, answer channels if needed, create the placeholder channels and grab the other channels make the channels compatible, send error if we fail doing so setup the bridge thread object and start the bridge.
Return values
0

Definition at line 6975 of file features.c.

References ast_channel::_state, ast_answer(), ast_calloc, ast_channel_alloc(), ast_channel_get_by_name_prefix(), ast_channel_make_compatible(), ast_channel_unref, ast_hangup(), ast_log(), ast_manager_event_multichan, AST_STATE_DOWN, AST_STATE_UP, ast_streamfile(), ast_strlen_zero(), ast_true(), ast_waitstream(), astman_get_header(), astman_send_ack(), astman_send_error(), bridge_call_thread_launch(), ast_bridge_thread_obj::chan, do_bridge_masquerade(), errno, EVENT_FLAG_CALL, ast_channel::linkedid, LOG_WARNING, ast_channel::name, ast_bridge_thread_obj::peer, playtone(), ast_bridge_thread_obj::return_to_pbx, and xfersound.

Referenced by ast_features_init().

6976 {
6977  const char *channela = astman_get_header(m, "Channel1");
6978  const char *channelb = astman_get_header(m, "Channel2");
6979  const char *playtone = astman_get_header(m, "Tone");
6980  struct ast_channel *chana = NULL, *chanb = NULL, *chans[2];
6981  struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
6982  struct ast_bridge_thread_obj *tobj = NULL;
6983  char buf[256];
6984 
6985  /* make sure valid channels were specified */
6986  if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
6987  astman_send_error(s, m, "Missing channel parameter in request");
6988  return 0;
6989  }
6990 
6991  /* Start with chana */
6992  chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
6993  if (!chana) {
6994  snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
6995  astman_send_error(s, m, buf);
6996  return 0;
6997  }
6998 
6999  /* Answer the channels if needed */
7000  if (chana->_state != AST_STATE_UP)
7001  ast_answer(chana);
7002 
7003  /* create the placeholder channels and grab the other channels */
7004  if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
7005  NULL, NULL, chana->linkedid, 0, "Bridge/%s", chana->name))) {
7006  astman_send_error(s, m, "Unable to create temporary channel!");
7007  chana = ast_channel_unref(chana);
7008  return 0;
7009  }
7010 
7011  if (do_bridge_masquerade(chana, tmpchana)) {
7012  snprintf(buf, sizeof(buf), "Unable to masquerade channel %s!", channela);
7013  astman_send_error(s, m, buf);
7014  ast_hangup(tmpchana);
7015  chana = ast_channel_unref(chana);
7016  return 0;
7017  }
7018 
7019  chana = ast_channel_unref(chana);
7020 
7021  /* now do chanb */
7022  chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
7023  if (!chanb) {
7024  snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
7025  astman_send_error(s, m, buf);
7026  ast_hangup(tmpchana);
7027  return 0;
7028  }
7029 
7030  /* Answer the channels if needed */
7031  if (chanb->_state != AST_STATE_UP)
7032  ast_answer(chanb);
7033 
7034  /* create the placeholder channels and grab the other channels */
7035  if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
7036  NULL, NULL, chanb->linkedid, 0, "Bridge/%s", chanb->name))) {
7037  astman_send_error(s, m, "Unable to create temporary channels!");
7038  ast_hangup(tmpchana);
7039  chanb = ast_channel_unref(chanb);
7040  return 0;
7041  }
7042 
7043  if (do_bridge_masquerade(chanb, tmpchanb)) {
7044  snprintf(buf, sizeof(buf), "Unable to masquerade channel %s!", channelb);
7045  astman_send_error(s, m, buf);
7046  ast_hangup(tmpchana);
7047  ast_hangup(tmpchanb);
7048  chanb = ast_channel_unref(chanb);
7049  return 0;
7050  }
7051 
7052  chanb = ast_channel_unref(chanb);
7053 
7054  /* make the channels compatible, send error if we fail doing so */
7055  if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
7056  ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
7057  astman_send_error(s, m, "Could not make channels compatible for manager bridge");
7058  ast_hangup(tmpchana);
7059  ast_hangup(tmpchanb);
7060  return 0;
7061  }
7062 
7063  /* setup the bridge thread object and start the bridge */
7064  if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
7065  ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
7066  astman_send_error(s, m, "Unable to spawn a new bridge thread");
7067  ast_hangup(tmpchana);
7068  ast_hangup(tmpchanb);
7069  return 0;
7070  }
7071 
7072  tobj->chan = tmpchana;
7073  tobj->peer = tmpchanb;
7074  tobj->return_to_pbx = 1;
7075 
7076  if (ast_true(playtone)) {
7077  if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
7078  if (ast_waitstream(tmpchanb, "") < 0)
7079  ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
7080  }
7081  }
7082 
7083  chans[0] = tmpchana;
7084  chans[1] = tmpchanb;
7085 
7086  ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeAction", 2, chans,
7087  "Response: Success\r\n"
7088  "Channel1: %s\r\n"
7089  "Channel2: %s\r\n", tmpchana->name, tmpchanb->name);
7090 
7092 
7093  astman_send_ack(s, m, "Launched bridge thread with success");
7094 
7095  return 0;
7096 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
Main Channel structure associated with a channel.
Definition: channel.h:742
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
struct ast_channel * peer
Definition: features.c:858
struct ast_channel * chan
Definition: features.c:857
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define LOG_WARNING
Definition: logger.h:144
#define EVENT_FLAG_CALL
Definition: manager.h:72
static void playtone(struct ast_channel *chan, int tone, int len)
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
const ast_string_field linkedid
Definition: channel.h:787
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1808
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static int do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
Actual bridge.
Definition: features.c:6933
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
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
enum ast_channel_state _state
Definition: channel.h:839
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 errno
static char xfersound[256]
Definition: features.c:590
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
Definition: channel.c:5970
#define ast_calloc(a, b)
Definition: astmm.h:82
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
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
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
unsigned int return_to_pbx
Definition: features.c:859
static void bridge_call_thread_launch(struct ast_bridge_thread_obj *data)
create thread for the parked call
Definition: features.c:1037
static int add_features_datastore ( struct ast_channel chan,
const struct ast_flags my_features,
const struct ast_flags peer_features 
)
static

Definition at line 768 of file features.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_flags, ast_datastore_alloc(), ast_datastore_free(), AST_FLAGS_ALL, ast_log(), ast_datastore::data, DATASTORE_INHERIT_FOREVER, dial_features_info, ast_datastore::inheritance, LOG_WARNING, ast_dial_features::my_features, and ast_dial_features::peer_features.

Referenced by add_features_datastores(), and builtin_atxfer().

769 {
770  struct ast_datastore *datastore;
771  struct ast_dial_features *dialfeatures;
772 
773  ast_channel_lock(chan);
774  datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL);
775  ast_channel_unlock(chan);
776  if (datastore) {
777  /* Already exists. */
778  return 1;
779  }
780 
781  /* Create a new datastore with specified feature flags. */
782  datastore = ast_datastore_alloc(&dial_features_info, NULL);
783  if (!datastore) {
784  ast_log(LOG_WARNING, "Unable to create channel features datastore.\n");
785  return 0;
786  }
787  dialfeatures = ast_calloc(1, sizeof(*dialfeatures));
788  if (!dialfeatures) {
789  ast_log(LOG_WARNING, "Unable to allocate memory for feature flags.\n");
790  ast_datastore_free(datastore);
791  return 0;
792  }
793  ast_copy_flags(&dialfeatures->my_features, my_features, AST_FLAGS_ALL);
794  ast_copy_flags(&dialfeatures->peer_features, peer_features, AST_FLAGS_ALL);
796  datastore->data = dialfeatures;
797  ast_channel_lock(chan);
798  ast_channel_datastore_add(chan, datastore);
799  ast_channel_unlock(chan);
800  return 0;
801 }
struct ast_flags peer_features
Definition: features.c:653
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define LOG_WARNING
Definition: logger.h:144
struct ast_flags my_features
Definition: features.c:651
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
Structure for a data store object.
Definition: datastore.h:54
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
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
static struct ast_datastore_info dial_features_info
Definition: features.c:752
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
#define AST_FLAGS_ALL
Definition: utils.h:196
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:156
unsigned int inheritance
Definition: datastore.h:58
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static void add_features_datastores ( struct ast_channel caller,
struct ast_channel callee,
struct ast_bridge_config config 
)
static

Definition at line 3897 of file features.c.

References add_features_datastore(), ast_bridge_config::features_callee, and ast_bridge_config::features_caller.

Referenced by ast_bridge_call().

3898 {
3899  if (add_features_datastore(caller, &config->features_caller, &config->features_callee)) {
3900  /*
3901  * If we don't return here, then when we do a builtin_atxfer we
3902  * will copy the disconnect flags over from the atxfer to the
3903  * callee (Party C).
3904  */
3905  return;
3906  }
3907 
3908  add_features_datastore(callee, &config->features_callee, &config->features_caller);
3909 }
struct ast_flags features_callee
Definition: channel.h:976
struct ast_flags features_caller
Definition: channel.h:975
static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
Definition: features.c:768
static int adsi_announce_park ( struct ast_channel chan,
char *  parkingexten 
)
static

Announce call parking by ADSI.

Parameters
chan.
parkingexten. Create message to show for ADSI, display message.
Return values
0on success.
-1on failure.

Definition at line 1063 of file features.c.

References ADSI_JUST_CENT, ast_adsi_load_session(), ast_adsi_print(), and justify.

Referenced by park_call_full().

1064 {
1065  int res;
1066  int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
1067  char tmp[256];
1068  char *message[5] = {NULL, NULL, NULL, NULL, NULL};
1069 
1070  snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
1071  message[0] = tmp;
1072  res = ast_adsi_load_session(chan, NULL, 0, 1);
1073  if (res == -1)
1074  return res;
1075  return ast_adsi_print(chan, message, justify, 1);
1076 }
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay...
Definition: adsi.c:76
static struct adsi_event justify[]
Definition: app_adsiprog.c:105
#define ADSI_JUST_CENT
Definition: adsi.h:114
int ast_adsi_print(struct ast_channel *chan, char **lines, int *align, int voice)
Display some stuff on the screen.
Definition: adsi.c:65
int ast_bridge_call ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config 
)

bridge the call and set CDR

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
void ast_channel_log ( char *  title,
struct ast_channel chan 
)

Definition at line 3832 of file features.c.

References ast_log(), and LOG_NOTICE.

Referenced by ast_bridge_call().

3833 {
3834  ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long)chan);
3835  ast_log(LOG_NOTICE, "CHAN: name: %s; appl: %s; data: %s; contxt: %s; exten: %s; pri: %d;\n",
3836  chan->name, chan->appl, chan->data, chan->context, chan->exten, chan->priority);
3837  ast_log(LOG_NOTICE, "CHAN: acctcode: %s; dialcontext: %s; amaflags: %x; maccontxt: %s; macexten: %s; macpri: %d;\n",
3838  chan->accountcode, chan->dialcontext, (unsigned)chan->amaflags, chan->macrocontext, chan->macroexten, chan->macropriority);
3839  ast_log(LOG_NOTICE, "CHAN: masq: %p; masqr: %p; _bridge: %p; uniqueID: %s; linkedID:%s\n",
3840  chan->masq, chan->masqr,
3841  chan->_bridge, chan->uniqueid, chan->linkedid);
3842  if (chan->masqr)
3843  ast_log(LOG_NOTICE, "CHAN: masquerading as: %s; cdr: %p;\n",
3844  chan->masqr->name, chan->masqr->cdr);
3845  if (chan->_bridge)
3846  ast_log(LOG_NOTICE, "CHAN: Bridged to %s\n", chan->_bridge->name);
3847 
3848  ast_log(LOG_NOTICE, "===== done ====\n");
3849 }
struct ast_channel * masqr
Definition: channel.h:752
struct ast_channel * masq
Definition: channel.h:751
int priority
Definition: channel.h:841
const ast_string_field uniqueid
Definition: channel.h:787
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
struct ast_cdr * cdr
Definition: channel.h:766
const char * data
Definition: channel.h:755
const ast_string_field linkedid
Definition: channel.h:787
const char * appl
Definition: channel.h:754
int macropriority
Definition: channel.h:842
struct ast_channel * _bridge
Definition: channel.h:748
const ast_string_field dialcontext
Definition: channel.h:787
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
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
const ast_string_field accountcode
Definition: channel.h:787
int amaflags
Definition: channel.h:843
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
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_init ( void  )

Provided by features.c

Definition at line 8336 of file features.c.

References action_bridge(), ao2_container_alloc, ARRAY_LEN, ast_cli_register_multiple(), ast_devstate_prov_add(), ast_manager_register_xml, ast_pthread_create, ast_register_application2(), ast_register_atexit(), AST_TEST_REGISTER, bridge_exec(), do_parking_thread(), EVENT_FLAG_CALL, features_shutdown(), load_config(), manager_park(), manager_parking_status(), metermaidstate(), park_call_exec(), parkcall, parked_call_exec(), parking_thread, parkinglot_cmp_cb(), parkinglot_hash_cb(), and parkinglots.

Referenced by main().

8337 {
8338  int res;
8339 
8341  if (!parkinglots) {
8342  return -1;
8343  }
8344 
8345  res = load_config(0);
8346  if (res) {
8347  return res;
8348  }
8351  return -1;
8352  }
8353  ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
8354  res = ast_register_application2(parkedcall, parked_call_exec, NULL, NULL, NULL);
8355  if (!res)
8356  res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
8357  if (!res) {
8361  }
8362 
8363  res |= ast_devstate_prov_add("Park", metermaidstate);
8364 #if defined(TEST_FRAMEWORK)
8365  res |= AST_TEST_REGISTER(features_test);
8366 #endif /* defined(TEST_FRAMEWORK) */
8367 
8369 
8370  return res;
8371 }
static void * do_parking_thread(void *ignore)
Take care of parked calls and unpark them if needed.
Definition: features.c:4984
static int parkinglot_hash_cb(const void *obj, const int flags)
Definition: features.c:862
static const char * parkedcall
Definition: features.c:419
static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
Definition: features.c:869
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int bridge_exec(struct ast_channel *chan, const char *data)
Bridge channels.
Definition: features.c:7650
static void features_shutdown(void)
Definition: features.c:8314
static struct ast_cli_entry cli_features[]
Definition: features.c:7165
static int park_call_exec(struct ast_channel *chan, const char *data)
Park a call.
Definition: features.c:5063
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:371
static enum ast_device_state metermaidstate(const char *data)
metermaids callback from devicestate.c
Definition: features.c:1105
static int parked_call_exec(struct ast_channel *chan, const char *data)
Pickup parked call.
Definition: features.c:5173
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:172
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:998
static pthread_t parking_thread
Definition: features.c:648
static char * app_bridge
Definition: features.c:7493
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:418
static int action_bridge(struct mansession *s, const struct message *m)
Bridge channels together.
Definition: features.c:6975
static int manager_park(struct mansession *s, const struct message *m)
Create manager event for parked calls.
Definition: features.c:7245
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static int load_config(int reload)
Definition: features.c:6717
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx.c:6344
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
static int manager_parking_status(struct mansession *s, const struct message *m)
Dump parking lot status.
Definition: features.c:7179
static const char * parkcall
Definition: features.c:637
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
const ast_string_field name
Definition: channel.h:787
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_list

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
static void ast_unregister_features ( void  )
static

Remove all features in the list.

Definition at line 3088 of file features.c.

References ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, feature_group_exten::feature, and ast_call_feature::feature_entry.

Referenced by process_config().

3089 {
3090  struct ast_call_feature *feature;
3091 
3093  while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
3094  ast_free(feature);
3095  }
3097 }
#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_HEAD
Definition: linkedlists.h:829
struct ast_call_feature::@170 feature_entry
static void ast_unregister_groups ( void  )
static

Remove all feature groups in the list.

Definition at line 3114 of file features.c.

References ast_free, AST_LIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, and feature_group::features.

Referenced by process_config().

3115 {
3116  struct feature_group *fg;
3117  struct feature_group_exten *fge;
3118 
3120  while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
3121  while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
3123  ast_free(fge);
3124  }
3125 
3127  ast_free(fg);
3128  }
3130 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
struct feature_group::@266 features
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
struct feature_group_exten::@264 entry
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
static void atxfer_fail_cleanup ( struct ast_channel transferee,
struct ast_channel transferer,
struct ast_party_connected_line connected_line 
)
static

Definition at line 2490 of file features.c.

References ast_channel_connected_line_macro(), ast_channel_update_connected_line(), ast_party_connected_line_free(), and finishup().

Referenced by builtin_atxfer().

2491 {
2492  finishup(transferee);
2493 
2494  /*
2495  * Restore party B connected line info about party A.
2496  *
2497  * Party B was the caller to party C and is the last known mode
2498  * for party B.
2499  */
2500  if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
2501  ast_channel_update_connected_line(transferer, connected_line, NULL);
2502  }
2503  ast_party_connected_line_free(connected_line);
2504 }
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
static int finishup(struct ast_channel *chan)
Definition: features.c:1870
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
static void* bridge_call_thread ( void *  data)
static

bridge the call

Parameters
datathread bridge.

Set Last Data for respective channels, reset cdr for channels bridge call, check if we're going back to dialplan if not hangup both legs of the call

Definition at line 987 of file features.c.

References ast_channel::appl, ast_bridge_call(), ast_check_hangup(), ast_free, ast_hangup(), ast_log(), ast_pbx_start(), ast_bridge_thread_obj::bconfig, ast_bridge_thread_obj::chan, ast_channel::data, LOG_VERBOSE, LOG_WARNING, ast_channel::name, ast_bridge_thread_obj::peer, ast_bridge_thread_obj::return_to_pbx, and set_chan_app_data().

Referenced by bridge_call_thread_launch().

988 {
989  struct ast_bridge_thread_obj *tobj = data;
990 
991  tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
992  if (set_chan_app_data(tobj->chan, tobj->peer->name)) {
993  tobj->chan->data = "(Empty)";
994  }
995  tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
996  if (set_chan_app_data(tobj->peer, tobj->chan->name)) {
997  tobj->peer->data = "(Empty)";
998  }
999 
1000  ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
1001 
1002  if (tobj->return_to_pbx) {
1003  if (!ast_check_hangup(tobj->peer)) {
1004  ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
1005  if (ast_pbx_start(tobj->peer)) {
1006  ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
1007  ast_hangup(tobj->peer);
1008  }
1009  } else {
1010  ast_hangup(tobj->peer);
1011  }
1012  if (!ast_check_hangup(tobj->chan)) {
1013  ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
1014  if (ast_pbx_start(tobj->chan)) {
1015  ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
1016  ast_hangup(tobj->chan);
1017  }
1018  } else {
1019  ast_hangup(tobj->chan);
1020  }
1021  } else {
1022  ast_hangup(tobj->chan);
1023  ast_hangup(tobj->peer);
1024  }
1025 
1026  ast_free(tobj);
1027 
1028  return NULL;
1029 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
struct ast_channel * peer
Definition: features.c:858
struct ast_channel * chan
Definition: features.c:857
#define LOG_WARNING
Definition: logger.h:144
static int set_chan_app_data(struct ast_channel *chan, const char *src_app_data)
Definition: features.c:957
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
Definition: features.c:3960
const char * data
Definition: channel.h:755
const char * appl
Definition: channel.h:754
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
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 ast_free(a)
Definition: astmm.h:97
#define LOG_VERBOSE
Definition: logger.h:166
struct ast_bridge_config bconfig
Definition: features.c:856
unsigned int return_to_pbx
Definition: features.c:859
static void bridge_call_thread_launch ( struct ast_bridge_thread_obj data)
static

create thread for the parked call

Parameters
dataCreate thread and attributes, call bridge_call_thread

Definition at line 1037 of file features.c.

References ast_hangup(), ast_log(), ast_pthread_create, bridge_call_thread(), ast_bridge_thread_obj::chan, LOG_ERROR, ast_bridge_thread_obj::peer, and thread.

Referenced by action_bridge(), and builtin_atxfer().

1038 {
1039  pthread_t thread;
1040  pthread_attr_t attr;
1041  struct sched_param sched;
1042 
1043  pthread_attr_init(&attr);
1044  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1045  if (ast_pthread_create(&thread, &attr, bridge_call_thread, data)) {
1046  ast_hangup(data->chan);
1047  ast_hangup(data->peer);
1048  ast_log(LOG_ERROR, "Failed to create bridge_call_thread.\n");
1049  }
1050  pthread_attr_destroy(&attr);
1051  memset(&sched, 0, sizeof(sched));
1052  pthread_setschedparam(thread, SCHED_RR, &sched);
1053 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
pthread_t thread
Definition: app_meetme.c:962
struct ast_channel * peer
Definition: features.c:858
struct ast_channel * chan
Definition: features.c:857
Definition: sched.c:57
#define LOG_ERROR
Definition: logger.h:155
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
static void * bridge_call_thread(void *data)
bridge the call
Definition: features.c:987
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:418
static int bridge_exec ( struct ast_channel chan,
const char *  data 
)
static

Bridge channels.

Parameters
chan
datachannel to bridge with.

Split data, check we aren't bridging with ourself, check valid channel, answer call if not already, check compatible channels, setup bridge config now bridge call, if transferred party hangs up return to PBX extension.

Definition at line 7650 of file features.c.

References ast_channel::_state, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_bridge_call(), ast_bridge_timelimit(), ast_channel_alloc(), ast_channel_get_by_name_prefix(), ast_channel_make_compatible(), ast_channel_unref, ast_check_hangup(), ast_debug, AST_DECLARE_APP_ARGS, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, AST_FLAG_BRIDGE_HANGUP_DONT, ast_free, ast_hangup(), ast_log(), ast_manager_event, ast_manager_event_multichan, ast_pbx_start(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_DOWN, AST_STATE_UP, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), bridge_exec_options, BRIDGE_OPT_PLAYTONE, ast_channel::context, do_bridge_masquerade(), ast_bridge_config::end_sound, EVENT_FLAG_CALL, ast_channel::exten, ast_bridge_config::features_callee, ast_bridge_config::features_caller, ast_channel::language, ast_channel::linkedid, LOG_WARNING, ast_channel::name, OPT_ARG_ARRAY_SIZE, OPT_ARG_DURATION_LIMIT, OPT_CALLEE_HANGUP, OPT_CALLEE_KILL, OPT_CALLEE_MONITOR, OPT_CALLEE_PARK, OPT_CALLEE_TRANSFER, OPT_CALLER_HANGUP, OPT_CALLER_MONITOR, OPT_CALLER_PARK, OPT_CALLER_TRANSFER, OPT_DURATION_LIMIT, pbx_builtin_setvar_helper(), ast_channel::priority, ast_bridge_config::start_sound, ast_bridge_config::warning_sound, and xfersound.

Referenced by ast_features_init().

7651 {
7652  struct ast_channel *current_dest_chan, *final_dest_chan, *chans[2];
7653  char *tmp_data = NULL;
7654  struct ast_flags opts = { 0, };
7655  struct ast_bridge_config bconfig = { { 0, }, };
7656  char *opt_args[OPT_ARG_ARRAY_SIZE];
7657  struct timeval calldurationlimit = { 0, };
7658 
7660  AST_APP_ARG(dest_chan);
7661  AST_APP_ARG(options);
7662  );
7663 
7664  if (ast_strlen_zero(data)) {
7665  ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
7666  return -1;
7667  }
7668 
7669  tmp_data = ast_strdupa(data);
7670  AST_STANDARD_APP_ARGS(args, tmp_data);
7671  if (!ast_strlen_zero(args.options))
7672  ast_app_parse_options(bridge_exec_options, &opts, opt_args, args.options);
7673 
7674  /* avoid bridge with ourselves */
7675  if (!strcmp(chan->name, args.dest_chan)) {
7676  ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
7677  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7678  "Response: Failed\r\n"
7679  "Reason: Unable to bridge channel to itself\r\n"
7680  "Channel1: %s\r\n"
7681  "Channel2: %s\r\n",
7682  chan->name, args.dest_chan);
7683  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
7684  return 0;
7685  }
7686 
7687  /* make sure we have a valid end point */
7688  if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
7689  strlen(args.dest_chan)))) {
7690  ast_log(LOG_WARNING, "Bridge failed because channel %s does not exist\n",
7691  args.dest_chan);
7692  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7693  "Response: Failed\r\n"
7694  "Reason: Channel2 does not exist\r\n"
7695  "Channel1: %s\r\n"
7696  "Channel2: %s\r\n", chan->name, args.dest_chan);
7697  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
7698  return 0;
7699  }
7700 
7701  /* try to allocate a place holder where current_dest_chan will be placed */
7702  if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
7703  NULL, NULL, current_dest_chan->linkedid, 0, "Bridge/%s", current_dest_chan->name))) {
7704  ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
7705  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7706  "Response: Failed\r\n"
7707  "Reason: Cannot create placeholder channel\r\n"
7708  "Channel1: %s\r\n"
7709  "Channel2: %s\r\n", chan->name, args.dest_chan);
7710  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
7711  ast_channel_unref(current_dest_chan);
7712  return 0;
7713  }
7714 
7715  if (ast_test_flag(&opts, OPT_DURATION_LIMIT)
7717  && ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) {
7718  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7719  "Response: Failed\r\n"
7720  "Reason: Cannot setup bridge time limit\r\n"
7721  "Channel1: %s\r\n"
7722  "Channel2: %s\r\n", chan->name, args.dest_chan);
7723  ast_hangup(final_dest_chan);
7724  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
7725  current_dest_chan = ast_channel_unref(current_dest_chan);
7726  goto done;
7727  }
7728 
7729  if (do_bridge_masquerade(current_dest_chan, final_dest_chan)) {
7730  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7731  "Response: Failed\r\n"
7732  "Reason: Cannot masquerade channels\r\n"
7733  "Channel1: %s\r\n"
7734  "Channel2: %s\r\n", chan->name, args.dest_chan);
7735  ast_hangup(final_dest_chan);
7736  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
7737  current_dest_chan = ast_channel_unref(current_dest_chan);
7738  goto done;
7739  }
7740 
7741  /* answer the channel if needed */
7742  if (final_dest_chan->_state != AST_STATE_UP) {
7743  ast_answer(final_dest_chan);
7744  }
7745 
7746  chans[0] = current_dest_chan;
7747  chans[1] = final_dest_chan;
7748 
7749  /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
7750  /* try to make compatible, send error if we fail */
7751  if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
7752  ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
7753  ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
7754  "Response: Failed\r\n"
7755  "Reason: Could not make channels compatible for bridge\r\n"
7756  "Channel1: %s\r\n"
7757  "Channel2: %s\r\n", chan->name, final_dest_chan->name);
7758 
7759  /* Maybe we should return this channel to the PBX? */
7760  ast_hangup(final_dest_chan);
7761 
7762  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
7763  current_dest_chan = ast_channel_unref(current_dest_chan);
7764  goto done;
7765  }
7766 
7767  /* Report that the bridge will be successfull */
7768  ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
7769  "Response: Success\r\n"
7770  "Channel1: %s\r\n"
7771  "Channel2: %s\r\n", chan->name, final_dest_chan->name);
7772 
7773  current_dest_chan = ast_channel_unref(current_dest_chan);
7774 
7775  /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */
7777  if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
7778  if (ast_waitstream(final_dest_chan, "") < 0)
7779  ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
7780  }
7781  }
7782 
7783  if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER))
7785  if (ast_test_flag(&opts, OPT_CALLER_TRANSFER))
7787  if (ast_test_flag(&opts, OPT_CALLEE_HANGUP))
7789  if (ast_test_flag(&opts, OPT_CALLER_HANGUP))
7791  if (ast_test_flag(&opts, OPT_CALLEE_MONITOR))
7793  if (ast_test_flag(&opts, OPT_CALLER_MONITOR))
7795  if (ast_test_flag(&opts, OPT_CALLEE_PARK))
7797  if (ast_test_flag(&opts, OPT_CALLER_PARK))
7799 
7800  /*
7801  * Don't let the after-bridge code run the h-exten. We want to
7802  * continue in the dialplan.
7803  */
7805  ast_bridge_call(chan, final_dest_chan, &bconfig);
7806 
7807  /* The bridge has ended, set BRIDGERESULT to SUCCESS. */
7808  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
7809 
7810  /* If the other channel has not been hung up, return it to the PBX */
7811  if (!ast_check_hangup(final_dest_chan)) {
7812  if (!ast_test_flag(&opts, OPT_CALLEE_KILL)) {
7813  ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
7814  final_dest_chan->context, final_dest_chan->exten,
7815  final_dest_chan->priority, final_dest_chan->name);
7816 
7817  if (ast_pbx_start(final_dest_chan)) {
7818  ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
7819  ast_hangup(final_dest_chan);
7820  } else {
7821  ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
7822  }
7823  } else {
7824  ast_hangup(final_dest_chan);
7825  }
7826  } else {
7827  ast_debug(1, "chan %s was hungup\n", final_dest_chan->name);
7828  ast_hangup(final_dest_chan);
7829  }
7830 done:
7831  ast_free((char *) bconfig.warning_sound);
7832  ast_free((char *) bconfig.end_sound);
7833  ast_free((char *) bconfig.start_sound);
7834 
7835  return 0;
7836 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
Main Channel structure associated with a channel.
Definition: channel.h:742
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
int priority
Definition: channel.h:841
struct ast_flags features_callee
Definition: channel.h:976
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define ast_test_flag(p, flag)
Definition: utils.h:63
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define EVENT_FLAG_CALL
Definition: manager.h:72
static struct ast_app_option bridge_exec_options[128]
Definition: features.c:7530
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
Definition: features.c:3960
const ast_string_field linkedid
Definition: channel.h:787
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1808
const char * start_sound
Definition: channel.h:986
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
Actual bridge.
Definition: features.c:6933
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
bridge configuration
Definition: channel.h:974
const char * end_sound
Definition: channel.h:985
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
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
static struct @350 args
enum ast_channel_state _state
Definition: channel.h:839
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 ast_free(a)
Definition: astmm.h:97
static char xfersound[256]
Definition: features.c:590
Structure used to handle boolean flags.
Definition: utils.h:200
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
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
Definition: channel.c:5970
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
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
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
const char * warning_sound
Definition: channel.h:984
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
const ast_string_field language
Definition: channel.h:787
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
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
Definition: features.c:7532
static struct parking_dp_context* build_dialplan_useage_context ( struct ast_parkinglot lot)
static

Definition at line 6324 of file features.c.

References ast_calloc, ast_parkinglot::cfg, parking_dp_context::context, destroy_dialplan_usage_context(), dialplan_usage_add_parkinglot_data(), and parkinglot_cfg::parking_con.

Referenced by dialplan_usage_add_parkinglot().

6325 {
6326  struct parking_dp_context *ctx_node;
6327 
6328  ctx_node = ast_calloc(1, sizeof(*ctx_node) + strlen(lot->cfg.parking_con));
6329  if (!ctx_node) {
6330  return NULL;
6331  }
6332  if (dialplan_usage_add_parkinglot_data(ctx_node, lot, 0)) {
6334  return NULL;
6335  }
6336  strcpy(ctx_node->context, lot->cfg.parking_con);
6337  return ctx_node;
6338 }
static void destroy_dialplan_usage_context(struct parking_dp_context *doomed)
Definition: features.c:6043
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
struct parkinglot_cfg cfg
Definition: features.c:560
#define ast_calloc(a, b)
Definition: astmm.h:82
static int dialplan_usage_add_parkinglot_data(struct parking_dp_context *ctx_node, struct ast_parkinglot *lot, int complain)
Definition: features.c:6297
static int build_dialplan_useage_map ( struct parking_dp_map usage_map,
int  complain 
)
static

Definition at line 6396 of file features.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, dialplan_usage_add_parkinglot(), parkinglots, and status.

Referenced by load_config().

6397 {
6398  int status = 0;
6399  struct ao2_iterator iter;
6400  struct ast_parkinglot *curlot;
6401 
6402  /* For all parking lots */
6403  iter = ao2_iterator_init(parkinglots, 0);
6404  for (; (curlot = ao2_iterator_next(&iter)); ao2_ref(curlot, -1)) {
6405  /* Add the parking lot to the map. */
6406  if (dialplan_usage_add_parkinglot(usage_map, curlot, complain)) {
6407  ao2_ref(curlot, -1);
6408  status = -1;
6409  break;
6410  }
6411  }
6412  ao2_iterator_destroy(&iter);
6413 
6414  return status;
6415 }
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
#define ao2_ref(o, delta)
Definition: astobj2.h:472
Structure for parking lots which are put in a container.
Definition: features.c:556
static int dialplan_usage_add_parkinglot(struct parking_dp_map *usage_map, struct ast_parkinglot *lot, int complain)
Definition: features.c:6351
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
jack_status_t status
Definition: app_jack.c:143
static struct parking_dp_ramp* build_dialplan_useage_ramp ( const char *  exten,
int  exclusive 
)
static

Definition at line 6087 of file features.c.

References ast_calloc, parking_dp_ramp::exclusive, and parking_dp_ramp::exten.

Referenced by usage_context_add_ramp().

6088 {
6089  struct parking_dp_ramp *ramp_node;
6090 
6091  ramp_node = ast_calloc(1, sizeof(*ramp_node) + strlen(exten));
6092  if (!ramp_node) {
6093  return NULL;
6094  }
6095  ramp_node->exclusive = exclusive;
6096  strcpy(ramp_node->exten, exten);
6097  return ramp_node;
6098 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
#define ast_calloc(a, b)
Definition: astmm.h:82
unsigned int exclusive
Definition: features.c:428
char exten[1]
Definition: features.c:430
static struct parking_dp_spaces* build_dialplan_useage_spaces ( int  start,
int  stop 
)
static

Definition at line 6168 of file features.c.

References ast_calloc, parking_dp_spaces::start, parking_dp_spaces::stop, and stop.

Referenced by usage_context_add_spaces().

6169 {
6170  struct parking_dp_spaces *spaces_node;
6171 
6172  spaces_node = ast_calloc(1, sizeof(*spaces_node));
6173  if (!spaces_node) {
6174  return NULL;
6175  }
6176  spaces_node->start = start;
6177  spaces_node->stop = stop;
6178  return spaces_node;
6179 }
unsigned int stop
Definition: app_meetme.c:969
#define ast_calloc(a, b)
Definition: astmm.h:82
static struct ast_parkinglot* build_parkinglot ( const char *  pl_name,
struct ast_variable var 
)
static

Build parkinglot from configuration and chain it in if it doesn't already exist.

Definition at line 5689 of file features.c.

References ao2_link, ao2_lock, ao2_unlock, ast_debug, AST_LIST_EMPTY, ast_log(), ast_parkinglot::cfg, create_parkinglot(), DEFAULT_PARKINGLOT, find_parkinglot(), force_reload_load, LOG_WARNING, ast_parkinglot::name, parkinglot, parkinglot_cfg_default, parkinglot_cfg_default_default, parkinglot_config_read(), parkinglot_unref(), parkinglots, ast_parkinglot::parkings, and ast_parkinglot::the_mark.

Referenced by load_config(), and process_config().

5690 {
5691  struct ast_parkinglot *parkinglot;
5692  const struct parkinglot_cfg *cfg_defaults;
5693  struct parkinglot_cfg new_cfg;
5694  int cfg_error;
5695  int oldparkinglot = 0;
5696 
5697  parkinglot = find_parkinglot(pl_name);
5698  if (parkinglot) {
5699  oldparkinglot = 1;
5700  } else {
5701  parkinglot = create_parkinglot(pl_name);
5702  if (!parkinglot) {
5703  return NULL;
5704  }
5705  }
5706  if (!strcmp(parkinglot->name, DEFAULT_PARKINGLOT)) {
5707  cfg_defaults = &parkinglot_cfg_default_default;
5708  } else {
5709  cfg_defaults = &parkinglot_cfg_default;
5710  }
5711  new_cfg = *cfg_defaults;
5712 
5713  ast_debug(1, "Building parking lot %s\n", parkinglot->name);
5714 
5715  ao2_lock(parkinglot);
5716 
5717  /* Do some config stuff */
5718  cfg_error = parkinglot_config_read(parkinglot->name, &new_cfg, var);
5719  if (oldparkinglot) {
5720  if (cfg_error) {
5721  /* Bad configuration read. Keep using the original config. */
5722  ast_log(LOG_WARNING, "Changes to parking lot %s are discarded.\n",
5723  parkinglot->name);
5724  cfg_error = 0;
5725  } else if (!AST_LIST_EMPTY(&parkinglot->parkings)
5726  && memcmp(&new_cfg, &parkinglot->cfg, sizeof(parkinglot->cfg))) {
5727  /* Try reloading later when parking lot is empty. */
5729  "Parking lot %s has parked calls. Parking lot changes discarded.\n",
5730  parkinglot->name);
5731  force_reload_load = 1;
5732  } else {
5733  /* Accept the new config */
5734  parkinglot->cfg = new_cfg;
5735  }
5736  } else {
5737  /* Load the initial parking lot config. */
5738  parkinglot->cfg = new_cfg;
5739  }
5740  parkinglot->the_mark = 0;
5741 
5742  ao2_unlock(parkinglot);
5743 
5744  if (cfg_error) {
5745  /* Only new parking lots could have config errors here. */
5746  ast_log(LOG_WARNING, "New parking lot %s is discarded.\n", parkinglot->name);
5747  parkinglot_unref(parkinglot);
5748  return NULL;
5749  }
5750 
5751  /* Move it into the list, if it wasn't already there */
5752  if (!oldparkinglot) {
5753  ao2_link(parkinglots, parkinglot);
5754  }
5755  parkinglot_unref(parkinglot);
5756 
5757  return parkinglot;
5758 }
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
static struct parkinglot_cfg parkinglot_cfg_default
Definition: features.c:5508
#define LOG_WARNING
Definition: logger.h:144
unsigned int the_mark
Definition: features.c:566
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define ao2_unlock(a)
Definition: astobj2.h:497
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct parkinglot_cfg parkinglot_cfg_default_default
Definition: features.c:5498
#define ao2_lock(a)
Definition: astobj2.h:488
static int force_reload_load
Definition: features.c:585
Structure for parking lots which are put in a container.
Definition: features.c:556
struct parkinglot_cfg cfg
Definition: features.c:560
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
static struct ast_parkinglot * create_parkinglot(const char *name)
Allocate parking lot structure.
Definition: features.c:5459
struct ast_parkinglot::parkinglot_parklist parkings
static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cfg, struct ast_variable *var)
Definition: features.c:5546
#define DEFAULT_PARKINGLOT
Definition: features.h:37
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
Definition: features.c:5017
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
static int builtin_atxfer ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
const char *  code,
int  sense,
void *  data 
)
static

Attended transfer.

Parameters
chantransferred user
peerperson transfering call
config
code
sensefeature options
dataGet extension to transfer to, if you cannot generate channel (or find extension) return to host channel. After called channel answered wait for hangup of transferer, bridge call between transfer peer (taking them off hold) to attended transfer channel.
Returns
-1 on failure

Definition at line 2521 of file features.c.

References ast_channel::_state, add_features_datastore(), ast_app_dtget(), ast_autoservice_start(), ast_autoservice_stop(), ast_best_codec(), ast_bridge_call(), ast_calloc, AST_CEL_ATTENDEDTRANSFER, ast_cel_report_event(), ast_channel_alloc(), ast_channel_connected_line_macro(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_channel_update_connected_line(), ast_check_hangup(), ast_clear_flag, ast_connected_line_copy_from_caller(), AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_flags, ast_debug, AST_DIGIT_ANY, ast_do_masquerade(), ast_explicit_goto(), AST_FEATURE_DISCONNECT, AST_FEATURE_RETURN_SUCCESS, AST_FLAG_BRIDGE_HANGUP_DONT, AST_FLAGS_ALL, ast_hangup(), ast_indicate(), ast_log(), ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_safe_sleep(), ast_set_flag, AST_STATE_DOWN, AST_STATE_UP, ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), atxfer_fail_cleanup(), atxfercallbackretries, atxferdropcall, atxferloopdelay, atxfernoanswertimeout, ast_bridge_thread_obj::bconfig, bridge_call_thread_launch(), ast_channel::caller, ast_bridge_thread_obj::chan, check_compat(), config, ast_channel::connected, ast_datastore::data, dial_features_info, ast_bridge_config::end_bridge_callback_data_fixup, feature_request_and_dial(), ast_bridge_config::features_callee, ast_bridge_config::features_caller, finishup(), get_parking_exten(), ast_channel::language, ast_channel::linkedid, LOG_WARNING, ast_dial_features::my_features, ast_channel::name, ast_channel::nativeformats, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), ast_bridge_thread_obj::peer, ast_dial_features::peer_features, ast_channel::readformat, real_ctx(), set_peers(), ast_party_connected_line::source, strsep(), transferdigittimeout, ast_channel::visible_indication, ast_channel::writeformat, xfer_park_call_helper(), xferfailsound, and xfersound.

2522 {
2523  struct ast_channel *transferer;/* Party B */
2524  struct ast_channel *transferee;/* Party A */
2525  struct ast_exten *park_exten;
2526  const char *chan1_attended_sound;
2527  const char *chan2_attended_sound;
2528  const char *transferer_real_context;
2529  char xferto[256] = "";
2530  int res;
2531  int outstate=0;
2532  struct ast_channel *newchan;
2533  struct ast_channel *xferchan;
2534  struct ast_bridge_thread_obj *tobj;
2535  struct ast_bridge_config bconfig;
2536  int l;
2537  struct ast_party_connected_line connected_line;
2538  struct ast_datastore *features_datastore;
2539  struct ast_dial_features *dialfeatures;
2540  char *transferer_tech;
2541  char *transferer_name;
2542  char *transferer_name_orig;
2543  char *dash;
2544 
2545  ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2546  set_peers(&transferer, &transferee, peer, chan, sense);
2547  transferer_real_context = real_ctx(transferer, transferee);
2548 
2549  /* Start autoservice on transferee while we talk to the transferer */
2550  ast_autoservice_start(transferee);
2551  ast_indicate(transferee, AST_CONTROL_HOLD);
2552 
2553  /* Transfer */
2554  res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2555  if (res < 0) {
2556  finishup(transferee);
2557  return -1;
2558  }
2559  if (res > 0) { /* If they've typed a digit already, handle it */
2560  xferto[0] = (char) res;
2561  }
2562 
2563  /* this is specific of atxfer */
2564  res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2565  if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
2566  finishup(transferee);
2567  return -1;
2568  }
2569  l = strlen(xferto);
2570  if (res == 0) {
2571  if (l) {
2572  ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2573  xferto, transferer_real_context);
2574  } else {
2575  /* Does anyone care about this case? */
2576  ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
2577  }
2578  ast_stream_and_wait(transferer, "pbx-invalid", "");
2579  finishup(transferee);
2581  }
2582 
2583  park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
2584  if (park_exten) {
2585  /* We are transfering the transferee to a parking lot. */
2586  return xfer_park_call_helper(transferee, transferer, park_exten);
2587  }
2588 
2589  /*
2590  * Append context to dialed transfer number.
2591  *
2592  * NOTE: The local channel needs the /n flag so party C will use
2593  * the feature flags set by the dialplan when calling that
2594  * party.
2595  */
2596  snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
2597 
2598  /* If we are performing an attended transfer and we have two channels involved then
2599  copy sound file information to play upon attended transfer completion */
2600  chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2601  chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2602  if (!ast_strlen_zero(chan1_attended_sound)) {
2603  pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
2604  }
2605  if (!ast_strlen_zero(chan2_attended_sound)) {
2606  pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
2607  }
2608 
2609  /* Extract redial transferer information from the channel name. */
2610  transferer_name_orig = ast_strdupa(transferer->name);
2611  transferer_name = ast_strdupa(transferer_name_orig);
2612  transferer_tech = strsep(&transferer_name, "/");
2613  dash = strrchr(transferer_name, '-');
2614  if (dash) {
2615  /* Trim off channel name sequence/serial number. */
2616  *dash = '\0';
2617  }
2618 
2619  /* Stop autoservice so we can monitor all parties involved in the transfer. */
2620  if (ast_autoservice_stop(transferee) < 0) {
2621  ast_indicate(transferee, AST_CONTROL_UNHOLD);
2622  return -1;
2623  }
2624 
2625  /* Save connected line info for party B about party A in case transfer fails. */
2626  ast_party_connected_line_init(&connected_line);
2627  ast_channel_lock(transferer);
2628  ast_party_connected_line_copy(&connected_line, &transferer->connected);
2629  ast_channel_unlock(transferer);
2630  connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2631 
2632  /* Dial party C */
2633  newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
2634  transferee, "Local", ast_best_codec(transferer->nativeformats), xferto,
2635  atxfernoanswertimeout, &outstate, transferer->language);
2636  ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
2637 
2638  if (!ast_check_hangup(transferer)) {
2639  int hangup_dont = 0;
2640 
2641  /* Transferer (party B) is up */
2642  ast_debug(1, "Actually doing an attended transfer.\n");
2643 
2644  /* Start autoservice on transferee while the transferer deals with party C. */
2645  ast_autoservice_start(transferee);
2646 
2647  ast_indicate(transferer, -1);
2648  if (!newchan) {
2649  /* any reason besides user requested cancel and busy triggers the failed sound */
2650  switch (outstate) {
2651  case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
2652  case AST_CONTROL_BUSY:
2654  if (ast_stream_and_wait(transferer, xfersound, "")) {
2655  ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2656  }
2657  break;
2658  default:
2659  if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2660  ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2661  }
2662  break;
2663  }
2664  atxfer_fail_cleanup(transferee, transferer, &connected_line);
2666  }
2667 
2668  if (check_compat(transferer, newchan)) {
2669  if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2670  ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2671  }
2672  atxfer_fail_cleanup(transferee, transferer, &connected_line);
2674  }
2675  memset(&bconfig,0,sizeof(struct ast_bridge_config));
2676  ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
2677  ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
2678 
2679  /*
2680  * ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we
2681  * don't want that to happen here because the transferer is in
2682  * another bridge already.
2683  */
2684  if (ast_test_flag(transferer, AST_FLAG_BRIDGE_HANGUP_DONT)) {
2685  hangup_dont = 1;
2686  }
2687 
2688  /*
2689  * Don't let the after-bridge code run the h-exten. It is the
2690  * wrong bridge to run the h-exten after.
2691  */
2693 
2694  /*
2695  * Let party B and C talk as long as they want while party A
2696  * languishes in autoservice listening to MOH.
2697  */
2698  ast_bridge_call(transferer, newchan, &bconfig);
2699 
2700  if (hangup_dont) {
2701  /* Restore the AST_FLAG_BRIDGE_HANGUP_DONT flag */
2703  }
2704 
2705  if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
2706  ast_hangup(newchan);
2707  if (ast_stream_and_wait(transferer, xfersound, "")) {
2708  ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2709  }
2710  atxfer_fail_cleanup(transferee, transferer, &connected_line);
2712  }
2713 
2714  /* Transferer (party B) is confirmed hung up at this point. */
2715  if (check_compat(transferee, newchan)) {
2716  finishup(transferee);
2717  ast_party_connected_line_free(&connected_line);
2718  return -1;
2719  }
2720 
2721  ast_indicate(transferee, AST_CONTROL_UNHOLD);
2722  if ((ast_autoservice_stop(transferee) < 0)
2723  || (ast_waitfordigit(transferee, 100) < 0)
2724  || (ast_waitfordigit(newchan, 100) < 0)
2725  || ast_check_hangup(transferee)
2726  || ast_check_hangup(newchan)) {
2727  ast_hangup(newchan);
2728  ast_party_connected_line_free(&connected_line);
2729  return -1;
2730  }
2731  } else if (!ast_check_hangup(transferee)) {
2732  /* Transferer (party B) has hung up at this point. Doing blonde transfer. */
2733  ast_debug(1, "Actually doing a blonde transfer.\n");
2734 
2735  if (!newchan && !atxferdropcall) {
2736  /* Party C is not available, try to call party B back. */
2737  unsigned int tries = 0;
2738 
2739  if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
2741  "Transferer channel name: '%s' cannot be used for callback.\n",
2742  transferer_name_orig);
2743  ast_indicate(transferee, AST_CONTROL_UNHOLD);
2744  ast_party_connected_line_free(&connected_line);
2745  return -1;
2746  }
2747 
2748  tries = 0;
2749  for (;;) {
2750  /* Try to get party B back. */
2751  ast_debug(1, "We're trying to callback %s/%s\n",
2752  transferer_tech, transferer_name);
2753  newchan = feature_request_and_dial(transferer, transferer_name_orig,
2754  transferee, transferee, transferer_tech,
2755  ast_best_codec(transferee->nativeformats), transferer_name,
2756  atxfernoanswertimeout, &outstate, transferer->language);
2757  ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
2758  !!newchan, outstate);
2759  if (newchan) {
2760  /*
2761  * We have recalled party B (newchan). We need to give this
2762  * call leg the same feature flags as the original party B call
2763  * leg.
2764  */
2765  ast_channel_lock(transferer);
2766  features_datastore = ast_channel_datastore_find(transferer,
2767  &dial_features_info, NULL);
2768  if (features_datastore && (dialfeatures = features_datastore->data)) {
2769  struct ast_flags my_features = { 0 };
2770  struct ast_flags peer_features = { 0 };
2771 
2772  ast_copy_flags(&my_features, &dialfeatures->my_features,
2773  AST_FLAGS_ALL);
2774  ast_copy_flags(&peer_features, &dialfeatures->peer_features,
2775  AST_FLAGS_ALL);
2776  ast_channel_unlock(transferer);
2777  add_features_datastore(newchan, &my_features, &peer_features);
2778  } else {
2779  ast_channel_unlock(transferer);
2780  }
2781  break;
2782  }
2783  if (ast_check_hangup(transferee)) {
2784  break;
2785  }
2786 
2787  ++tries;
2788  if (atxfercallbackretries <= tries) {
2789  /* No more callback tries remaining. */
2790  break;
2791  }
2792 
2793  if (atxferloopdelay) {
2794  /* Transfer failed, sleeping */
2795  ast_debug(1, "Sleeping for %u ms before retrying atxfer.\n",
2796  atxferloopdelay);
2797  ast_safe_sleep(transferee, atxferloopdelay);
2798  if (ast_check_hangup(transferee)) {
2799  ast_party_connected_line_free(&connected_line);
2800  return -1;
2801  }
2802  }
2803 
2804  /* Retry dialing party C. */
2805  ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
2806  newchan = feature_request_and_dial(transferer, transferer_name_orig,
2807  transferer, transferee, "Local",
2808  ast_best_codec(transferee->nativeformats), xferto,
2809  atxfernoanswertimeout, &outstate, transferer->language);
2810  ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
2811  !!newchan, outstate);
2812  if (newchan || ast_check_hangup(transferee)) {
2813  break;
2814  }
2815  }
2816  }
2817  ast_indicate(transferee, AST_CONTROL_UNHOLD);
2818  if (!newchan) {
2819  /* No party C or could not callback party B. */
2820  ast_party_connected_line_free(&connected_line);
2821  return -1;
2822  }
2823 
2824  /* newchan is up, we should prepare transferee and bridge them */
2825  if (ast_check_hangup(newchan)) {
2826  ast_hangup(newchan);
2827  ast_party_connected_line_free(&connected_line);
2828  return -1;
2829  }
2830  if (check_compat(transferee, newchan)) {
2831  ast_party_connected_line_free(&connected_line);
2832  return -1;
2833  }
2834  } else {
2835  /*
2836  * Both the transferer and transferee have hungup. If newchan
2837  * is up, hang it up as it has no one to talk to.
2838  */
2839  ast_debug(1, "Everyone is hungup.\n");
2840  if (newchan) {
2841  ast_hangup(newchan);
2842  }
2843  ast_party_connected_line_free(&connected_line);
2844  return -1;
2845  }
2846 
2847  /* Initiate the channel transfer of party A to party C (or recalled party B). */
2848  ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
2849 
2850  xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", transferee->linkedid, 0, "Transfered/%s", transferee->name);
2851  if (!xferchan) {
2852  ast_hangup(newchan);
2853  ast_party_connected_line_free(&connected_line);
2854  return -1;
2855  }
2856 
2857  /* Give party A a momentary ringback tone during transfer. */
2859 
2860  /* Make formats okay */
2861  xferchan->readformat = transferee->readformat;
2862  xferchan->writeformat = transferee->writeformat;
2863 
2864  if (ast_channel_masquerade(xferchan, transferee)) {
2865  ast_hangup(xferchan);
2866  ast_hangup(newchan);
2867  ast_party_connected_line_free(&connected_line);
2868  return -1;
2869  }
2870 
2871  dash = strrchr(xferto, '@');
2872  if (dash) {
2873  /* Trim off the context. */
2874  *dash = '\0';
2875  }
2876  ast_explicit_goto(xferchan, transferer_real_context, xferto, 1);
2877  xferchan->_state = AST_STATE_UP;
2878  ast_clear_flag(xferchan, AST_FLAGS_ALL);
2879 
2880  /* Do the masquerade manually to make sure that is is completed. */
2881  ast_do_masquerade(xferchan);
2882 
2883  newchan->_state = AST_STATE_UP;
2884  ast_clear_flag(newchan, AST_FLAGS_ALL);
2885  tobj = ast_calloc(1, sizeof(*tobj));
2886  if (!tobj) {
2887  ast_hangup(xferchan);
2888  ast_hangup(newchan);
2889  ast_party_connected_line_free(&connected_line);
2890  return -1;
2891  }
2892 
2893  tobj->chan = newchan;
2894  tobj->peer = xferchan;
2895  tobj->bconfig = *config;
2896 
2897  ast_channel_lock(newchan);
2898  features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL);
2899  if (features_datastore && (dialfeatures = features_datastore->data)) {
2900  ast_copy_flags(&tobj->bconfig.features_callee, &dialfeatures->my_features,
2901  AST_FLAGS_ALL);
2902  }
2903  ast_channel_unlock(newchan);
2904 
2905  ast_channel_lock(xferchan);
2906  features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL);
2907  if (features_datastore && (dialfeatures = features_datastore->data)) {
2908  ast_copy_flags(&tobj->bconfig.features_caller, &dialfeatures->my_features,
2909  AST_FLAGS_ALL);
2910  }
2911  ast_channel_unlock(xferchan);
2912 
2914  tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
2915  }
2916 
2917  /*
2918  * xferchan is transferee, and newchan is the transfer target
2919  * So...in a transfer, who is the caller and who is the callee?
2920  *
2921  * When the call is originally made, it is clear who is caller and callee.
2922  * When a transfer occurs, it is my humble opinion that the transferee becomes
2923  * the caller, and the transfer target is the callee.
2924  *
2925  * The problem is that these macros were set with the intention of the original
2926  * caller and callee taking those roles. A transfer can totally mess things up,
2927  * to be technical. What sucks even more is that you can't effectively change
2928  * the macros in the dialplan during the call from the transferer to the transfer
2929  * target because the transferee is stuck with whatever role he originally had.
2930  *
2931  * I think the answer here is just to make sure that it is well documented that
2932  * during a transfer, the transferee is the "caller" and the transfer target
2933  * is the "callee."
2934  *
2935  * This means that if party B calls party A, and party B transfers party A to
2936  * party C, then A has switched roles for the call. Now party A will have the
2937  * caller macro called on his channel instead of the callee macro.
2938  *
2939  * Luckily, the method by which the party B to party C bridge is
2940  * launched above ensures that the transferee is the "chan" on
2941  * the bridge and the transfer target is the "peer," so my idea
2942  * for the roles post-transfer does not require extensive code
2943  * changes.
2944  */
2945 
2946  /* Transfer party C connected line to party A */
2947  ast_channel_lock(transferer);
2948  /*
2949  * Due to a limitation regarding when callerID is set on a Local channel,
2950  * we use the transferer's connected line information here.
2951  */
2952  ast_party_connected_line_copy(&connected_line, &transferer->connected);
2953  ast_channel_unlock(transferer);
2954  connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2955  if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
2956  ast_channel_update_connected_line(xferchan, &connected_line, NULL);
2957  }
2958 
2959  /* Transfer party A connected line to party C */
2960  ast_channel_lock(xferchan);
2961  ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
2962  ast_channel_unlock(xferchan);
2963  connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2964  if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
2965  ast_channel_update_connected_line(newchan, &connected_line, NULL);
2966  }
2967 
2968  if (ast_stream_and_wait(newchan, xfersound, ""))
2969  ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2971 
2972  ast_party_connected_line_free(&connected_line);
2973  return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
2974 }
struct ast_flags peer_features
Definition: features.c:653
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
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
static struct ast_channel * feature_request_and_dial(struct ast_channel *caller, const char *caller_name, struct ast_channel *requestor, struct ast_channel *transferee, const char *type, format_t format, void *data, int timeout, int *outstate, const char *language)
Definition: features.c:3544
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
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
struct ast_channel * peer
Definition: features.c:858
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
Present a dialtone and collect a certain length extension.
Definition: app.c:120
static int transferdigittimeout
Definition: features.c:614
void(* end_bridge_callback_data_fixup)(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
Definition: channel.h:993
static const char config[]
Definition: cdr_csv.c:57
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
char * strsep(char **str, const char *delims)
struct ast_channel * chan
Definition: features.c:857
struct ast_flags features_callee
Definition: channel.h:976
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
format_t writeformat
Definition: channel.h:854
int visible_indication
Definition: channel.h:861
static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
Definition: features.c:2490
#define AST_DIGIT_ANY
Definition: file.h:47
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
#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
static unsigned int atxferloopdelay
Definition: features.c:620
static char xferfailsound[256]
Definition: features.c:591
static int atxfernoanswertimeout
Definition: features.c:618
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
Definition: features.c:3960
static int finishup(struct ast_channel *chan)
Definition: features.c:1870
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
Definition: channel.c:1062
struct ast_flags my_features
Definition: features.c:651
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8708
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
format_t nativeformats
Definition: channel.h:852
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
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
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
static struct ast_exten * get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
Definition: features.c:823
const ast_string_field linkedid
Definition: channel.h:787
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
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
static unsigned int atxferdropcall
Definition: features.c:619
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
bridge configuration
Definition: channel.h:974
static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
make channels compatible
Definition: features.c:2466
static struct ast_datastore_info dial_features_info
Definition: features.c:752
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
struct ast_flags features_caller
Definition: channel.h:975
static const char * real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
Find the context for the transfer.
Definition: features.c:2321
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
a transfer occurs
Definition: cel.h:76
static unsigned int atxfercallbackretries
Definition: features.c:621
enum ast_channel_state _state
Definition: channel.h:839
static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
Definition: features.c:1891
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
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static char xfersound[256]
Definition: features.c:590
static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
Definition: features.c:768
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
#define AST_FLAGS_ALL
Definition: utils.h:196
Structure used to handle boolean flags.
Definition: utils.h:200
#define ast_clear_flag(p, flag)
Definition: utils.h:77
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
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
void * data
Definition: datastore.h:56
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
format_t readformat
Definition: channel.h:853
#define ast_calloc(a, b)
Definition: astmm.h:82
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
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
struct ast_bridge_config bconfig
Definition: features.c:856
const ast_string_field language
Definition: channel.h:787
static void bridge_call_thread_launch(struct ast_bridge_thread_obj *data)
create thread for the parked call
Definition: features.c:1037
int ast_do_masquerade(struct ast_channel *chan)
Start masquerading a channel.
Definition: channel.c:6546
static void set_peers(struct ast_channel **caller, struct ast_channel **callee, struct ast_channel *peer, struct ast_channel *chan, int sense)
set caller and callee according to the direction
Definition: features.c:1951
static int builtin_automixmonitor ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
const char *  code,
int  sense,
void *  data 
)
static

Definition at line 2200 of file features.c.

References args, ast_alloca, AST_AUDIOHOOK_TYPE_SPY, ast_autoservice_ignore(), ast_autoservice_start(), ast_autoservice_stop(), ast_channel_audiohook_count_by_source(), ast_channel_audiohook_count_by_source_running(), ast_channel_lock, ast_channel_unlock, AST_FEATURE_RETURN_SUCCESS, AST_FRAME_DTMF_END, ast_log(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_verb, ast_channel::caller, courtesytone, ast_party_caller::id, len(), LOG_ERROR, LOG_WARNING, mixmonitor_app, mixmonitor_ok, mixmonitor_spy_type, ast_channel::name, ast_party_id::number, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), S_COR, S_OR, set_peers(), stopmixmonitor_app, stopmixmonitor_ok, ast_party_number::str, and ast_party_number::valid.

2201 {
2202  char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
2203  int x = 0;
2204  size_t len;
2205  struct ast_channel *caller_chan, *callee_chan;
2206  const char *mixmonitor_spy_type = "MixMonitor";
2207  const char *touch_format;
2208  const char *touch_monitor;
2209  int count = 0;
2210 
2211  if (!mixmonitor_ok) {
2212  ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
2213  return -1;
2214  }
2215 
2216  if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
2217  mixmonitor_ok = 0;
2218  ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
2219  return -1;
2220  }
2221 
2222  set_peers(&caller_chan, &callee_chan, peer, chan, sense);
2223 
2224  if (!ast_strlen_zero(courtesytone)) {
2225  if (ast_autoservice_start(callee_chan))
2226  return -1;
2228  if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
2229  ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2230  ast_autoservice_stop(callee_chan);
2231  return -1;
2232  }
2233  if (ast_autoservice_stop(callee_chan))
2234  return -1;
2235  }
2236 
2237  ast_channel_lock(callee_chan);
2238  count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
2239  ast_channel_unlock(callee_chan);
2240 
2241  /* This means a mixmonitor is attached to the channel, running or not is unknown. */
2242  if (count > 0) {
2243  ast_verb(3, "User hit '%s' to stop recording call.\n", code);
2244 
2245  /* Make sure they are running */
2246  ast_channel_lock(callee_chan);
2247  count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
2248  ast_channel_unlock(callee_chan);
2249  if (count > 0) {
2250  if (!stopmixmonitor_ok) {
2251  ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2252  return -1;
2253  }
2254  if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
2255  stopmixmonitor_ok = 0;
2256  ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2257  return -1;
2258  } else {
2259  pbx_exec(callee_chan, stopmixmonitor_app, "");
2261  }
2262  }
2263 
2264  ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
2265  }
2266 
2267  touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
2268  touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
2269 
2270  if (!touch_format)
2271  touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
2272 
2273  if (!touch_monitor)
2274  touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
2275 
2276  if (touch_monitor) {
2277  len = strlen(touch_monitor) + 50;
2278  args = ast_alloca(len);
2279  touch_filename = ast_alloca(len);
2280  snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
2281  snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
2282  } else {
2283  caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
2284  caller_chan->caller.id.number.str, caller_chan->name));
2285  callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
2286  callee_chan->caller.id.number.str, callee_chan->name));
2287  len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
2288  args = ast_alloca(len);
2289  touch_filename = ast_alloca(len);
2290  snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
2291  snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
2292  }
2293 
2294  for( x = 0; x < strlen(args); x++) {
2295  if (args[x] == '/')
2296  args[x] = '-';
2297  }
2298 
2299  ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
2300 
2301  pbx_exec(callee_chan, mixmonitor_app, args);
2302  pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
2303  pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
2305 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#define LOG_WARNING
Definition: logger.h:144
static struct ast_app * stopmixmonitor_app
Definition: features.c:645
static int mixmonitor_ok
Definition: features.c:643
#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
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int ast_channel_audiohook_count_by_source(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
Find out how many audiohooks from a certain source exist on a given channel, regardless of status...
Definition: audiohook.c:791
static const char *const mixmonitor_spy_type
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#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_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
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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 ast_channel_unlock(chan)
Definition: channel.h:2467
static char courtesytone[256]
Definition: features.c:589
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
static int stopmixmonitor_ok
Definition: features.c:646
int ast_autoservice_ignore(struct ast_channel *chan, enum ast_frame_type ftype)
Ignore certain frame types.
Definition: autoservice.c:307
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 struct ast_app * mixmonitor_app
Definition: features.c:642
#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
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
int ast_channel_audiohook_count_by_source_running(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
Find out how many spies of a certain type exist on a given channel, and are in state running...
Definition: audiohook.c:830
static void set_peers(struct ast_channel **caller, struct ast_channel **callee, struct ast_channel *peer, struct ast_channel *chan, int sense)
set caller and callee according to the direction
Definition: features.c:1951
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int builtin_automonitor ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
const char *  code,
int  sense,
void *  data 
)
static

Monitor a channel by DTMF.

Parameters
chanchannel requesting monitor
peerchannel to be monitored
config
code
sensefeature options
dataCheck monitor app enabled, setup channels, both caller/callee chans not null get TOUCH_MONITOR variable for filename if exists, exec monitor app.
Return values
AST_FEATURE_RETURN_SUCCESSon success.
-1on error.

Definition at line 2098 of file features.c.

References args, ast_alloca, AST_FEATURE_RETURN_SUCCESS, ast_log(), ast_strdupa, ast_strlen_zero(), ast_verb, ast_channel::caller, courtesytone, EVENT_FLAG_USER, ast_party_caller::id, len(), LOG_ERROR, manager_event, ast_channel::monitor, monitor_app, monitor_ok, ast_channel::name, ast_party_id::number, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), play_message_in_bridged_call(), S_COR, S_OR, set_peers(), ast_channel_monitor::stop, ast_party_number::str, ast_channel::uniqueid, and ast_party_number::valid.

2099 {
2100  char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
2101  int x = 0;
2102  size_t len;
2103  struct ast_channel *caller_chan, *callee_chan;
2104  const char *automon_message_start = NULL;
2105  const char *automon_message_stop = NULL;
2106  const char *touch_format = NULL;
2107  const char *touch_monitor = NULL;
2108  const char *touch_monitor_prefix = NULL;
2109 
2110  if (!monitor_ok) {
2111  ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
2112  return -1;
2113  }
2114 
2115  if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
2116  monitor_ok = 0;
2117  ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
2118  return -1;
2119  }
2120 
2121  set_peers(&caller_chan, &callee_chan, peer, chan, sense);
2122 
2123  /* Find extra messages */
2124  automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
2125  automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
2126 
2127  if (!ast_strlen_zero(courtesytone)) { /* Play courtesy tone if configured */
2128  if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
2129  return -1;
2130  }
2131  }
2132 
2133  if (callee_chan->monitor) {
2134  manager_event(EVENT_FLAG_USER, "UserEvent",
2135  "UserEvent: StopRec\r\n"
2136  "Uniqueid: %s\r\n",
2137  caller_chan->uniqueid);
2138  ast_verb(4, "User hit '%s' to stop recording call.\n", code);
2139  if (!ast_strlen_zero(automon_message_stop)) {
2140  play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
2141  }
2142  callee_chan->monitor->stop(callee_chan, 1);
2144  }
2145 
2146  touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
2147  touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
2148  touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
2149 
2150  if (!touch_format)
2151  touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
2152 
2153  if (!touch_monitor)
2154  touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
2155 
2156  if (!touch_monitor_prefix)
2157  touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
2158 
2159  if (touch_monitor) {
2160  len = strlen(touch_monitor) + 50;
2161  args = ast_alloca(len);
2162  touch_filename = ast_alloca(len);
2163  snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
2164  snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
2165  } else {
2166  caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
2167  caller_chan->caller.id.number.str, caller_chan->name));
2168  callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
2169  callee_chan->caller.id.number.str, callee_chan->name));
2170  len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
2171  args = ast_alloca(len);
2172  touch_filename = ast_alloca(len);
2173  snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
2174  snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
2175  }
2176 
2177  for(x = 0; x < strlen(args); x++) {
2178  if (args[x] == '/')
2179  args[x] = '-';
2180  }
2181 
2182  manager_event(EVENT_FLAG_USER, "UserEvent",
2183  "UserEvent: Rec\r\n"
2184  "Uniqueid: %s\r\n"
2185  "FileName: %s\r\n",
2186  caller_chan->uniqueid, touch_filename);
2187  ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
2188 
2189  pbx_exec(callee_chan, monitor_app, args);
2190  pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
2191  pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
2192 
2193  if (!ast_strlen_zero(automon_message_start)) { /* Play start message for both channels */
2194  play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
2195  }
2196 
2198 }
Main Channel structure associated with a channel.
Definition: channel.h:742
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
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 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
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
static int monitor_ok
Definition: features.c:640
static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
Play message to both caller and callee in bridged call, plays synchronously, autoservicing the other ...
Definition: features.c:2078
int(* stop)(struct ast_channel *chan, int need_lock)
Definition: monitor.h:50
#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
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#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
static struct ast_app * monitor_app
Definition: features.c:639
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
#define EVENT_FLAG_USER
Definition: manager.h:77
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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
static char courtesytone[256]
Definition: features.c:589
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 S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
struct ast_channel_monitor * monitor
Definition: channel.h:769
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
static void set_peers(struct ast_channel **caller, struct ast_channel **callee, struct ast_channel *peer, struct ast_channel *chan, int sense)
set caller and callee according to the direction
Definition: features.c:1951
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int builtin_blindtransfer ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
const char *  code,
int  sense,
void *  data 
)
static

Blind transfer user to another extension.

Parameters
chanchannel to be transferred
peerchannel initiated blind transfer
config
code
data
sensefeature options

Place chan on hold, check if transferred to parkinglot extension, otherwise check extension exists and transfer caller.

Return values
AST_FEATURE_RETURN_SUCCESS.
-1on failure.

Definition at line 2350 of file features.c.

References ast_app_dtget(), ast_async_goto(), ast_autoservice_start(), ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), AST_CEL_BLINDTRANSFER, ast_cel_report_event(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_HOLD, ast_debug, AST_DIGIT_ANY, AST_FEATURE_RETURN_SUCCESS, AST_FEATURE_RETURN_SUCCESSBREAK, AST_FLAG_BRIDGE_HANGUP_DONT, ast_indicate(), ast_log(), ast_set_flag, ast_stream_and_wait(), ast_verb, ast_channel::cdr, ast_cdr::channel, check_goto_on_transfer(), ast_cdr::dstchannel, finishup(), get_parking_exten(), ast_cdr::lastapp, ast_cdr::lastdata, LOG_WARNING, ast_channel::name, ast_channel::pbx, pbx_builtin_setvar_helper(), real_ctx(), set_c_e_p(), set_peers(), transferdigittimeout, and xfer_park_call_helper().

2351 {
2352  struct ast_channel *transferer;
2353  struct ast_channel *transferee;
2354  struct ast_exten *park_exten;
2355  const char *transferer_real_context;
2356  char xferto[256] = "";
2357  int res;
2358 
2359  ast_debug(1, "Executing Blind Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2360  set_peers(&transferer, &transferee, peer, chan, sense);
2361  transferer_real_context = real_ctx(transferer, transferee);
2362 
2363  /* Start autoservice on transferee while we talk to the transferer */
2364  ast_autoservice_start(transferee);
2365  ast_indicate(transferee, AST_CONTROL_HOLD);
2366 
2367  /* Transfer */
2368  res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2369  if (res < 0) {
2370  finishup(transferee);
2371  return -1; /* error ? */
2372  }
2373  if (res > 0) { /* If they've typed a digit already, handle it */
2374  xferto[0] = (char) res;
2375  }
2376 
2377  res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2378  if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
2379  finishup(transferee);
2380  return -1;
2381  }
2382  if (res == 0) {
2383  if (xferto[0]) {
2384  ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2385  xferto, transferer_real_context);
2386  } else {
2387  /* Does anyone care about this case? */
2388  ast_log(LOG_WARNING, "No digits dialed.\n");
2389  }
2390  ast_stream_and_wait(transferer, "pbx-invalid", "");
2391  finishup(transferee);
2393  }
2394 
2395  park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
2396  if (park_exten) {
2397  /* We are transfering the transferee to a parking lot. */
2398  return xfer_park_call_helper(transferee, transferer, park_exten);
2399  }
2400 
2401  /* Do blind transfer. */
2402  ast_verb(3, "Blind transferring %s to '%s' (context %s) priority 1\n",
2403  transferee->name, xferto, transferer_real_context);
2404  ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
2405  pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
2406  pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
2407  finishup(transferee);
2408  ast_channel_lock(transferer);
2409  if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
2410  transferer->cdr = ast_cdr_alloc();
2411  if (transferer->cdr) {
2412  ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
2413  ast_cdr_start(transferer->cdr);
2414  }
2415  }
2416  ast_channel_unlock(transferer);
2417  if (transferer->cdr) {
2418  struct ast_cdr *swap = transferer->cdr;
2419 
2420  ast_debug(1,
2421  "transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
2422  transferer->name, transferee->name, transferer->cdr->lastapp,
2423  transferer->cdr->lastdata, transferer->cdr->channel,
2424  transferer->cdr->dstchannel);
2425  ast_debug(1, "TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
2426  transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel,
2427  transferee->cdr->dstchannel);
2428  ast_debug(1, "transferer_real_context=%s; xferto=%s\n",
2429  transferer_real_context, xferto);
2430  /* swap cdrs-- it will save us some time & work */
2431  transferer->cdr = transferee->cdr;
2432  transferee->cdr = swap;
2433  }
2434  if (!transferee->pbx) {
2435  /* Doh! Use our handy async_goto functions */
2436  ast_debug(1, "About to ast_async_goto %s.\n", transferee->name);
2437  if (ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
2438  ast_log(LOG_WARNING, "Async goto failed :-(\n");
2439  }
2440 
2441  /* The transferee is masqueraded and the original bridged channels can be hungup. */
2442  res = -1;
2443  } else {
2444  /* Set the transferee's new extension, since it exists, using transferer context */
2445  ast_debug(1, "About to explicit goto %s, it has a PBX.\n", transferee->name);
2446  ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
2447  set_c_e_p(transferee, transferer_real_context, xferto, 0);
2448 
2449  /*
2450  * Break the bridge. The transferee needs to resume executing
2451  * dialplan at the xferto location.
2452  */
2454  }
2455  check_goto_on_transfer(transferer);
2456  return res;
2457 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
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_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
Present a dialtone and collect a certain length extension.
Definition: app.c:120
static int transferdigittimeout
Definition: features.c:614
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
#define AST_FEATURE_RETURN_SUCCESSBREAK
Definition: features.h:40
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:94
#define AST_DIGIT_ANY
Definition: file.h:47
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
#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
static int finishup(struct ast_channel *chan)
Definition: features.c:1870
struct ast_cdr * cdr
Definition: channel.h:766
static struct ast_exten * get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
Definition: features.c:823
#define ast_verb(level,...)
Definition: logger.h:243
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:98
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
a transfer occurs
Definition: cel.h:74
static const char * real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
Find the context for the transfer.
Definition: features.c:2321
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
static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
Definition: features.c:1891
const ast_string_field name
Definition: channel.h:787
static void check_goto_on_transfer(struct ast_channel *chan)
Check goto on transfer.
Definition: features.c:896
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
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
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
store context, extension and priority
Definition: features.c:881
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
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:8731
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
Definition: cdr.c:897
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:499
static void set_peers(struct ast_channel **caller, struct ast_channel **callee, struct ast_channel *peer, struct ast_channel *chan, int sense)
set caller and callee according to the direction
Definition: features.c:1951
struct ast_pbx * pbx
Definition: channel.h:761
static int builtin_disconnect ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
const char *  code,
int  sense,
void *  data 
)
static

Definition at line 2307 of file features.c.

References AST_FEATURE_RETURN_HANGUP, and ast_verb.

2308 {
2309  ast_verb(4, "User hit '%s' to disconnect call.\n", code);
2311 }
#define ast_verb(level,...)
Definition: logger.h:243
#define AST_FEATURE_RETURN_HANGUP
Definition: features.h:39
static int builtin_parkcall ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
const char *  code,
int  sense,
void *  data 
)
static

support routing for one touch call parking

Parameters
chanchannel parking call
peerchannel to be parked
configunsed
codeunused
sensefeature options
dataunused
Return values
-1on successful park.
-1on chan hangup.
AST_FEATURE_RETURN_SUCCESSon error to keep the bridge connected.

Definition at line 1976 of file features.c.

References ast_channel::_state, ast_answer(), AST_FEATURE_RETURN_SUCCESS, ast_safe_sleep(), AST_STATE_UP, masq_park_call(), and set_peers().

1977 {
1978  struct ast_channel *parker;
1979  struct ast_channel *parkee;
1980  struct ast_park_call_args args = { 0, };
1981 
1982  /*
1983  * We used to set chan's exten and priority to "s" and 1 here,
1984  * but this generates (in some cases) an invalid extension, and
1985  * if "s" exists, could errantly cause execution of extensions
1986  * you don't expect. It makes more sense to let nature take its
1987  * course when chan finishes, and let the pbx do its thing and
1988  * hang up when the park is over.
1989  */
1990 
1991  /* Answer if call is not up */
1992  if (chan->_state != AST_STATE_UP) {
1993  /*
1994  * XXX Why are we doing this? Both of the channels should be up
1995  * since you cannot do DTMF features unless you are bridged.
1996  */
1997  if (ast_answer(chan)) {
1998  return -1;
1999  }
2000 
2001  /* Sleep to allow VoIP streams to settle down */
2002  if (ast_safe_sleep(chan, 1000)) {
2003  return -1;
2004  }
2005  }
2006 
2007  /* one direction used to call park_call.... */
2008  set_peers(&parker, &parkee, peer, chan, sense);
2009  return masq_park_call(parkee, parker, &args) ? AST_FEATURE_RETURN_SUCCESS : -1;
2010 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
Main Channel structure associated with a channel.
Definition: channel.h:742
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 struct @350 args
enum ast_channel_state _state
Definition: channel.h:839
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
static void set_peers(struct ast_channel **caller, struct ast_channel **callee, struct ast_channel *peer, struct ast_channel *chan, int sense)
set caller and callee according to the direction
Definition: features.c:1951
static char* callback_dialoptions ( struct ast_flags features_callee,
struct ast_flags features_caller,
char *  options,
size_t  len 
)
static

Definition at line 4651 of file features.c.

References AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, and ast_test_flag.

Referenced by manage_parked_call().

4652 {
4653  int i = 0;
4654  enum {
4655  OPT_CALLEE_REDIRECT = 't',
4656  OPT_CALLER_REDIRECT = 'T',
4657  OPT_CALLEE_AUTOMON = 'w',
4658  OPT_CALLER_AUTOMON = 'W',
4659  OPT_CALLEE_DISCONNECT = 'h',
4660  OPT_CALLER_DISCONNECT = 'H',
4661  OPT_CALLEE_PARKCALL = 'k',
4662  OPT_CALLER_PARKCALL = 'K',
4663  };
4664 
4665  memset(options, 0, len);
4666  if (ast_test_flag(features_caller, AST_FEATURE_REDIRECT) && i < len) {
4667  options[i++] = OPT_CALLER_REDIRECT;
4668  }
4669  if (ast_test_flag(features_caller, AST_FEATURE_AUTOMON) && i < len) {
4670  options[i++] = OPT_CALLER_AUTOMON;
4671  }
4672  if (ast_test_flag(features_caller, AST_FEATURE_DISCONNECT) && i < len) {
4673  options[i++] = OPT_CALLER_DISCONNECT;
4674  }
4675  if (ast_test_flag(features_caller, AST_FEATURE_PARKCALL) && i < len) {
4676  options[i++] = OPT_CALLER_PARKCALL;
4677  }
4678 
4679  if (ast_test_flag(features_callee, AST_FEATURE_REDIRECT) && i < len) {
4680  options[i++] = OPT_CALLEE_REDIRECT;
4681  }
4682  if (ast_test_flag(features_callee, AST_FEATURE_AUTOMON) && i < len) {
4683  options[i++] = OPT_CALLEE_AUTOMON;
4684  }
4685  if (ast_test_flag(features_callee, AST_FEATURE_DISCONNECT) && i < len) {
4686  options[i++] = OPT_CALLEE_DISCONNECT;
4687  }
4688  if (ast_test_flag(features_callee, AST_FEATURE_PARKCALL) && i < len) {
4689  options[i++] = OPT_CALLEE_PARKCALL;
4690  }
4691 
4692  return options;
4693 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int check_compat ( struct ast_channel c,
struct ast_channel newchan 
)
static

make channels compatible

Parameters
c
newchan
Return values
0on success.
-1on failure.

Definition at line 2466 of file features.c.

References ast_channel_make_compatible(), ast_hangup(), ast_log(), LOG_WARNING, and ast_channel::name.

Referenced by builtin_atxfer().

2467 {
2468  if (ast_channel_make_compatible(c, newchan) < 0) {
2469  ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
2470  c->name, newchan->name);
2471  ast_hangup(newchan);
2472  return -1;
2473  }
2474  return 0;
2475 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
#define LOG_WARNING
Definition: logger.h:144
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 ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
Definition: channel.c:5970
static void check_goto_on_transfer ( struct ast_channel chan)
static

Check goto on transfer.

Parameters
chanCheck if channel has 'GOTO_ON_BLINDXFR' set, if not exit. When found make sure the types are compatible. Check if channel is valid if so start the new channel else hangup the call.

Definition at line 896 of file features.c.

References ast_channel::_state, ast_channel_alloc(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_clear_flag, ast_debug, ast_do_masquerade(), AST_FLAGS_ALL, ast_hangup(), ast_parseable_goto(), ast_pbx_start(), AST_SOFTHANGUP_ALL, AST_STATE_DOWN, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_channel::linkedid, ast_channel::name, pbx_builtin_getvar_helper(), ast_channel::readformat, and ast_channel::writeformat.

Referenced by builtin_blindtransfer().

897 {
898  struct ast_channel *xferchan;
899  const char *val;
900  char *goto_on_transfer;
901  char *x;
902 
903  ast_channel_lock(chan);
904  val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
905  if (ast_strlen_zero(val)) {
906  ast_channel_unlock(chan);
907  return;
908  }
909  goto_on_transfer = ast_strdupa(val);
910  ast_channel_unlock(chan);
911 
912  ast_debug(1, "Attempting GOTO_ON_BLINDXFR=%s for %s.\n", val, chan->name);
913 
914  xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0,
915  "%s", chan->name);
916  if (!xferchan) {
917  return;
918  }
919 
920  /* Make formats okay */
921  xferchan->readformat = chan->readformat;
922  xferchan->writeformat = chan->writeformat;
923 
924  if (ast_channel_masquerade(xferchan, chan)) {
925  /* Failed to setup masquerade. */
926  ast_hangup(xferchan);
927  return;
928  }
929 
930  for (x = goto_on_transfer; *x; ++x) {
931  if (*x == '^') {
932  *x = ',';
933  }
934  }
935  ast_parseable_goto(xferchan, goto_on_transfer);
936  xferchan->_state = AST_STATE_UP;
937  ast_clear_flag(xferchan, AST_FLAGS_ALL);
939 
940  ast_do_masquerade(xferchan);
941  if (ast_pbx_start(xferchan)) {
942  /* Failed to start PBX. */
943  ast_hangup(xferchan);
944  }
945 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
Definition: ast_expr2.c:325
format_t writeformat
Definition: channel.h:854
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
const ast_string_field linkedid
Definition: channel.h:787
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2707
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:11326
All softhangup flags.
Definition: channel.h:1055
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define AST_FLAGS_ALL
Definition: utils.h:196
#define ast_clear_flag(p, flag)
Definition: utils.h:77
format_t readformat
Definition: channel.h:853
int ast_do_masquerade(struct ast_channel *chan)
Start masquerading a channel.
Definition: channel.c:6546
static void clear_dialed_interfaces ( struct ast_channel chan)
static

Definition at line 3911 of file features.c.

References ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_unlock, ast_datastore_free(), ast_log(), dialed_interface_info, LOG_DEBUG, ast_channel::name, and option_debug.

Referenced by ast_bridge_call().

3912 {
3913  struct ast_datastore *di_datastore;
3914 
3915  ast_channel_lock(chan);
3916  if ((di_datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL))) {
3917  if (option_debug) {
3918  ast_log(LOG_DEBUG, "Removing dialed interfaces datastore on %s since we're bridging\n", chan->name);
3919  }
3920  if (!ast_channel_datastore_remove(chan, di_datastore)) {
3921  ast_datastore_free(di_datastore);
3922  }
3923  }
3924  ast_channel_unlock(chan);
3925 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
int option_debug
Definition: asterisk.c:182
Structure for a data store object.
Definition: datastore.h:54
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
#define LOG_DEBUG
Definition: logger.h:122
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
struct ast_datastore_info dialed_interface_info
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 ast_channel_unlock(chan)
Definition: channel.h:2467
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2599
static struct ast_parkinglot * copy_parkinglot ( const char *  name,
const struct ast_parkinglot parkinglot 
)
static

Copy parkinglot and store it with new name.

Definition at line 5034 of file features.c.

References ao2_ref, ast_debug, ast_parkinglot::cfg, create_parkinglot(), and find_parkinglot().

Referenced by create_dynamic_parkinglot().

5035 {
5036  struct ast_parkinglot *copylot;
5037 
5038  if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
5039  ao2_ref(copylot, -1);
5040  return NULL;
5041  }
5042 
5043  copylot = create_parkinglot(name);
5044  if (!copylot) {
5045  return NULL;
5046  }
5047 
5048  ast_debug(1, "Building parking lot %s\n", name);
5049 
5050  /* Copy the source parking lot configuration. */
5051  copylot->cfg = parkinglot->cfg;
5052 
5053  return copylot;
5054 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define ao2_ref(o, delta)
Definition: astobj2.h:472
Structure for parking lots which are put in a container.
Definition: features.c:556
struct parkinglot_cfg cfg
Definition: features.c:560
static const char name[]
static struct ast_parkinglot * create_parkinglot(const char *name)
Allocate parking lot structure.
Definition: features.c:5459
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
Definition: features.c:5017
static struct ast_parkinglot* create_dynamic_parkinglot ( const char *  name,
struct ast_channel chan 
)
static

Definition at line 1165 of file features.c.

References ao2_link, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), ast_parkinglot::cfg, copy_parkinglot(), default_parkinglot, find_parkinglot(), parkinglot_cfg::is_invalid, LOG_ERROR, LOG_WARNING, ast_parkinglot::name, parkinglot_cfg::parkext, parkinglot_cfg::parkext_exclusive, parkinglot_cfg::parking_con, parkinglot_cfg::parking_start, parkinglot_cfg::parking_stop, parkinglot, parkinglot_activate(), parkinglot_addref(), parkinglot_unref(), parkinglots, pbx_builtin_getvar_helper(), and S_OR.

Referenced by ast_masq_park_call_exten(), ast_park_call_exten(), park_call_exec(), park_space_reserve(), and xfer_park_call_helper().

1166 {
1167  const char *dyn_context;
1168  const char *dyn_exten;
1169  const char *dyn_range;
1170  const char *template_name;
1171  struct ast_parkinglot *template_parkinglot = NULL;
1172  struct ast_parkinglot *parkinglot;
1173  int dyn_start;
1174  int dyn_end;
1175 
1176  ast_channel_lock(chan);
1177  template_name = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
1178  dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
1179  dyn_exten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNEXTEN"), ""));
1180  dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
1181  ast_channel_unlock(chan);
1182 
1183  if (!ast_strlen_zero(template_name)) {
1184  template_parkinglot = find_parkinglot(template_name);
1185  if (!template_parkinglot) {
1186  ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
1187  template_name);
1188  } else if (template_parkinglot->cfg.is_invalid) {
1189  ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
1190  template_name);
1191  parkinglot_unref(template_parkinglot);
1192  template_parkinglot = NULL;
1193  }
1194  }
1195  if (!template_parkinglot) {
1196  template_parkinglot = parkinglot_addref(default_parkinglot);
1197  ast_debug(1, "Using default parking lot for template\n");
1198  }
1199 
1200  parkinglot = copy_parkinglot(name, template_parkinglot);
1201  if (!parkinglot) {
1202  ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
1203  } else {
1204  /* Configure the dynamic parking lot. */
1205  if (!ast_strlen_zero(dyn_context)) {
1206  ast_copy_string(parkinglot->cfg.parking_con, dyn_context,
1207  sizeof(parkinglot->cfg.parking_con));
1208  }
1209  if (!ast_strlen_zero(dyn_exten)) {
1210  ast_copy_string(parkinglot->cfg.parkext, dyn_exten,
1211  sizeof(parkinglot->cfg.parkext));
1212  }
1213  if (!ast_strlen_zero(dyn_range)) {
1214  if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
1216  "Format for parking positions is a-b, where a and b are numbers\n");
1217  } else if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
1219  "Format for parking positions is a-b, where a <= b\n");
1220  } else {
1221  parkinglot->cfg.parking_start = dyn_start;
1222  parkinglot->cfg.parking_stop = dyn_end;
1223  }
1224  }
1225 
1226  /*
1227  * Sanity check for dynamic parking lot configuration.
1228  *
1229  * XXX It may be desirable to instead check if the dynamic
1230  * parking lot overlaps any existing lots like what is done for
1231  * a reload.
1232  */
1233  if (!strcmp(parkinglot->cfg.parking_con, template_parkinglot->cfg.parking_con)) {
1234  if (!strcmp(parkinglot->cfg.parkext, template_parkinglot->cfg.parkext)
1235  && parkinglot->cfg.parkext_exclusive) {
1237  "Parking lot '%s' conflicts with template parking lot '%s'!\n"
1238  "Change either PARKINGDYNCONTEXT or PARKINGDYNEXTEN.\n",
1239  parkinglot->name, template_parkinglot->name);
1240  }
1241  if ((template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_start
1242  && parkinglot->cfg.parking_start <= template_parkinglot->cfg.parking_stop)
1243  || (template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_stop
1244  && parkinglot->cfg.parking_stop <= template_parkinglot->cfg.parking_stop)
1245  || (parkinglot->cfg.parking_start < template_parkinglot->cfg.parking_start
1246  && template_parkinglot->cfg.parking_stop < parkinglot->cfg.parking_stop)) {
1248  "Parking lot '%s' parking spaces overlap template parking lot '%s'!\n"
1249  "Change PARKINGDYNPOS.\n",
1250  parkinglot->name, template_parkinglot->name);
1251  }
1252  }
1253 
1254  parkinglot_activate(parkinglot);
1255  ao2_link(parkinglots, parkinglot);
1256  }
1257  parkinglot_unref(template_parkinglot);
1258 
1259  return parkinglot;
1260 }
int parking_stop
Definition: features.c:501
#define ast_channel_lock(chan)
Definition: channel.h:2466
static struct ast_parkinglot * parkinglot_addref(struct ast_parkinglot *parkinglot)
Definition: features.c:5435
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
static struct ast_parkinglot * copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot)
Copy parkinglot and store it with new name.
Definition: features.c:5034
#define LOG_WARNING
Definition: logger.h:144
static struct ast_parkinglot * default_parkinglot
Default parking lot.
Definition: features.c:582
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
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
unsigned int is_invalid
Definition: features.c:552
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
unsigned int parkext_exclusive
Definition: features.c:548
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int parking_start
Definition: features.c:499
static int parkinglot_activate(struct ast_parkinglot *parkinglot)
Definition: features.c:5640
Structure for parking lots which are put in a container.
Definition: features.c:556
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
struct parkinglot_cfg cfg
Definition: features.c:560
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 const char name[]
char parkext[AST_MAX_EXTENSION]
Definition: features.c:495
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
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
Definition: features.c:5017
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
static struct ast_parkinglot * create_parkinglot ( const char *  name)
static

Allocate parking lot structure.

Definition at line 5459 of file features.c.

References ao2_alloc, ast_copy_string(), AST_LIST_HEAD_INIT, ast_strlen_zero(), ast_parkinglot::cfg, parkinglot_cfg::is_invalid, ast_parkinglot::name, parkinglot_destroy(), and ast_parkinglot::parkings.

Referenced by build_parkinglot(), and copy_parkinglot().

5460 {
5461  struct ast_parkinglot *newlot;
5462 
5463  if (ast_strlen_zero(name)) { /* No name specified */
5464  return NULL;
5465  }
5466 
5467  newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);
5468  if (!newlot)
5469  return NULL;
5470 
5471  ast_copy_string(newlot->name, name, sizeof(newlot->name));
5472  newlot->cfg.is_invalid = 1;/* No config is set yet. */
5473  AST_LIST_HEAD_INIT(&newlot->parkings);
5474 
5475  return newlot;
5476 }
static void parkinglot_destroy(void *obj)
Destroy a parking lot.
Definition: features.c:5445
unsigned int is_invalid
Definition: features.c:552
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Structure for parking lots which are put in a container.
Definition: features.c:556
struct parkinglot_cfg cfg
Definition: features.c:560
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
static const char name[]
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:611
struct ast_parkinglot::parkinglot_parklist parkings
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static void destroy_dialplan_usage_context ( struct parking_dp_context doomed)
static

Definition at line 6043 of file features.c.

References parking_dp_context::access_extens, ast_free, AST_LIST_REMOVE_HEAD, parking_dp_context::hints, and parking_dp_context::spaces.

Referenced by build_dialplan_useage_context(), and destroy_dialplan_usage_map().

6044 {
6045  struct parking_dp_ramp *ramp;
6046  struct parking_dp_spaces *spaces;
6047 
6048  while ((ramp = AST_LIST_REMOVE_HEAD(&doomed->access_extens, node))) {
6049  ast_free(ramp);
6050  }
6051  while ((spaces = AST_LIST_REMOVE_HEAD(&doomed->spaces, node))) {
6052  ast_free(spaces);
6053  }
6054  while ((spaces = AST_LIST_REMOVE_HEAD(&doomed->hints, node))) {
6055  ast_free(spaces);
6056  }
6057  ast_free(doomed);
6058 }
struct parking_dp_space_map hints
Definition: features.c:458
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct parking_dp_ramp_map access_extens
Definition: features.c:454
#define ast_free(a)
Definition: astmm.h:97
struct parking_dp_spaces::@268 node
struct parking_dp_space_map spaces
Definition: features.c:456
static void destroy_dialplan_usage_map ( struct parking_dp_map doomed)
static

Definition at line 6068 of file features.c.

References AST_LIST_REMOVE_HEAD, and destroy_dialplan_usage_context().

Referenced by load_config().

6069 {
6070  struct parking_dp_context *item;
6071 
6072  while ((item = AST_LIST_REMOVE_HEAD(doomed, node))) {
6074  }
6075 }
static void destroy_dialplan_usage_context(struct parking_dp_context *doomed)
Definition: features.c:6043
struct parking_dp_context::@269 node
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
static void destroy_space ( const char *  context,
int  space 
)
static

Definition at line 6498 of file features.c.

References AST_MAX_EXTENSION, PRIORITY_HINT, and remove_exten_if_exist().

Referenced by remove_dead_context_usage(), and remove_dead_spaces_usage().

6499 {
6500  char exten[AST_MAX_EXTENSION];
6501 
6502  /* Destroy priorities of the parking space that we registered. */
6503  snprintf(exten, sizeof(exten), "%d", space);
6505  remove_exten_if_exist(context, exten, 1);
6506 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
static void remove_exten_if_exist(const char *context, const char *exten, int priority)
Definition: features.c:6427
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define PRIORITY_HINT
Definition: pbx.h:53
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void dial_features_destroy ( void *  data)
static

Definition at line 744 of file features.c.

References ast_free.

745 {
746  struct ast_dial_features *df = data;
747  if (df) {
748  ast_free(df);
749  }
750 }
#define ast_free(a)
Definition: astmm.h:97
static void* dial_features_duplicate ( void *  data)
static

Definition at line 731 of file features.c.

References ast_calloc.

732 {
733  struct ast_dial_features *df = data, *df_copy;
734 
735  if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
736  return NULL;
737  }
738 
739  memcpy(df_copy, df, sizeof(*df));
740 
741  return df_copy;
742 }
#define ast_calloc(a, b)
Definition: astmm.h:82
static int dialplan_usage_add_parkinglot ( struct parking_dp_map usage_map,
struct ast_parkinglot lot,
int  complain 
)
static

Definition at line 6351 of file features.c.

References AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, build_dialplan_useage_context(), ast_parkinglot::cfg, parking_dp_context::context, dialplan_usage_add_parkinglot_data(), and parkinglot_cfg::parking_con.

Referenced by build_dialplan_useage_map().

6352 {
6353  struct parking_dp_context *cur_ctx;
6354  struct parking_dp_context *new_ctx;
6355  int cmp;
6356 
6357  AST_LIST_TRAVERSE_SAFE_BEGIN(usage_map, cur_ctx, node) {
6358  cmp = strcmp(lot->cfg.parking_con, cur_ctx->context);
6359  if (cmp > 0) {
6360  /* The parking lot context goes after this node. */
6361  continue;
6362  }
6363  if (cmp == 0) {
6364  /* This is the node we will add parking lot spaces to the map. */
6365  return dialplan_usage_add_parkinglot_data(cur_ctx, lot, complain);
6366  }
6367  /* The new parking lot context goes before this node. */
6368  new_ctx = build_dialplan_useage_context(lot);
6369  if (!new_ctx) {
6370  return -1;
6371  }
6373  return 0;
6374  }
6376 
6377  /* New parking lot context goes on the end. */
6378  new_ctx = build_dialplan_useage_context(lot);
6379  if (!new_ctx) {
6380  return -1;
6381  }
6382  AST_LIST_INSERT_TAIL(usage_map, new_ctx, node);
6383  return 0;
6384 }
static struct parking_dp_context * build_dialplan_useage_context(struct ast_parkinglot *lot)
Definition: features.c:6324
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
struct parking_dp_context::@269 node
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
struct parkinglot_cfg cfg
Definition: features.c:560
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:584
static int dialplan_usage_add_parkinglot_data(struct parking_dp_context *ctx_node, struct ast_parkinglot *lot, int complain)
Definition: features.c:6297
static int dialplan_usage_add_parkinglot_data ( struct parking_dp_context ctx_node,
struct ast_parkinglot lot,
int  complain 
)
static

Definition at line 6297 of file features.c.

References parking_dp_context::access_extens, ast_parkinglot::cfg, parking_dp_context::hints, parkinglot_cfg::parkaddhints, parkinglot_cfg::parkext, parkinglot_cfg::parkext_exclusive, parkinglot_cfg::parking_start, parkinglot_cfg::parking_stop, parking_dp_context::spaces, usage_context_add_ramp(), and usage_context_add_spaces().

Referenced by build_dialplan_useage_context(), and dialplan_usage_add_parkinglot().

6298 {
6299  if (usage_context_add_ramp(&ctx_node->access_extens, lot->cfg.parkext,
6300  lot->cfg.parkext_exclusive, lot, complain)) {
6301  return -1;
6302  }
6303  if (usage_context_add_spaces(&ctx_node->spaces, lot->cfg.parking_start,
6304  lot->cfg.parking_stop, lot, complain)) {
6305  return -1;
6306  }
6307  if (lot->cfg.parkaddhints
6308  && usage_context_add_spaces(&ctx_node->hints, lot->cfg.parking_start,
6309  lot->cfg.parking_stop, lot, 0)) {
6310  return -1;
6311  }
6312  return 0;
6313 }
int parking_stop
Definition: features.c:501
unsigned int parkaddhints
Definition: features.c:550
struct parking_dp_space_map hints
Definition: features.c:458
unsigned int parkext_exclusive
Definition: features.c:548
int parking_start
Definition: features.c:499
static int usage_context_add_ramp(struct parking_dp_ramp_map *ramp_map, const char *exten, int exclusive, struct ast_parkinglot *lot, int complain)
Definition: features.c:6113
struct parking_dp_ramp_map access_extens
Definition: features.c:454
struct parkinglot_cfg cfg
Definition: features.c:560
char parkext[AST_MAX_EXTENSION]
Definition: features.c:495
static int usage_context_add_spaces(struct parking_dp_space_map *space_map, int start, int stop, struct ast_parkinglot *lot, int complain)
Definition: features.c:6194
struct parking_dp_space_map spaces
Definition: features.c:456
static int do_bridge_masquerade ( struct ast_channel chan,
struct ast_channel tmpchan 
)
static

Actual bridge.

Parameters
chan
tmpchanStop hold music, lock both channels, masq channels, after bridge return channel to next priority.
Return values
0on success.
-1on error.

Definition at line 6933 of file features.c.

References ast_channel::_state, ast_channel_lock_both, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_moh_stop(), ast_setstate(), ast_strdupa, context, ast_channel::context, feature_group_exten::exten, ast_channel::exten, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.

Referenced by action_bridge(), and bridge_exec().

6934 {
6935  const char *context;
6936  const char *exten;
6937  int priority;
6938 
6939  ast_moh_stop(chan);
6940  ast_channel_lock_both(chan, tmpchan);
6941  context = ast_strdupa(chan->context);
6942  exten = ast_strdupa(chan->exten);
6943  priority = chan->priority;
6944  ast_setstate(tmpchan, chan->_state);
6945  tmpchan->readformat = chan->readformat;
6946  tmpchan->writeformat = chan->writeformat;
6947  ast_channel_unlock(chan);
6948  ast_channel_unlock(tmpchan);
6949 
6950  /* Masquerade setup and execution must be done without any channel locks held */
6951  if (ast_channel_masquerade(tmpchan, chan)) {
6952  return -1;
6953  }
6954  ast_do_masquerade(tmpchan);
6955 
6956  /* when returning from bridge, the channel will continue at the next priority */
6957  ast_explicit_goto(tmpchan, context, exten, priority + 1);
6958 
6959  return 0;
6960 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
int priority
Definition: channel.h:841
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
format_t writeformat
Definition: channel.h:854
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8708
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
enum ast_channel_state _state
Definition: channel.h:839
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2473
format_t readformat
Definition: channel.h:853
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int ast_do_masquerade(struct ast_channel *chan)
Start masquerading a channel.
Definition: channel.c:6546
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static void* do_parking_thread ( void *  ignore)
static

Take care of parked calls and unpark them if needed.

Parameters
ignoreunused var.

Start inf loop, lock parking lot, check if any parked channels have gone above timeout if so, remove channel from parking lot and return it to the extension that parked it. Check if parked channel decided to hangup, wait until next FD via select().

Definition at line 4984 of file features.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_free, ast_poll, manage_parkinglot(), and parkinglots.

Referenced by ast_features_init().

4985 {
4986  struct pollfd *pfds = NULL, *new_pfds = NULL;
4987  int nfds = 0, new_nfds = 0;
4988 
4989  for (;;) {
4990  struct ao2_iterator iter;
4991  struct ast_parkinglot *curlot;
4992  int ms = -1; /* poll2 timeout, uninitialized */
4993 
4994  iter = ao2_iterator_init(parkinglots, 0);
4995  while ((curlot = ao2_iterator_next(&iter))) {
4996  manage_parkinglot(curlot, pfds, nfds, &new_pfds, &new_nfds, &ms);
4997  ao2_ref(curlot, -1);
4998  }
4999  ao2_iterator_destroy(&iter);
5000 
5001  /* Recycle */
5002  ast_free(pfds);
5003  pfds = new_pfds;
5004  nfds = new_nfds;
5005  new_pfds = NULL;
5006  new_nfds = 0;
5007 
5008  /* Wait for something to happen */
5009  ast_poll(pfds, nfds, ms);
5010  pthread_testcancel();
5011  }
5012  /* If this WERE reached, we'd need to free(pfds) */
5013  return NULL; /* Never reached */
5014 }
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static void manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
Run management on parkinglots, called once per parkinglot.
Definition: features.c:4940
Structure for parking lots which are put in a container.
Definition: features.c:556
#define ast_free(a)
Definition: astmm.h:97
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
static int feature_check ( struct ast_channel chan,
struct ast_flags features,
char *  code 
)
static

Check if a feature exists.

Definition at line 3440 of file features.c.

References ast_channel_lock, ast_channel_unlock, ast_strdupa, FEATURE_INTERPRET_CHECK, feature_interpret_helper(), pbx_builtin_getvar_helper(), and S_OR.

Referenced by ast_bridge_call().

3440  {
3441  char *chan_dynamic_features;
3442  ast_channel_lock(chan);
3443  chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
3444  ast_channel_unlock(chan);
3445 
3446  return feature_interpret_helper(chan, NULL, NULL, code, 0, chan_dynamic_features, features, FEATURE_INTERPRET_CHECK, NULL);
3447 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#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
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
static int feature_exec_app ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
const char *  code,
int  sense,
void *  data 
)
static

exec an app by feature

Parameters
chan,peer,config,code,sense,dataFind a feature, determine which channel activated
Return values
AST_FEATURE_RETURN_NO_HANGUP_PEER
-1error.
-2when an application cannot be found.
Todo:
XXX should probably return res

Definition at line 3179 of file features.c.

References app, ast_call_feature::app, ast_call_feature::app_args, ast_app_exec_macro(), ast_app_exec_sub(), ast_autoservice_ignore(), ast_autoservice_start(), ast_autoservice_stop(), AST_FEATURE_FLAG_BYCALLEE, AST_FEATURE_FLAG_BYCALLER, AST_FEATURE_FLAG_ONSELF, AST_FEATURE_RETURN_KEEPTRYING, AST_FEATURE_RETURN_SUCCESS, AST_FEATURE_RETURN_SUCCESSBREAK, AST_FRAME_DTMF_END, ast_log(), ast_moh_start(), ast_moh_stop(), ast_strlen_zero(), ast_test_flag, FEATURE_SENSE_CHAN, LOG_NOTICE, LOG_WARNING, ast_call_feature::moh_class, ast_channel::name, pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), and ast_call_feature::sname.

Referenced by process_applicationmap_line().

3180 {
3181  struct ast_app *app;
3182  struct ast_call_feature *feature = data;
3183  struct ast_channel *work, *idle;
3184  int res;
3185 
3186  if (!feature) { /* shouldn't ever happen! */
3187  ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
3188  return -1;
3189  }
3190 
3191  if (sense == FEATURE_SENSE_CHAN) {
3194  if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
3195  work = chan;
3196  idle = peer;
3197  } else {
3198  work = peer;
3199  idle = chan;
3200  }
3201  } else {
3204  if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
3205  work = peer;
3206  idle = chan;
3207  } else {
3208  work = chan;
3209  idle = peer;
3210  }
3211  }
3212 
3213  if (!(app = pbx_findapp(feature->app))) {
3214  ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
3215  return -2;
3216  }
3217 
3218  ast_autoservice_start(idle);
3220 
3221  pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", idle->name);
3222  pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", work->name);
3223  pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
3224  pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
3225 
3226  if (!ast_strlen_zero(feature->moh_class))
3227  ast_moh_start(idle, feature->moh_class, NULL);
3228 
3229  if (!strcasecmp("Gosub", feature->app)) {
3230  res = ast_app_exec_sub(NULL, work, feature->app_args, 0);
3231  } else if (!strcasecmp("Macro", feature->app)) {
3232  res = ast_app_exec_macro(NULL, work, feature->app_args);
3233  } else {
3234  res = pbx_exec(work, app, feature->app_args);
3235  }
3236 
3237  if (!ast_strlen_zero(feature->moh_class))
3238  ast_moh_stop(idle);
3239 
3240  ast_autoservice_stop(idle);
3241 
3242  if (res) {
3244  }
3245  return AST_FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
3246 }
Main Channel structure associated with a channel.
Definition: channel.h:742
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
#define AST_FEATURE_RETURN_SUCCESSBREAK
Definition: features.h:40
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition: app.c:343
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
char app[FEATURE_APP_LEN]
Definition: features.h:73
static const char app[]
Definition: app_adsiprog.c:49
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char app_args[FEATURE_APP_ARGS_LEN]
Definition: features.h:74
#define AST_FEATURE_RETURN_KEEPTRYING
Definition: features.h:46
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
char moh_class[FEATURE_MOH_LEN]
Definition: features.h:75
const ast_string_field name
Definition: channel.h:787
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
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
int ast_autoservice_ignore(struct ast_channel *chan, enum ast_frame_type ftype)
Ignore certain frame types.
Definition: autoservice.c:307
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
ast_app: A registered application
Definition: pbx.c:971
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
int ast_app_exec_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *macro_args)
Run a macro on a channel, placing an optional second channel into autoservice.
Definition: app.c:254
#define FEATURE_SENSE_CHAN
Definition: features.h:49
static int feature_interpret ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config,
const char *  code,
int  sense 
)
static

Check the dynamic features.

Parameters
chan,peer,config,code,sense
Return values
reson success.
-1on failure.

Definition at line 3403 of file features.c.

References ast_channel_lock, ast_channel_unlock, ast_copy_flags, ast_debug, AST_FLAGS_ALL, ast_strdupa, FEATURE_INTERPRET_DO, feature_interpret_helper(), FEATURE_SENSE_CHAN, ast_bridge_config::features_callee, ast_bridge_config::features_caller, ast_flags::flags, ast_channel::name, pbx_builtin_getvar_helper(), and S_OR.

Referenced by ast_bridge_call().

3403  {
3404 
3405  char dynamic_features_buf[128];
3406  const char *peer_dynamic_features, *chan_dynamic_features;
3407  struct ast_flags features;
3408  struct ast_call_feature feature;
3409  if (sense == FEATURE_SENSE_CHAN) {
3410  /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
3411  ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
3412  }
3413  else {
3414  /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
3415  ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
3416  }
3417 
3418  ast_channel_lock(peer);
3419  peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
3420  ast_channel_unlock(peer);
3421 
3422  ast_channel_lock(chan);
3423  chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
3424  ast_channel_unlock(chan);
3425 
3426  snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
3427 
3428  ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%u, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
3429 
3430  return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, FEATURE_INTERPRET_DO, &feature);
3431 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
struct ast_flags features_callee
Definition: channel.h:976
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
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
const ast_string_field name
Definition: channel.h:787
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define AST_FLAGS_ALL
Definition: utils.h:196
Structure used to handle boolean flags.
Definition: utils.h:200
#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
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
#define FEATURE_SENSE_CHAN
Definition: features.h:49
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 
)
static

Helper function for feature_interpret and ast_feature_detect.

Parameters
chan,peer,config,code,sense,dynamic_features_buf,features,operation,featureLock features list, browse for code, unlock list If a feature is found and the operation variable is set, that feature's operation is executed. The first feature found is copied to the feature parameter.
Return values
reson success.
-1on failure.

Definition at line 3286 of file features.c.

References ast_debug, AST_FEATURE_RETURN_KEEPTRYING, AST_FEATURE_RETURN_PASSDIGITS, AST_FEATURE_RETURN_STOREDIGITS, AST_FEATURE_RETURN_SUCCESS, AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_rwlock_rdlock, ast_rwlock_unlock, ast_strlen_zero(), ast_test_flag, ast_verb, ast_call_feature::exten, feature_group_exten::exten, feature_group_exten::feature, FEATURE_INTERPRET_CHECK, FEATURE_INTERPRET_DO, ast_call_feature::feature_mask, feature_group::features, FEATURES_COUNT, features_lock, find_dynamic_feature(), find_group(), ast_call_feature::fname, ast_call_feature::operation, ast_call_feature::sname, and strsep().

Referenced by ast_feature_detect(), feature_check(), and feature_interpret().

3289 {
3290  int x;
3291  struct feature_group *fg = NULL;
3292  struct feature_group_exten *fge;
3293  struct ast_call_feature *tmpfeature;
3294  char *tmp, *tok;
3296  int feature_detected = 0;
3297 
3298  if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
3299  return -1; /* can not run feature operation */
3300  }
3301 
3303  for (x = 0; x < FEATURES_COUNT; x++) {
3304  if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
3306  /* Feature is up for consideration */
3307  if (!strcmp(builtin_features[x].exten, code)) {
3308  ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
3310  res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
3311  } else if (operation == FEATURE_INTERPRET_DO) {
3312  res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
3313  }
3314  if (feature) {
3315  memcpy(feature, &builtin_features[x], sizeof(*feature));
3316  }
3317  feature_detected = 1;
3318  break;
3319  } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
3320  if (res == AST_FEATURE_RETURN_PASSDIGITS) {
3322  }
3323  }
3324  }
3325  }
3327 
3328  if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
3329  return res;
3330  }
3331 
3332  tmp = dynamic_features_buf;
3333 
3334  while ((tok = strsep(&tmp, "#"))) {
3336 
3337  fg = find_group(tok);
3338 
3339  if (fg) {
3340  AST_LIST_TRAVERSE(&fg->features, fge, entry) {
3341  if (!strcmp(fge->exten, code)) {
3342  if (operation) {
3343  res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
3344  }
3345  if (feature) {
3346  memcpy(feature, fge->feature, sizeof(*feature));
3347  }
3348  if (res != AST_FEATURE_RETURN_KEEPTRYING) {
3350  break;
3351  }
3353  } else if (!strncmp(fge->exten, code, strlen(code))) {
3355  }
3356  }
3357  if (fge) {
3358  break;
3359  }
3360  }
3361 
3363 
3365 
3366  if (!(tmpfeature = find_dynamic_feature(tok))) {
3368  continue;
3369  }
3370 
3371  /* Feature is up for consideration */
3372  if (!strcmp(tmpfeature->exten, code)) {
3373  ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
3375  res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
3376  } else if (operation == FEATURE_INTERPRET_DO) {
3377  res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
3378  }
3379  if (feature) {
3380  memcpy(feature, tmpfeature, sizeof(*feature));
3381  }
3382  if (res != AST_FEATURE_RETURN_KEEPTRYING) {
3384  break;
3385  }
3387  } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
3389 
3391  }
3392 
3393  return res;
3394 }
char exten[FEATURE_MAX_LEN]
Definition: features.h:69
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
static ast_rwlock_t features_lock
Definition: features.c:2979
static struct ast_call_feature * find_dynamic_feature(const char *name)
find a call feature by name
Definition: features.c:3100
char * strsep(char **str, const char *delims)
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct feature_group::@266 features
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static struct feature_group * find_group(const char *name)
Find a group by name.
Definition: features.c:3138
#define ast_rwlock_unlock(a)
Definition: lock.h:200
#define ast_verb(level,...)
Definition: logger.h:243
#define FEATURES_COUNT
Definition: features.c:2977
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char * fname
Definition: features.h:67
#define AST_FEATURE_RETURN_PASSDIGITS
Definition: features.h:43
struct ast_call_feature * feature
Definition: features.c:400
#define AST_FEATURE_RETURN_KEEPTRYING
Definition: features.h:46
const ast_string_field exten
Definition: features.c:399
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_FEATURE_RETURN_STOREDIGITS
Definition: features.h:44
char sname[FEATURE_SNAME_LEN]
Definition: features.h:68
static struct ast_call_feature builtin_features[]
Definition: features.c:2981
ast_feature_operation operation
Definition: features.h:71
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
static struct ast_channel * feature_request_and_dial ( struct ast_channel caller,
const char *  caller_name,
struct ast_channel requestor,
struct ast_channel transferee,
const char *  type,
format_t  format,
void *  data,
int  timeout,
int *  outstate,
const char *  language 
)
static

Definition at line 3544 of file features.c.

References ast_channel::_state, ast_alloca, ast_autoservice_start(), ast_autoservice_stop(), ast_call(), ast_call_forward(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_channel_connected_line_macro(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_redirecting_macro(), ast_channel_set_connected_line(), ast_channel_unlock, ast_check_hangup(), ast_connected_line_copy_from_caller(), ast_connected_line_parse_data(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_frisolate(), ast_hangup(), ast_indicate(), ast_indicate_data(), ast_is_deferrable_frame(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_party_connected_line_free(), ast_party_connected_line_set_init(), ast_poll_channel_add(), ast_poll_channel_del(), ast_queue_frame_head(), ast_read(), ast_request(), ast_rwlock_rdlock, ast_rwlock_unlock, AST_STATE_UP, ast_string_field_set, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, ast_waitfor_n(), ast_write(), ast_channel::call_forward, ast_channel::caller, ast_channel::connected, ast_frame::data, ast_frame::datalen, ast_call_feature::exten, ast_channel::exten, f, FEATURES_COUNT, features_lock, ast_frame::frametype, ast_channel::hangupcause, ast_frame_subclass::integer, LOG_NOTICE, ast_channel::name, pbx_builtin_setvar_helper(), ast_frame::ptr, state, and ast_frame::subclass.

Referenced by builtin_atxfer().

3548 {
3549  int state = 0;
3550  int cause = 0;
3551  int to;
3552  int caller_hungup;
3553  int transferee_hungup;
3554  struct ast_channel *chan;
3555  struct ast_channel *monitor_chans[3];
3556  struct ast_channel *active_channel;
3557  int res;
3558  int ready = 0;
3559  struct timeval started;
3560  int x, len = 0;
3561  char *disconnect_code = NULL, *dialed_code = NULL;
3562  struct ast_frame *f;
3563  AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
3564 
3565  caller_hungup = ast_check_hangup(caller);
3566 
3567  if (!(chan = ast_request(type, format, requestor, data, &cause))) {
3568  ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
3569  switch (cause) {
3570  case AST_CAUSE_BUSY:
3571  state = AST_CONTROL_BUSY;
3572  break;
3573  case AST_CAUSE_CONGESTION:
3574  state = AST_CONTROL_CONGESTION;
3575  break;
3576  default:
3577  state = 0;
3578  break;
3579  }
3580  goto done;
3581  }
3582 
3584  ast_channel_inherit_variables(caller, chan);
3585  pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
3586 
3587  ast_channel_lock(chan);
3588  ast_connected_line_copy_from_caller(&chan->connected, &requestor->caller);
3589  ast_channel_unlock(chan);
3590 
3591  if (ast_call(chan, data, timeout)) {
3592  ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
3593  switch (chan->hangupcause) {
3594  case AST_CAUSE_BUSY:
3595  state = AST_CONTROL_BUSY;
3596  break;
3597  case AST_CAUSE_CONGESTION:
3598  state = AST_CONTROL_CONGESTION;
3599  break;
3600  default:
3601  state = 0;
3602  break;
3603  }
3604  goto done;
3605  }
3606 
3607  /* support dialing of the featuremap disconnect code while performing an attended tranfer */
3609  for (x = 0; x < FEATURES_COUNT; x++) {
3610  if (strcasecmp(builtin_features[x].sname, "disconnect"))
3611  continue;
3612 
3613  disconnect_code = builtin_features[x].exten;
3614  len = strlen(disconnect_code) + 1;
3615  dialed_code = ast_alloca(len);
3616  memset(dialed_code, 0, len);
3617  break;
3618  }
3620  x = 0;
3621  started = ast_tvnow();
3622  to = timeout;
3623  AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
3624 
3625  ast_poll_channel_add(caller, chan);
3626 
3627  transferee_hungup = 0;
3628  while (!ast_check_hangup(transferee) && (chan->_state != AST_STATE_UP)) {
3629  int num_chans = 0;
3630 
3631  monitor_chans[num_chans++] = transferee;
3632  monitor_chans[num_chans++] = chan;
3633  if (!caller_hungup) {
3634  if (ast_check_hangup(caller)) {
3635  caller_hungup = 1;
3636 
3637 #if defined(ATXFER_NULL_TECH)
3638  /* Change caller's name to ensure that it will remain unique. */
3639  set_new_chan_name(caller);
3640 
3641  /*
3642  * Get rid of caller's physical technology so it is free for
3643  * other calls.
3644  */
3645  set_kill_chan_tech(caller);
3646 #endif /* defined(ATXFER_NULL_TECH) */
3647  } else {
3648  /* caller is not hungup so monitor it. */
3649  monitor_chans[num_chans++] = caller;
3650  }
3651  }
3652 
3653  /* see if the timeout has been violated */
3654  if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
3655  state = AST_CONTROL_UNHOLD;
3656  ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", chan->name);
3657  break; /*doh! timeout*/
3658  }
3659 
3660  active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
3661  if (!active_channel)
3662  continue;
3663 
3664  f = NULL;
3665  if (transferee == active_channel) {
3666  struct ast_frame *dup_f;
3667 
3668  f = ast_read(transferee);
3669  if (f == NULL) { /*doh! where'd he go?*/
3670  transferee_hungup = 1;
3671  state = 0;
3672  break;
3673  }
3674  if (ast_is_deferrable_frame(f)) {
3675  dup_f = ast_frisolate(f);
3676  if (dup_f) {
3677  if (dup_f == f) {
3678  f = NULL;
3679  }
3680  AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
3681  }
3682  }
3683  } else if (chan == active_channel) {
3684  if (!ast_strlen_zero(chan->call_forward)) {
3685  state = 0;
3686  ast_autoservice_start(transferee);
3687  chan = ast_call_forward(caller, chan, NULL, format, NULL, &state);
3688  ast_autoservice_stop(transferee);
3689  if (!chan) {
3690  break;
3691  }
3692  continue;
3693  }
3694  f = ast_read(chan);
3695  if (f == NULL) { /*doh! where'd he go?*/
3696  switch (chan->hangupcause) {
3697  case AST_CAUSE_BUSY:
3698  state = AST_CONTROL_BUSY;
3699  break;
3700  case AST_CAUSE_CONGESTION:
3701  state = AST_CONTROL_CONGESTION;
3702  break;
3703  default:
3704  state = 0;
3705  break;
3706  }
3707  break;
3708  }
3709 
3710  if (f->frametype == AST_FRAME_CONTROL) {
3711  if (f->subclass.integer == AST_CONTROL_RINGING) {
3712  ast_verb(3, "%s is ringing\n", chan->name);
3714  } else if (f->subclass.integer == AST_CONTROL_BUSY) {
3715  state = f->subclass.integer;
3716  ast_verb(3, "%s is busy\n", chan->name);
3717  ast_indicate(caller, AST_CONTROL_BUSY);
3718  ast_frfree(f);
3719  break;
3720  } else if (f->subclass.integer == AST_CONTROL_INCOMPLETE) {
3721  ast_verb(3, "%s dialed incomplete extension %s; ignoring\n", chan->name, chan->exten);
3722  } else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
3723  state = f->subclass.integer;
3724  ast_verb(3, "%s is congested\n", chan->name);
3726  ast_frfree(f);
3727  break;
3728  } else if (f->subclass.integer == AST_CONTROL_ANSWER) {
3729  /* This is what we are hoping for */
3730  state = f->subclass.integer;
3731  ast_frfree(f);
3732  ready=1;
3733  break;
3734  } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
3735  if (caller_hungup) {
3737 
3738  /* Just save it for the transfer. */
3739  ast_party_connected_line_set_init(&connected, &caller->connected);
3741  &connected);
3742  if (!res) {
3743  ast_channel_set_connected_line(caller, &connected, NULL);
3744  }
3746  } else {
3747  ast_autoservice_start(transferee);
3748  if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
3750  f->data.ptr, f->datalen);
3751  }
3752  ast_autoservice_stop(transferee);
3753  }
3754  } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
3755  if (!caller_hungup) {
3756  ast_autoservice_start(transferee);
3757  if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
3759  f->data.ptr, f->datalen);
3760  }
3761  ast_autoservice_stop(transferee);
3762  }
3763  } else if (f->subclass.integer != -1
3766  ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
3767  }
3768  /* else who cares */
3769  } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
3770  ast_write(caller, f);
3771  }
3772  } else if (caller == active_channel) {
3773  f = ast_read(caller);
3774  if (f) {
3775  if (f->frametype == AST_FRAME_DTMF) {
3776  dialed_code[x++] = f->subclass.integer;
3777  dialed_code[x] = '\0';
3778  if (strlen(dialed_code) == len) {
3779  x = 0;
3780  } else if (x && strncmp(dialed_code, disconnect_code, x)) {
3781  x = 0;
3782  dialed_code[x] = '\0';
3783  }
3784  if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
3785  /* Caller Canceled the call */
3786  state = AST_CONTROL_UNHOLD;
3787  ast_frfree(f);
3788  break;
3789  }
3790  } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
3791  ast_write(chan, f);
3792  }
3793  }
3794  }
3795  if (f)
3796  ast_frfree(f);
3797  } /* end while */
3798 
3799  ast_poll_channel_del(caller, chan);
3800 
3801  /*
3802  * We need to free all the deferred frames, but we only need to
3803  * queue the deferred frames if no hangup was received.
3804  */
3805  ast_channel_lock(transferee);
3806  transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
3807  while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
3808  if (!transferee_hungup) {
3809  ast_queue_frame_head(transferee, f);
3810  }
3811  ast_frfree(f);
3812  }
3813  ast_channel_unlock(transferee);
3814 
3815 done:
3816  ast_indicate(caller, -1);
3817  if (chan && (ready || chan->_state == AST_STATE_UP)) {
3818  state = AST_CONTROL_ANSWER;
3819  } else if (chan) {
3820  ast_hangup(chan);
3821  chan = NULL;
3822  }
3823 
3824  if (outstate)
3825  *outstate = state;
3826 
3827  return chan;
3828 }
char exten[FEATURE_MAX_LEN]
Definition: features.h:69
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
Definition: channel.c:3534
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
enum sip_cc_notify_state state
Definition: chan_sip.c:842
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
static ast_rwlock_t features_lock
Definition: features.c:2979
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1)
Definition: channel.c:2665
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
Definition: channel.c:2329
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
void * ptr
Definition: frame.h:160
#define AST_FRAME_DTMF
Definition: frame.h:128
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
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
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
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2353
struct ast_frame * ast_frisolate(struct ast_frame *fr)
Makes a frame independent of any static storage.
Definition: frame.c:391
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
#define ast_rwlock_unlock(a)
Definition: lock.h:200
#define ast_verb(level,...)
Definition: logger.h:243
#define FEATURES_COUNT
Definition: features.c:2977
struct ast_channel * ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, format_t format, struct outgoing_helper *oh, int *outstate)
Forwards a call to a new channel specified by the original channel&#39;s call_forward str...
Definition: channel.c:5386
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int datalen
Definition: frame.h:148
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:224
int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
Parse connected line indication frame data.
Definition: channel.c:8886
const ast_string_field call_forward
Definition: channel.h:787
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_channel_state _state
Definition: channel.h:839
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
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition: channel.c:6241
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
int ast_call(struct ast_channel *chan, char *addr, int timeout)
Make a call.
Definition: channel.c:5761
static struct ast_call_feature builtin_features[]
Definition: features.c:2981
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
static const char type[]
Definition: chan_nbs.c:57
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
void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1)
Definition: channel.c:2688
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:666
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
#define AST_CAUSE_BUSY
Definition: causes.h:148
int ast_is_deferrable_frame(const struct ast_frame *frame)
Should we keep this frame for later?
Definition: channel.c:1818
Data structure associated with a single frame of data.
Definition: frame.h:142
int hangupcause
Definition: channel.h:849
static int connected
Definition: cdr_pgsql.c:57
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to the head of a channel&#39;s frame queue.
Definition: channel.c:1563
struct ast_channel * ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *status)
Requests a channel.
Definition: channel.c:5695
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Set the connected line information in the Asterisk channel.
Definition: channel.c:8458
#define AST_CAUSE_CONGESTION
Definition: causes.h:152
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
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
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static void features_shutdown ( void  )
static

Definition at line 8314 of file features.c.

References ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), ast_context_destroy(), ast_devstate_prov_del(), ast_manager_unregister(), AST_TEST_UNREGISTER, ast_unregister_application(), parkcall, parking_thread, parkinglots, and registrar.

Referenced by ast_features_init().

8315 {
8317  ast_devstate_prov_del("Park");
8318  ast_manager_unregister("Bridge");
8319  ast_manager_unregister("Park");
8320  ast_manager_unregister("Parkinglots");
8321  ast_manager_unregister("ParkedCalls");
8325 #if defined(TEST_FRAMEWORK)
8326  AST_TEST_UNREGISTER(features_test);
8327 #endif /* defined(TEST_FRAMEWORK) */
8328 
8329  pthread_cancel(parking_thread);
8330  pthread_kill(parking_thread, SIGURG);
8331  pthread_join(parking_thread, NULL);
8333  ao2_ref(parkinglots, -1);
8334 }
static const char * parkedcall
Definition: features.c:419
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static struct ast_cli_entry cli_features[]
Definition: features.c:7165
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:389
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static pthread_t parking_thread
Definition: features.c:648
static char * app_bridge
Definition: features.c:7493
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
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 struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
static const char * parkcall
Definition: features.c:637
int ast_manager_unregister(char *action)
Unregister a registered manager command.
Definition: manager.c:5355
static int find_channel_by_group ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

< Potential pickup target

< Channel wanting to pickup call

Definition at line 7356 of file features.c.

References ast_can_pickup(), ast_channel_lock, ast_channel_unlock, ast_channel::callgroup, CMP_MATCH, CMP_STOP, ast_channel::data, and ast_channel::pickupgroup.

Referenced by ast_pickup_call().

7357 {
7358  struct ast_channel *target = obj;/*!< Potential pickup target */
7359  struct ast_channel *chan = data;/*!< Channel wanting to pickup call */
7360 
7361  ast_channel_lock(target);
7362  if (chan != target && (chan->pickupgroup & target->callgroup)
7363  && ast_can_pickup(target)) {
7364  /* Return with the channel still locked on purpose */
7365  return CMP_MATCH | CMP_STOP;
7366  }
7367  ast_channel_unlock(target);
7368 
7369  return 0;
7370 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
const char * data
Definition: channel.h:755
ast_group_t pickupgroup
Definition: channel.h:819
ast_group_t callgroup
Definition: channel.h:818
#define ast_channel_unlock(chan)
Definition: channel.h:2467
int ast_can_pickup(struct ast_channel *chan)
Test if a channel can be picked up.
Definition: features.c:7338
static struct ast_call_feature* find_dynamic_feature ( const char *  name)
static

find a call feature by name

Definition at line 3100 of file features.c.

References AST_RWLIST_TRAVERSE, ast_call_feature::feature_entry, and ast_call_feature::sname.

Referenced by feature_interpret_helper(), process_applicationmap_line(), process_config(), and set_config_flags().

3101 {
3102  struct ast_call_feature *tmp;
3103 
3105  if (!strcasecmp(tmp->sname, name)) {
3106  break;
3107  }
3108  }
3109 
3110  return tmp;
3111 }
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
static const char name[]
char sname[FEATURE_SNAME_LEN]
Definition: features.h:68
struct ast_call_feature::@170 feature_entry
static struct feature_group* find_group ( const char *  name)
static

Find a group by name.

Parameters
namefeature name
Return values
featuregroup on success.
NULLon failure.

Definition at line 3138 of file features.c.

References AST_LIST_TRAVERSE, and feature_group::gname.

Referenced by feature_interpret_helper().

3139 {
3140  struct feature_group *fg = NULL;
3141 
3143  if (!strcasecmp(fg->gname, name))
3144  break;
3145  }
3146 
3147  return fg;
3148 }
const ast_string_field gname
Definition: features.c:407
struct feature_group::@265 entry
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
static struct ast_parkinglot * find_parkinglot ( const char *  name)
static

Find parkinglot by name.

Definition at line 5017 of file features.c.

References ao2_find, ast_debug, ast_strlen_zero(), ast_parkinglot::name, parkinglot, and parkinglots.

Referenced by ast_masq_park_call_exten(), ast_park_call_exten(), build_parkinglot(), copy_parkinglot(), create_dynamic_parkinglot(), manager_park(), park_call_exec(), park_space_reserve(), parked_call_exec(), and xfer_park_call_helper().

5018 {
5019  struct ast_parkinglot *parkinglot;
5020 
5021  if (ast_strlen_zero(name)) {
5022  return NULL;
5023  }
5024 
5025  parkinglot = ao2_find(parkinglots, (void *) name, 0);
5026  if (parkinglot) {
5027  ast_debug(1, "Found Parking lot: %s\n", parkinglot->name);
5028  }
5029 
5030  return parkinglot;
5031 }
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Structure for parking lots which are put in a container.
Definition: features.c:556
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
static const char name[]
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
static const char* findparkinglotname ( struct ast_channel chan)
static

Find parking lot name from channel.

Note
Channel needs to be locked while the returned string is in use.

Definition at line 1082 of file features.c.

References ast_strlen_zero(), name, ast_channel::parkinglot, and pbx_builtin_getvar_helper().

Referenced by park_call_exec(), park_space_reserve(), parked_call_exec(), and xfer_park_call_helper().

1083 {
1084  const char *name;
1085 
1086  /* The channel variable overrides everything */
1087  name = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
1088  if (!name && !ast_strlen_zero(chan->parkinglot)) {
1089  /* Use the channel's parking lot. */
1090  name = chan->parkinglot;
1091  }
1092  return name;
1093 }
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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const ast_string_field parkinglot
Definition: channel.h:787
static const char name[]
static int finishup ( struct ast_channel chan)
static

Definition at line 1870 of file features.c.

References ast_autoservice_stop(), AST_CONTROL_UNHOLD, and ast_indicate().

Referenced by atxfer_fail_cleanup(), builtin_atxfer(), builtin_blindtransfer(), and xfer_park_call_helper().

1871 {
1873 
1874  return ast_autoservice_stop(chan);
1875 }
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
static struct ast_exten* get_parking_exten ( const char *  exten_str,
struct ast_channel chan,
const char *  context 
)
static

Definition at line 823 of file features.c.

References ast_debug, ast_get_extension_app(), E_MATCH, feature_group_exten::exten, parkcall, pbx_find_extension(), and pbx_find_info::stacklen.

Referenced by ast_masq_park_call_exten(), ast_park_call_exten(), ast_parking_ext_valid(), builtin_atxfer(), and builtin_blindtransfer().

824 {
825  struct ast_exten *exten;
826  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
827  const char *app_at_exten;
828 
829  ast_debug(4, "Checking if %s@%s is a parking exten\n", exten_str, context);
830  exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL,
831  E_MATCH);
832  if (!exten) {
833  return NULL;
834  }
835 
836  app_at_exten = ast_get_extension_app(exten);
837  if (!app_at_exten || strcasecmp(parkcall, app_at_exten)) {
838  return NULL;
839  }
840 
841  return exten;
842 }
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
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:11141
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int stacklen
Definition: extconf.h:234
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: pbx.c:3013
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static const char * parkcall
Definition: features.c:637
static char* handle_feature_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

CLI command to list configured features.

Parameters
e
cmd
a
Return values
CLI_SUCCESSon success.
NULLwhen tab completion is used.

Definition at line 6799 of file features.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), AST_CLI_YESNO, AST_LIST_TRAVERSE, ast_pickup_ext(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_rwlock_rdlock, ast_rwlock_unlock, ast_parkinglot::cfg, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_call_feature::default_exten, ast_parkinglot::disabled, ast_call_feature::exten, feature_group_exten::exten, ast_cli_args::fd, feature_group_exten::feature, feature_group::features, FEATURES_COUNT, features_lock, ast_call_feature::fname, feature_group::gname, HFS_FORMAT, parkinglot_cfg::mohclass, ast_parkinglot::name, parkinglot_cfg::parkext, parkinglot_cfg::parking_con, parkinglot_cfg::parking_start, parkinglot_cfg::parking_stop, parkinglots, parkinglot_cfg::parkingtime, ast_call_feature::sname, and ast_cli_entry::usage.

6800 {
6801  int i;
6802  struct ast_call_feature *feature;
6803  struct ao2_iterator iter;
6804  struct ast_parkinglot *curlot;
6805 #define HFS_FORMAT "%-25s %-7s %-7s\n"
6806 
6807  switch (cmd) {
6808 
6809  case CLI_INIT:
6810  e->command = "features show";
6811  e->usage =
6812  "Usage: features show\n"
6813  " Lists configured features\n";
6814  return NULL;
6815  case CLI_GENERATE:
6816  return NULL;
6817  }
6818 
6819  ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
6820  ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
6821 
6822  ast_cli(a->fd, HFS_FORMAT, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
6823 
6825  for (i = 0; i < FEATURES_COUNT; i++)
6828 
6829  ast_cli(a->fd, "\n");
6830  ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
6831  ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
6833  ast_cli(a->fd, "(none)\n");
6834  } else {
6836  AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
6837  ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
6838  }
6840  }
6841 
6842  ast_cli(a->fd, "\nFeature Groups:\n");
6843  ast_cli(a->fd, "---------------\n");
6845  ast_cli(a->fd, "(none)\n");
6846  } else {
6847  struct feature_group *fg;
6848  struct feature_group_exten *fge;
6849 
6852  ast_cli(a->fd, "===> Group: %s\n", fg->gname);
6853  AST_LIST_TRAVERSE(&fg->features, fge, entry) {
6854  ast_cli(a->fd, "===> --> %s (%s)\n", fge->feature->sname, fge->exten);
6855  }
6856  }
6858  }
6859 
6860  iter = ao2_iterator_init(parkinglots, 0);
6861  while ((curlot = ao2_iterator_next(&iter))) {
6862  ast_cli(a->fd, "\nCall parking (Parking lot: %s)\n", curlot->name);
6863  ast_cli(a->fd, "------------\n");
6864  ast_cli(a->fd,"%-22s: %s\n", "Parking extension", curlot->cfg.parkext);
6865  ast_cli(a->fd,"%-22s: %s\n", "Parking context", curlot->cfg.parking_con);
6866  ast_cli(a->fd,"%-22s: %d-%d\n", "Parked call extensions",
6867  curlot->cfg.parking_start, curlot->cfg.parking_stop);
6868  ast_cli(a->fd,"%-22s: %d ms\n", "Parkingtime", curlot->cfg.parkingtime);
6869  ast_cli(a->fd,"%-22s: %s\n", "MusicOnHold class", curlot->cfg.mohclass);
6870  ast_cli(a->fd,"%-22s: %s\n", "Enabled", AST_CLI_YESNO(!curlot->disabled));
6871  ast_cli(a->fd,"\n");
6872  ao2_ref(curlot, -1);
6873  }
6874  ao2_iterator_destroy(&iter);
6875 
6876  return CLI_SUCCESS;
6877 }
int parking_stop
Definition: features.c:501
char exten[FEATURE_MAX_LEN]
Definition: features.h:69
const ast_string_field gname
Definition: features.c:407
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
static ast_rwlock_t features_lock
Definition: features.c:2979
struct feature_group::@266 features
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:146
#define HFS_FORMAT
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define ast_rwlock_unlock(a)
Definition: lock.h:200
#define FEATURES_COUNT
Definition: features.c:2977
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
const int fd
Definition: cli.h:153
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * fname
Definition: features.h:67
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct ast_call_feature * feature
Definition: features.c:400
int parking_start
Definition: features.c:499
const ast_string_field exten
Definition: features.c:399
unsigned int disabled
Definition: features.c:568
Structure for parking lots which are put in a container.
Definition: features.c:556
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
struct parkinglot_cfg cfg
Definition: features.c:560
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char default_exten[FEATURE_MAX_LEN]
Definition: features.h:70
char * command
Definition: cli.h:180
char parkext[AST_MAX_EXTENSION]
Definition: features.c:495
char sname[FEATURE_SNAME_LEN]
Definition: features.h:68
static struct ast_call_feature builtin_features[]
Definition: features.c:2981
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
struct feature_group_exten::@264 entry
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
#define AST_CLI_YESNO(x)
return Yes or No depending on the argument. This is used in many places in CLI command, having a function to generate this helps maintaining a consistent output (and possibly emitting the output in other languages, at some point).
Definition: cli.h:65
const char * ast_pickup_ext(void)
Determine system call pickup extension.
Definition: features.c:849
char mohclass[MAX_MUSICCLASS]
Definition: features.c:493
static char* handle_features_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 6905 of file features.c.

References ast_features_reload(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

6906 {
6907  switch (cmd) {
6908  case CLI_INIT:
6909  e->command = "features reload";
6910  e->usage =
6911  "Usage: features reload\n"
6912  " Reloads configured call features from features.conf\n";
6913  return NULL;
6914  case CLI_GENERATE:
6915  return NULL;
6916  }
6918 
6919  return CLI_SUCCESS;
6920 }
Definition: cli.h:146
int ast_features_reload(void)
Reload call features from features.conf.
Definition: features.c:6879
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static char* handle_parkedcalls ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

CLI command to list parked calls.

Parameters
e
cmd
aCheck right usage, lock parking lot, display parked calls, unlock parking lot list.
Return values
CLI_SUCCESSon success.
CLI_SHOWUSAGEon incorrect number of arguments.
NULLwhen tab completion is used.

Definition at line 7109 of file features.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, parkeduser::chan, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, parkeduser::context, default_parkinglot, ESS, parkeduser::exten, ast_cli_args::fd, ast_parkinglot::name, ast_channel::name, parkeduser::parkingexten, parkinglots, ast_parkinglot::parkings, parkeduser::parkingtime, parkeduser::priority, parkeduser::start, and ast_cli_entry::usage.

7110 {
7111  struct parkeduser *cur;
7112  int numparked = 0;
7113  struct ao2_iterator iter;
7114  struct ast_parkinglot *curlot;
7115 
7116  switch (cmd) {
7117  case CLI_INIT:
7118  e->command = "parkedcalls show";
7119  e->usage =
7120  "Usage: parkedcalls show\n"
7121  " List currently parked calls\n";
7122  return NULL;
7123  case CLI_GENERATE:
7124  return NULL;
7125  }
7126 
7127  if (a->argc > e->args)
7128  return CLI_SHOWUSAGE;
7129 
7130  ast_cli(a->fd, "%-10s %-25s (%-15s %-12s %4s) %s\n", "Num", "Channel",
7131  "Context", "Extension", "Pri", "Timeout");
7132 
7133  iter = ao2_iterator_init(parkinglots, 0);
7134  while ((curlot = ao2_iterator_next(&iter))) {
7135  int lotparked = 0;
7136 
7137  /* subtract ref for iterator and for configured parking lot */
7138  ast_cli(a->fd, "*** Parking lot: %s (%d)\n", curlot->name,
7139  ao2_ref(curlot, 0) - 2 - (curlot == default_parkinglot));
7140 
7141  AST_LIST_LOCK(&curlot->parkings);
7142  AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
7143  ast_cli(a->fd, "%-10.10s %-25s (%-15s %-12s %4d) %6lds\n",
7144  cur->parkingexten, cur->chan->name, cur->context, cur->exten,
7145  cur->priority,
7146  (long) (cur->start.tv_sec + (cur->parkingtime / 1000) - time(NULL)));
7147  ++lotparked;
7148  }
7149  AST_LIST_UNLOCK(&curlot->parkings);
7150  if (lotparked) {
7151  numparked += lotparked;
7152  ast_cli(a->fd, " %d parked call%s in parking lot %s\n", lotparked,
7153  ESS(lotparked), curlot->name);
7154  }
7155 
7156  ao2_ref(curlot, -1);
7157  }
7158  ao2_iterator_destroy(&iter);
7159 
7160  ast_cli(a->fd, "---\n%d parked call%s in total.\n", numparked, ESS(numparked));
7161 
7162  return CLI_SUCCESS;
7163 }
char context[AST_MAX_CONTEXT]
Definition: features.c:475
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char exten[AST_MAX_EXTENSION]
Definition: features.c:476
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static struct ast_parkinglot * default_parkinglot
Default parking lot.
Definition: features.c:582
Definition: cli.h:146
struct ast_channel * chan
Definition: features.c:471
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int args
This gets set in ast_cli_register()
Definition: cli.h:179
int priority
Definition: features.c:477
Description of one parked call, added to a list while active, then removed. The list belongs to a par...
Definition: features.c:470
const int fd
Definition: cli.h:153
#define ao2_ref(o, delta)
Definition: astobj2.h:472
Structure for parking lots which are put in a container.
Definition: features.c:556
#define CLI_SHOWUSAGE
Definition: cli.h:44
const ast_string_field name
Definition: channel.h:787
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ESS(x)
Definition: cli.h:58
char * command
Definition: cli.h:180
struct timeval start
Definition: features.c:472
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
const char * usage
Definition: cli.h:171
struct ast_parkinglot::parkinglot_parklist parkings
#define CLI_SUCCESS
Definition: cli.h:43
char parkingexten[AST_MAX_EXTENSION]
Definition: features.c:474
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
int parkingtime
Definition: features.c:478
static int load_config ( int  reload)
static

Definition at line 6717 of file features.c.

References ao2_t_callback, ast_config_destroy(), ast_config_load2(), ast_debug, AST_LIST_HEAD_NOLOCK_INIT_VALUE, ast_log(), build_dialplan_useage_map(), build_parkinglot(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_PARKINGLOT, default_parkinglot, destroy_dialplan_usage_map(), force_reload_load, LOG_ERROR, LOG_WARNING, OBJ_NODATA, OBJ_UNLINK, parkinglot_activate_cb(), parkinglot_is_marked_cb(), parkinglot_markall_cb(), parkinglots, process_config(), and remove_dead_dialplan_useage().

Referenced by ast_features_init(), and ast_features_reload().

6718 {
6719  struct ast_flags config_flags = {
6721  struct ast_config *cfg;
6722  struct parking_dp_map old_usage_map = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6723  struct parking_dp_map new_usage_map = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6724 
6725  /* We are reloading now and have already determined if we will force the reload. */
6726  force_reload_load = 0;
6727 
6728  if (!default_parkinglot) {
6729  /* Must create the default default parking lot */
6731  if (!default_parkinglot) {
6732  ast_log(LOG_ERROR, "Configuration of default default parking lot failed.\n");
6733  return -1;
6734  }
6735  ast_debug(1, "Configuration of default default parking lot done.\n");
6736  }
6737 
6738  cfg = ast_config_load2("features.conf", "features", config_flags);
6739  if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
6740  /* No sense in asking for reload trouble if nothing changed. */
6741  ast_debug(1, "features.conf did not change.\n");
6742  return 0;
6743  }
6744  if (cfg == CONFIG_STATUS_FILEMISSING
6745  || cfg == CONFIG_STATUS_FILEINVALID) {
6746  ast_log(LOG_WARNING, "Could not load features.conf\n");
6747  return 0;
6748  }
6749 
6750  /* Save current parking lot dialplan needs. */
6751  if (build_dialplan_useage_map(&old_usage_map, 0)) {
6752  destroy_dialplan_usage_map(&old_usage_map);
6753 
6754  /* Allow reloading later to see if conditions have improved. */
6755  force_reload_load = 1;
6756  return -1;
6757  }
6758 
6760  "callback to mark all parking lots");
6761  process_config(cfg);
6762  ast_config_destroy(cfg);
6764  "callback to remove marked parking lots");
6765 
6766  /* Save updated parking lot dialplan needs. */
6767  if (build_dialplan_useage_map(&new_usage_map, 1)) {
6768  /*
6769  * Yuck, if this failure caused any parking lot dialplan items
6770  * to be lost, they will likely remain lost until Asterisk is
6771  * restarted.
6772  */
6773  destroy_dialplan_usage_map(&old_usage_map);
6774  destroy_dialplan_usage_map(&new_usage_map);
6775  return -1;
6776  }
6777 
6778  /* Remove no longer needed parking lot dialplan usage. */
6779  remove_dead_dialplan_useage(&old_usage_map, &new_usage_map);
6780 
6781  destroy_dialplan_usage_map(&old_usage_map);
6782  destroy_dialplan_usage_map(&new_usage_map);
6783 
6785  "callback to activate all parking lots");
6786 
6787  return 0;
6788 }
static int parkinglot_markall_cb(void *obj, void *arg, int flags)
Definition: features.c:6661
#define LOG_WARNING
Definition: logger.h:144
static struct ast_parkinglot * default_parkinglot
Default parking lot.
Definition: features.c:582
static int parkinglot_is_marked_cb(void *obj, void *arg, int flags)
Definition: features.c:6669
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: config.c:2499
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define CONFIG_STATUS_FILEMISSING
Definition: config.h:50
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int force_reload_load
Definition: features.c:585
static int reload(void)
Definition: app_amd.c:497
#define LOG_ERROR
Definition: logger.h:155
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:909
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
static void remove_dead_dialplan_useage(struct parking_dp_map *old_map, struct parking_dp_map *new_map)
Definition: features.c:6617
static int process_config(struct ast_config *cfg)
Definition: features.c:5867
static void destroy_dialplan_usage_map(struct parking_dp_map *doomed)
Definition: features.c:6068
Structure used to handle boolean flags.
Definition: utils.h:200
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:251
static int parkinglot_activate_cb(void *obj, void *arg, int flags)
Definition: features.c:6689
#define DEFAULT_PARKINGLOT
Definition: features.h:37
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
static int build_dialplan_useage_map(struct parking_dp_map *usage_map, int complain)
Definition: features.c:6396
static struct ast_parkinglot * build_parkinglot(const char *pl_name, struct ast_variable *var)
Build parkinglot from configuration and chain it in if it doesn&#39;t already exist.
Definition: features.c:5689
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static int manage_parked_call ( struct parkeduser pu,
const struct pollfd *  pfds,
int  nfds,
struct pollfd **  new_pfds,
int *  new_nfds,
int *  ms 
)
static

Definition at line 4703 of file features.c.

References ast_add_extension(), AST_CEL_PARK_END, ast_cel_report_event(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_context_find_or_create(), AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, AST_FLAG_EXCEPTION, AST_FRAME_CONTROL, ast_free_ptr(), ast_frfree, ast_hangup(), ast_indicate(), ast_indicate_data(), ast_log(), AST_MAX_EXTENSION, AST_MAX_FDS, ast_pbx_start(), ast_read(), ast_realloc, ast_set_flag, ast_strdup, ast_strdupa, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, callback_dialoptions(), ast_parkinglot::cfg, parkeduser::chan, comebacktoorigin, parkeduser::context, ast_channel::context, ast_datastore::data, dial_features_info, parkeduser::exten, ast_channel::exten, f, ast_channel::fdno, ast_channel::fds, ast_frame::frametype, ast_channel::generatordata, parkeduser::hold_method, ast_frame_subclass::integer, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_DIAL_FEATURE_OPTIONS, parkeduser::moh_trys, parkinglot_cfg::mohclass, ast_dial_features::my_features, ast_parkinglot::name, ast_channel::name, parkeduser::options_specified, parking_con_dial, parkeduser::parkinglot, parkeduser::parkingnum, parkingretalertinfo, parkingretcidname, parkingretdahdiring, parkeduser::parkingtime, pbx_builtin_setvar_helper(), ast_dial_features::peer_features, parkeduser::peername, post_manager_event(), parkeduser::priority, ast_channel::priority, registrar, S_OR, set_c_e_p(), parkeduser::start, strdup, and ast_frame::subclass.

Referenced by manage_parkinglot().

4704 {
4705  struct ast_channel *chan = pu->chan; /* shorthand */
4706  int tms; /* timeout for this item */
4707  int x; /* fd index in channel */
4708 
4709  tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
4710  if (tms > pu->parkingtime) {
4711  /*
4712  * Call has been parked too long.
4713  * Stop entertaining the caller.
4714  */
4715  switch (pu->hold_method) {
4716  case AST_CONTROL_HOLD:
4718  break;
4719  case AST_CONTROL_RINGING:
4720  ast_indicate(pu->chan, -1);
4721  break;
4722  default:
4723  break;
4724  }
4725  pu->hold_method = 0;
4726 
4727  /* Get chan, exten from derived kludge */
4728  if (pu->peername[0]) {
4729  char *peername;
4730  char *dash;
4731  char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
4732  int i;
4733 
4734  peername = ast_strdupa(pu->peername);
4735  dash = strrchr(peername, '-');
4736  if (dash) {
4737  *dash = '\0';
4738  }
4739 
4740  peername_flat = ast_strdupa(peername);
4741  for (i = 0; peername_flat[i]; i++) {
4742  if (peername_flat[i] == '/') {
4743  peername_flat[i] = '_';
4744  }
4745  }
4746 
4749  "Parking dial context '%s' does not exist and unable to create\n",
4751  } else {
4752  char returnexten[AST_MAX_EXTENSION];
4753  struct ast_datastore *features_datastore;
4754  struct ast_dial_features *dialfeatures;
4755 
4756  if (!strncmp(peername, "Parked/", 7)) {
4757  peername += 7;
4758  }
4759  /* If dahdi channel, add a ring cadence DAHDI/NNr3 (if parkingretdahdiring defined) */
4760  if (!ast_strlen_zero(parkingretdahdiring) && !strncasecmp(peername, "dahdi", 5))
4761  strncat(peername, parkingretdahdiring, 2);
4762 
4763  ast_channel_lock(chan);
4764  features_datastore = ast_channel_datastore_find(chan, &dial_features_info,
4765  NULL);
4766  if (features_datastore && (dialfeatures = features_datastore->data)) {
4767  char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
4768 
4769  snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername,
4770  callback_dialoptions(&dialfeatures->peer_features,
4771  &dialfeatures->my_features, buf, sizeof(buf)));
4772  } else { /* Existing default */
4773  ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n",
4774  chan->name);
4775  snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
4776  }
4777  ast_channel_unlock(chan);
4778 
4779 
4780  int parkdialprio = 1;
4781  char parkciddata[512];
4782  char parkalertinfodata[512];
4783  /* alter CALLERID(name) and add AlertInfo header if requested */
4785  snprintf(parkciddata, sizeof(parkciddata), "CALLERID(name)=%s", parkingretcidname);
4786  if (ast_add_extension(parking_con_dial, 1, peername_flat, parkdialprio++, NULL, NULL, "Set", strdup(parkciddata), ast_free_ptr, registrar))
4787  ast_log(LOG_ERROR, "Could not create parking return dial exten: %s@%s\n", peername_flat, parking_con_dial);
4788  }
4790  snprintf(parkalertinfodata, sizeof(parkalertinfodata), "Alert-Info: %s", parkingretalertinfo);
4791  if (ast_add_extension(parking_con_dial, 1, peername_flat, parkdialprio++, NULL, NULL, "SIPAddHeader", strdup(parkalertinfodata), ast_free_ptr, registrar))
4792  ast_log(LOG_ERROR, "Could not create parking return dial exten: %s@%s\n", peername_flat, parking_con_dial);
4793  }
4794  if (ast_add_extension(parking_con_dial, 1, peername_flat, parkdialprio, NULL, NULL,
4795  "Dial", ast_strdup(returnexten), ast_free_ptr, registrar)) {
4797  "Could not create parking return dial exten: %s@%s\n",
4798  peername_flat, parking_con_dial);
4799  }
4800  }
4801  if (pu->options_specified) {
4802  /*
4803  * Park() was called with overriding return arguments, respect
4804  * those arguments.
4805  */
4806  set_c_e_p(chan, pu->context, pu->exten, pu->priority);
4807  } else if (comebacktoorigin) {
4808  set_c_e_p(chan, parking_con_dial, peername_flat, 1);
4809  } else {
4810  char parkingslot[AST_MAX_EXTENSION];
4811 
4812  snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
4813  pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
4814  set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
4815  }
4816  } else {
4817  /*
4818  * They've been waiting too long, send them back to where they
4819  * came. Theoretically they should have their original
4820  * extensions and such, but we copy to be on the safe side.
4821  */
4822  set_c_e_p(chan, pu->context, pu->exten, pu->priority);
4823  }
4824  post_manager_event("ParkedCallTimeOut", pu);
4825  ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
4826 
4827  ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n",
4828  pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context,
4829  pu->chan->exten, pu->chan->priority);
4830 
4831  /* Start up the PBX, or hang them up */
4832  if (ast_pbx_start(chan)) {
4834  "Unable to restart the PBX for user on '%s', hanging them up...\n",
4835  pu->chan->name);
4836  ast_hangup(chan);
4837  }
4838 
4839  /* And take them out of the parking lot */
4840  return 1;
4841  }
4842 
4843  /* still within parking time, process descriptors */
4844  if (pfds) {
4845  for (x = 0; x < AST_MAX_FDS; x++) {
4846  struct ast_frame *f;
4847  int y;
4848 
4849  if (chan->fds[x] == -1) {
4850  continue; /* nothing on this descriptor */
4851  }
4852 
4853  for (y = 0; y < nfds; y++) {
4854  if (pfds[y].fd == chan->fds[x]) {
4855  /* Found poll record! */
4856  break;
4857  }
4858  }
4859  if (y == nfds) {
4860  /* Not found */
4861  continue;
4862  }
4863 
4864  if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
4865  /* Next x */
4866  continue;
4867  }
4868 
4869  if (pfds[y].revents & POLLPRI) {
4871  } else {
4873  }
4874  chan->fdno = x;
4875 
4876  /* See if they need servicing */
4877  f = ast_read(pu->chan);
4878  /* Hangup? */
4879  if (!f || (f->frametype == AST_FRAME_CONTROL
4880  && f->subclass.integer == AST_CONTROL_HANGUP)) {
4881  if (f) {
4882  ast_frfree(f);
4883  }
4884  post_manager_event("ParkedCallGiveUp", pu);
4885  ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp",
4886  NULL);
4887 
4888  /* There's a problem, hang them up */
4889  ast_verb(2, "%s got tired of being parked\n", chan->name);
4890  ast_hangup(chan);
4891 
4892  /* And take them out of the parking lot */
4893  return 1;
4894  } else {
4895  /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
4896  ast_frfree(f);
4897  if (pu->hold_method == AST_CONTROL_HOLD
4898  && pu->moh_trys < 3
4899  && !chan->generatordata) {
4900  ast_debug(1,
4901  "MOH on parked call stopped by outside source. Restarting on channel %s.\n",
4902  chan->name);
4904  S_OR(pu->parkinglot->cfg.mohclass, NULL),
4906  ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0));
4907  pu->moh_trys++;
4908  }
4909  break;
4910  }
4911  } /* End for */
4912  }
4913 
4914  /* mark fds for next round */
4915  for (x = 0; x < AST_MAX_FDS; x++) {
4916  if (chan->fds[x] > -1) {
4917  void *tmp = ast_realloc(*new_pfds,
4918  (*new_nfds + 1) * sizeof(struct pollfd));
4919 
4920  if (!tmp) {
4921  continue;
4922  }
4923  *new_pfds = tmp;
4924  (*new_pfds)[*new_nfds].fd = chan->fds[x];
4925  (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
4926  (*new_pfds)[*new_nfds].revents = 0;
4927  (*new_nfds)++;
4928  }
4929  }
4930  /* Keep track of our shortest wait */
4931  if (tms < *ms || *ms < 0) {
4932  *ms = tms;
4933  }
4934 
4935  /* Stay in the parking lot. */
4936  return 0;
4937 }
struct ast_flags peer_features
Definition: features.c:653
char context[AST_MAX_CONTEXT]
Definition: features.c:475
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
int priority
Definition: channel.h:841
#define ast_strdup(a)
Definition: astmm.h:109
char exten[AST_MAX_EXTENSION]
Definition: features.c:476
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#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
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
#define MAX_DIAL_FEATURE_OPTIONS
Definition: features.c:393
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct ast_channel * chan
Definition: features.c:471
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
struct ast_flags my_features
Definition: features.c:651
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
Structure for a data store object.
Definition: datastore.h:54
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
void ast_free_ptr(void *ptr)
#define ast_verb(level,...)
Definition: logger.h:243
static char parkingretdahdiring[3]
Definition: features.c:596
int priority
Definition: features.c:477
unsigned int options_specified
Definition: features.c:482
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_MAX_EXTENSION
Definition: channel.h:135
static struct ast_datastore_info dial_features_info
Definition: features.c:752
int fds[AST_MAX_FDS]
Definition: channel.h:829
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static char parking_con_dial[]
Context for parking dialback to parker.
Definition: features.c:607
static char parkingretcidname[256]
Definition: features.c:595
#define LOG_ERROR
Definition: logger.h:155
struct parkinglot_cfg cfg
Definition: features.c:560
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
static char parkingretalertinfo[256]
Definition: features.c:597
int fdno
Definition: channel.h:834
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define AST_MAX_FDS
Definition: channel.h:158
struct timeval start
Definition: features.c:472
enum ast_control_frame_type hold_method
Definition: features.c:480
static struct ast_format f[]
Definition: format_g726.c:181
static void post_manager_event(const char *s, struct parkeduser *pu)
Output parking event to manager.
Definition: features.c:4629
static char * registrar
Definition: features.c:623
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
store context, extension and priority
Definition: features.c:881
#define ast_clear_flag(p, flag)
Definition: utils.h:77
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
void * data
Definition: datastore.h:56
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:8691
struct ast_parkinglot * parkinglot
Definition: features.c:486
#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
#define ast_realloc(a, b)
Definition: astmm.h:103
channel out of the park
Definition: cel.h:72
Data structure associated with a single frame of data.
Definition: frame.h:142
char name[AST_MAX_CONTEXT]
Definition: features.c:558
enum ast_frame_type frametype
Definition: frame.h:144
static char * callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
Definition: features.c:4651
#define ast_frfree(fr)
Definition: frame.h:583
int parkingnum
Definition: features.c:473
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:7726
#define strdup(a)
Definition: astmm.h:106
char peername[AST_CHANNEL_NAME]
Definition: features.c:483
unsigned char moh_trys
Definition: features.c:484
int parkingtime
Definition: features.c:478
void * generatordata
Definition: channel.h:746
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static int comebacktoorigin
Definition: features.c:616
char mohclass[MAX_MUSICCLASS]
Definition: features.c:493
static void manage_parkinglot ( struct ast_parkinglot curlot,
const struct pollfd *  pfds,
int  nfds,
struct pollfd **  new_pfds,
int *  new_nfds,
int *  ms 
)
static

Run management on parkinglots, called once per parkinglot.

Definition at line 4940 of file features.c.

References ast_context_find(), ast_context_remove_extension2(), AST_DEVICE_NOT_INUSE, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_parkinglot::cfg, LOG_WARNING, manage_parked_call(), ast_parkinglot::name, notify_metermaids(), parkeduser::notquiteyet, parkinglot_cfg::parking_con, parkeduser::parkingexten, parkeduser::parkinglot, parkinglot_unref(), and ast_parkinglot::parkings.

Referenced by do_parking_thread().

4941 {
4942  struct parkeduser *pu;
4943  struct ast_context *con;
4944 
4945  /* Lock parkings list */
4946  AST_LIST_LOCK(&curlot->parkings);
4947  AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
4948  if (pu->notquiteyet) { /* Pretend this one isn't here yet */
4949  continue;
4950  }
4951  if (manage_parked_call(pu, pfds, nfds, new_pfds, new_nfds, ms)) {
4952  /* Parking is complete for this call so remove it from the parking lot. */
4954  if (con) {
4955  if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
4957  "Whoa, failed to remove the parking extension %s@%s!\n",
4959  }
4962  } else {
4964  "Whoa, parking lot '%s' context '%s' does not exist.\n",
4966  }
4969  ast_free(pu);
4970  }
4971  }
4973  AST_LIST_UNLOCK(&curlot->parkings);
4974 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
Definition: features.c:4703
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
Description of one parked call, added to a list while active, then removed. The list belongs to a par...
Definition: features.c:470
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
struct parkinglot_cfg cfg
Definition: features.c:560
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_free(a)
Definition: astmm.h:97
struct ast_parkinglot::parkinglot_parklist parkings
char parkingexten[AST_MAX_EXTENSION]
Definition: features.c:474
struct ast_parkinglot * parkinglot
Definition: features.c:486
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Definition: pbx.c:6144
char name[AST_MAX_CONTEXT]
Definition: features.c:558
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
Notify metermaids that we&#39;ve changed an extension.
Definition: features.c:1096
ast_context: An extension context
Definition: pbx.c:955
unsigned int notquiteyet
Definition: features.c:481
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2971
static int manager_park ( struct mansession s,
const struct message m 
)
static

Create manager event for parked calls.

Parameters
s
mGet channels involved in park, create event.
Returns
Always 0
Note
ADSI is not compatible with this AMI action for the same reason ch2 can no longer announce the parking space.

Definition at line 7245 of file features.c.

References ast_channel_get_by_name(), ast_channel_unref, AST_PARK_OPT_SILENCE, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), find_parkinglot(), ast_park_call_args::flags, masq_park_call(), ast_park_call_args::parkinglot, parkinglot_unref(), and ast_park_call_args::timeout.

Referenced by ast_features_init().

7246 {
7247  const char *channel = astman_get_header(m, "Channel");
7248  const char *channel2 = astman_get_header(m, "Channel2");
7249  const char *timeout = astman_get_header(m, "Timeout");
7250  const char *parkinglotname = astman_get_header(m, "Parkinglot");
7251  char buf[BUFSIZ];
7252  int res = 0;
7253  struct ast_channel *ch1, *ch2;
7254  struct ast_park_call_args args = {
7255  /*
7256  * Don't say anything to ch2 since AMI is a third party parking
7257  * a call and we will likely crash if we do.
7258  *
7259  * XXX When the AMI action was originally implemented, the
7260  * parking space was announced to ch2. Unfortunately, grabbing
7261  * the ch2 lock and holding it while the announcement is played
7262  * was not really a good thing to do to begin with since it
7263  * could hold up the system. Also holding the lock is no longer
7264  * possible with a masquerade.
7265  *
7266  * Restoring the announcement to ch2 is not easily doable for
7267  * the following reasons:
7268  *
7269  * 1) The AMI manager is not the thread processing ch2.
7270  *
7271  * 2) ch2 could be the same as ch1, bridged to ch1, or some
7272  * random uninvolved channel.
7273  */
7274  .flags = AST_PARK_OPT_SILENCE,
7275  };
7276 
7277  if (ast_strlen_zero(channel)) {
7278  astman_send_error(s, m, "Channel not specified");
7279  return 0;
7280  }
7281 
7282  if (ast_strlen_zero(channel2)) {
7283  astman_send_error(s, m, "Channel2 not specified");
7284  return 0;
7285  }
7286 
7287  if (!ast_strlen_zero(timeout)) {
7288  if (sscanf(timeout, "%30d", &args.timeout) != 1) {
7289  astman_send_error(s, m, "Invalid timeout value.");
7290  return 0;
7291  }
7292  }
7293 
7294  if (!(ch1 = ast_channel_get_by_name(channel))) {
7295  snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
7296  astman_send_error(s, m, buf);
7297  return 0;
7298  }
7299 
7300  if (!(ch2 = ast_channel_get_by_name(channel2))) {
7301  snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
7302  astman_send_error(s, m, buf);
7303  ast_channel_unref(ch1);
7304  return 0;
7305  }
7306 
7307  if (!ast_strlen_zero(parkinglotname)) {
7308  args.parkinglot = find_parkinglot(parkinglotname);
7309  }
7310 
7311  res = masq_park_call(ch1, ch2, &args);
7312  if (!res) {
7314  astman_send_ack(s, m, "Park successful");
7315  } else {
7316  astman_send_error(s, m, "Park failure");
7317  }
7318 
7319  if (args.parkinglot) {
7321  }
7322  ch1 = ast_channel_unref(ch1);
7323  ch2 = ast_channel_unref(ch2);
7324 
7325  return 0;
7326 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
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
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
static struct @350 args
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
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int manager_parking_status ( struct mansession s,
const struct message m 
)
static

Dump parking lot status.

Parameters
s
mLock parking lot, iterate list and append parked calls status, unlock parking lot.
Returns
Always RESULT_SUCCESS

Definition at line 7179 of file features.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), ast_channel::caller, parkeduser::chan, ast_channel::connected, ast_party_caller::id, ast_party_connected_line::id, ast_party_id::name, ast_parkinglot::name, ast_channel::name, ast_party_id::number, parkinglots, parkeduser::parkingnum, ast_parkinglot::parkings, parkeduser::parkingtime, parkeduser::peername, RESULT_SUCCESS, S_COR, parkeduser::start, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.

Referenced by ast_features_init().

7180 {
7181  struct parkeduser *cur;
7182  const char *id = astman_get_header(m, "ActionID");
7183  char idText[256] = "";
7184  struct ao2_iterator iter;
7185  struct ast_parkinglot *curlot;
7186  int numparked = 0;
7187 
7188  if (!ast_strlen_zero(id))
7189  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
7190 
7191  astman_send_ack(s, m, "Parked calls will follow");
7192 
7193  iter = ao2_iterator_init(parkinglots, 0);
7194  while ((curlot = ao2_iterator_next(&iter))) {
7195  AST_LIST_LOCK(&curlot->parkings);
7196  AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
7197  astman_append(s, "Event: ParkedCall\r\n"
7198  "Parkinglot: %s\r\n"
7199  "Exten: %d\r\n"
7200  "Channel: %s\r\n"
7201  "From: %s\r\n"
7202  "Timeout: %ld\r\n"
7203  "CallerIDNum: %s\r\n"
7204  "CallerIDName: %s\r\n"
7205  "ConnectedLineNum: %s\r\n"
7206  "ConnectedLineName: %s\r\n"
7207  "%s"
7208  "\r\n",
7209  curlot->name,
7210  cur->parkingnum, cur->chan->name, cur->peername,
7211  (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
7212  S_COR(cur->chan->caller.id.number.valid, cur->chan->caller.id.number.str, ""), /* XXX in other places it is <unknown> */
7213  S_COR(cur->chan->caller.id.name.valid, cur->chan->caller.id.name.str, ""),
7214  S_COR(cur->chan->connected.id.number.valid, cur->chan->connected.id.number.str, ""), /* XXX in other places it is <unknown> */
7215  S_COR(cur->chan->connected.id.name.valid, cur->chan->connected.id.name.str, ""),
7216  idText);
7217  ++numparked;
7218  }
7219  AST_LIST_UNLOCK(&curlot->parkings);
7220  ao2_ref(curlot, -1);
7221  }
7222  ao2_iterator_destroy(&iter);
7223 
7224  astman_append(s,
7225  "Event: ParkedCallsComplete\r\n"
7226  "Total: %d\r\n"
7227  "%s"
7228  "\r\n",
7229  numparked, idText);
7230 
7231  return RESULT_SUCCESS;
7232 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ast_channel * chan
Definition: features.c:471
char * str
Subscriber name (Malloced)
Definition: channel.h:214
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
Description of one parked call, added to a list while active, then removed. The list belongs to a par...
Definition: features.c:470
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#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
Structure for parking lots which are put in a container.
Definition: features.c:556
const ast_string_field name
Definition: channel.h:787
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct timeval start
Definition: features.c:472
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
struct ast_parkinglot::parkinglot_parklist parkings
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
int parkingnum
Definition: features.c:473
#define RESULT_SUCCESS
Definition: cli.h:39
char peername[AST_CHANNEL_NAME]
Definition: features.c:483
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
int parkingtime
Definition: features.c:478
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int masq_park_call ( struct ast_channel rchan,
struct ast_channel peer,
struct ast_park_call_args args 
)
static

Park call via masqueraded channel and announce parking spot on peer channel.

Parameters
rchanthe real channel to be parked
peerthe channel to have the parking read to.
argsAdditional parking options when parking a call.
Return values
0on success.
-1on failure.

Definition at line 1726 of file features.c.

References ast_channel::accountcode, ast_channel::amaflags, ast_channel_alloc(), ast_channel_masquerade(), ast_copy_string(), ast_do_masquerade(), ast_hangup(), ast_log(), AST_PARK_OPT_SILENCE, AST_STATE_DOWN, ast_stream_and_wait(), ast_test_flag, ast_channel::context, ast_channel::exten, ast_channel::linkedid, LOG_WARNING, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, ast_channel::name, park_call_full(), park_space_abort(), park_space_reserve(), play_message_on_chan(), ast_channel::priority, ast_park_call_args::pu, ast_channel::readformat, set_c_e_p(), and ast_channel::writeformat.

Referenced by ast_masq_park_call(), ast_masq_park_call_exten(), builtin_parkcall(), manager_park(), park_call_exec(), and xfer_park_call_helper().

1727 {
1728  struct ast_channel *chan;
1729 
1730  /* Make a new, channel that we'll use to masquerade in the real one */
1731  chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten,
1732  rchan->context, rchan->linkedid, rchan->amaflags, "Parked/%s", rchan->name);
1733  if (!chan) {
1734  ast_log(LOG_WARNING, "Unable to create parked channel\n");
1735  if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1736  if (peer == rchan) {
1737  /* Only have one channel to worry about. */
1738  ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1739  } else if (peer) {
1740  /* Have two different channels to worry about. */
1741  play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1742  }
1743  }
1744  return -1;
1745  }
1746 
1747  args->pu = park_space_reserve(rchan, peer, args);
1748  if (!args->pu) {
1749  ast_hangup(chan);
1750  if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1751  if (peer == rchan) {
1752  /* Only have one channel to worry about. */
1753  ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1754  } else if (peer) {
1755  /* Have two different channels to worry about. */
1756  play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1757  }
1758  }
1759  return -1;
1760  }
1761 
1762  /* Make formats okay */
1763  chan->readformat = rchan->readformat;
1764  chan->writeformat = rchan->writeformat;
1765 
1766  if (ast_channel_masquerade(chan, rchan)) {
1767  park_space_abort(args->pu);
1768  args->pu = NULL;
1769  ast_hangup(chan);
1770  if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1771  if (peer == rchan) {
1772  /* Only have one channel to worry about. */
1773  ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1774  } else if (peer) {
1775  /* Have two different channels to worry about. */
1776  play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1777  }
1778  }
1779  return -1;
1780  }
1781 
1782  /* Setup the extensions and such */
1783  set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
1784 
1785  /* Setup the macro extension and such */
1786  ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
1787  ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
1788  chan->macropriority = rchan->macropriority;
1789 
1790  /* Manually do the masquerade to make sure it is complete. */
1791  ast_do_masquerade(chan);
1792 
1793  if (peer == rchan) {
1794  peer = chan;
1795  }
1796 
1797  /* parking space reserved, return code check unnecessary */
1798  park_call_full(chan, peer, args);
1799 
1800  return 0;
1801 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
Definition: features.c:1470
Main Channel structure associated with a channel.
Definition: channel.h:742
int priority
Definition: channel.h:841
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
format_t writeformat
Definition: channel.h:854
#define ast_test_flag(p, flag)
Definition: utils.h:63
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define LOG_WARNING
Definition: logger.h:144
static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
Definition: features.c:2024
const ast_string_field linkedid
Definition: channel.h:787
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
struct parkeduser * pu
Definition: features.c:1150
int macropriority
Definition: channel.h:842
static void park_space_abort(struct parkeduser *pu)
Definition: features.c:1272
static struct parkeduser * park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
Definition: features.c:1299
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
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
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
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
store context, extension and priority
Definition: features.c:881
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
format_t readformat
Definition: channel.h:853
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
const ast_string_field accountcode
Definition: channel.h:787
int amaflags
Definition: channel.h:843
int ast_do_masquerade(struct ast_channel *chan)
Start masquerading a channel.
Definition: channel.c:6546
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static enum ast_device_state metermaidstate ( const char *  data)
static

metermaids callback from devicestate.c

Definition at line 1105 of file features.c.

References ast_debug, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, ast_exists_extension(), ast_strdupa, context, feature_group_exten::exten, and strsep().

Referenced by ast_features_init().

1106 {
1107  char *context;
1108  char *exten;
1109 
1110  context = ast_strdupa(data);
1111 
1112  exten = strsep(&context, "@");
1113  if (!context)
1114  return AST_DEVICE_INVALID;
1115 
1116  ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
1117 
1118  if (!ast_exists_extension(NULL, context, exten, 1, NULL))
1119  return AST_DEVICE_NOT_INUSE;
1120 
1121  return AST_DEVICE_INUSE;
1122 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
char * strsep(char **str, const char *delims)
const char * data
Definition: channel.h:755
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void notify_metermaids ( const char *  exten,
char *  context,
enum ast_device_state  state 
)
static

Notify metermaids that we've changed an extension.

Definition at line 1096 of file features.c.

References ast_debug, ast_devstate2str(), AST_DEVSTATE_CACHABLE, and ast_devstate_changed().

Referenced by manage_parkinglot(), park_call_full(), parked_call_exec(), and parkinglot_activate().

1097 {
1098  ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
1100 
1102 }
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
Definition: devicestate.c:215
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:516
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void park_add_hints ( const char *  context,
int  start,
int  stop 
)
static

Add parking hints for all defined parking spaces.

Parameters
contextDialplan context to add the hints.
startStarting space in parkinglot.
stopEnding space in parkinglot.

Definition at line 5484 of file features.c.

References ast_add_extension(), AST_MAX_EXTENSION, PRIORITY_HINT, registrar, and stop.

Referenced by parkinglot_activate().

5485 {
5486  int numext;
5487  char device[AST_MAX_EXTENSION];
5488  char exten[10];
5489 
5490  for (numext = start; numext <= stop; numext++) {
5491  snprintf(exten, sizeof(exten), "%d", numext);
5492  snprintf(device, sizeof(device), "park:%s@%s", exten, context);
5493  ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
5494  }
5495 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
unsigned int stop
Definition: app_meetme.c:969
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define PRIORITY_HINT
Definition: pbx.h:53
static char * registrar
Definition: features.c:623
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:8691
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int park_call_exec ( struct ast_channel chan,
const char *  data 
)
static

Park a call.

Definition at line 5063 of file features.c.

References ast_channel::_state, ast_answer(), ast_app_parse_options(), ast_copy_string(), ast_log(), AST_MAX_EXTENSION, AST_PARK_OPT_SILENCE, ast_safe_sleep(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, create_dynamic_parkinglot(), default_parkinglot, ast_channel::exten, find_parkinglot(), findparkinglotname(), ast_flags::flags, ast_park_call_args::flags, LOG_WARNING, masq_park_call(), ast_channel::name, park_app_args::options, ast_park_call_args::orig_chan_name, orig_exten(), park_call_options, parkeddynamic, ast_park_call_args::parkinglot, parkinglot_addref(), parkinglot_unref(), parse(), pbx_builtin_getvar_helper(), park_app_args::pl_name, ast_channel::priority, park_app_args::return_con, ast_park_call_args::return_con, park_app_args::return_ext, ast_park_call_args::return_ext, park_app_args::return_pri, ast_park_call_args::return_pri, S_OR, park_app_args::timeout, and ast_park_call_args::timeout.

Referenced by ast_features_init().

5064 {
5065  struct ast_park_call_args args = { 0, };
5066  struct ast_flags flags = { 0 };
5068  int orig_priority;
5069  int res;
5070  const char *pl_name;
5071  char *parse;
5072  struct park_app_args app_args;
5073 
5074  /*
5075  * Cache the original channel name because we are going to
5076  * masquerade the channel. Prefer the BLINDTRANSFER channel
5077  * name over this channel name. BLINDTRANSFER could be set if
5078  * the parking access extension did not get detected and we are
5079  * executing the Park application from the dialplan.
5080  *
5081  * The orig_chan_name is used to return the call to the
5082  * originator on parking timeout.
5083  */
5085  pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"), chan->name));
5086 
5087  /* Answer if call is not up */
5088  if (chan->_state != AST_STATE_UP) {
5089  if (ast_answer(chan)) {
5090  return -1;
5091  }
5092 
5093  /* Sleep to allow VoIP streams to settle down */
5094  if (ast_safe_sleep(chan, 1000)) {
5095  return -1;
5096  }
5097  }
5098 
5099  /* Process the dialplan application options. */
5100  parse = ast_strdupa(data);
5101  AST_STANDARD_APP_ARGS(app_args, parse);
5102 
5103  if (!ast_strlen_zero(app_args.timeout)) {
5104  if (sscanf(app_args.timeout, "%30d", &args.timeout) != 1) {
5105  ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
5106  args.timeout = 0;
5107  }
5108  }
5109  if (!ast_strlen_zero(app_args.return_con)) {
5110  args.return_con = app_args.return_con;
5111  }
5112  if (!ast_strlen_zero(app_args.return_ext)) {
5113  args.return_ext = app_args.return_ext;
5114  }
5115  if (!ast_strlen_zero(app_args.return_pri)) {
5116  if (sscanf(app_args.return_pri, "%30d", &args.return_pri) != 1) {
5117  ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
5118  args.return_pri = 0;
5119  }
5120  }
5121 
5122  ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
5123  args.flags = flags.flags;
5124 
5125  /*
5126  * Setup the exten/priority to be s/1 since we don't know where
5127  * this call should return.
5128  */
5129  ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
5130  orig_priority = chan->priority;
5131  strcpy(chan->exten, "s");
5132  chan->priority = 1;
5133 
5134  /* Park the call */
5135  if (!ast_strlen_zero(app_args.pl_name)) {
5136  pl_name = app_args.pl_name;
5137  } else {
5138  pl_name = findparkinglotname(chan);
5139  }
5140  if (ast_strlen_zero(pl_name)) {
5141  /* Parking lot is not specified, so use the default parking lot. */
5143  } else {
5144  args.parkinglot = find_parkinglot(pl_name);
5145  if (!args.parkinglot && parkeddynamic) {
5146  args.parkinglot = create_dynamic_parkinglot(pl_name, chan);
5147  }
5148  }
5149  if (args.parkinglot) {
5150  res = masq_park_call(chan, chan, &args);
5152  } else {
5153  /* Parking failed because the parking lot does not exist. */
5154  if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
5155  ast_stream_and_wait(chan, "pbx-parkingfailed", "");
5156  }
5157  res = -1;
5158  }
5159  if (res) {
5160  /* Park failed, try to continue in the dialplan. */
5161  ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
5162  chan->priority = orig_priority;
5163  res = 0;
5164  } else {
5165  /* Park succeeded. */
5166  res = -1;
5167  }
5168 
5169  return res;
5170 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
static struct ast_parkinglot * parkinglot_addref(struct ast_parkinglot *parkinglot)
Definition: features.c:5435
int priority
Definition: channel.h:841
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
static struct ast_parkinglot * default_parkinglot
Default parking lot.
Definition: features.c:582
unsigned int flags
Definition: utils.h:201
static struct ast_app_option park_call_options[128]
Definition: features.c:5060
const char * orig_chan_name
Definition: features.c:1144
static const char * findparkinglotname(struct ast_channel *chan)
Find parking lot name from channel.
Definition: features.c:1082
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
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
const char * return_con
Definition: features.c:1145
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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_MAX_EXTENSION
Definition: channel.h:135
static char * orig_exten(int fd, const char *chan, const char *data)
orginate from extension
static int parkeddynamic
Definition: features.c:588
const char * return_ext
Definition: features.c:1146
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
enum ast_channel_state _state
Definition: channel.h:839
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
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
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
struct ast_parkinglot * parkinglot
Parkinglot to be parked in.
Definition: features.c:1152
Structure used to handle boolean flags.
Definition: utils.h:200
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
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
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
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static int park_call_full ( struct ast_channel chan,
struct ast_channel peer,
struct ast_park_call_args args 
)
static

< Channel name that is parking the call.

Definition at line 1470 of file features.c.

References adsi_announce_park(), adsipark, ast_channel::appl, ast_add_extension(), ast_adsi_available(), ast_adsi_unload_session(), ast_bridged_channel(), AST_CEL_PARK_START, ast_cel_report_event(), ast_channel_get_by_name(), ast_channel_lock, AST_CHANNEL_NAME, ast_channel_unlock, ast_channel_unref, ast_clear_flag, AST_CONTROL_HOLD, AST_CONTROL_RINGING, ast_copy_string(), ast_debug, AST_DEVICE_INUSE, AST_FLAG_MASQ_NOSTREAM, ast_free_ptr(), ast_indicate(), ast_indicate_data(), AST_LIST_UNLOCK, ast_log(), ast_manager_event, AST_MAX_CONTEXT, AST_MAX_EXTENSION, AST_PARK_OPT_RINGING, AST_PARK_OPT_SILENCE, ast_say_digits(), ast_set_flag, ast_strdup, ast_strlen_zero(), ast_test_flag, ast_tvnow(), ast_verb, ast_channel::caller, ast_parkinglot::cfg, parkeduser::chan, ast_channel::connected, parkeduser::context, ast_channel::context, ast_channel::data, EVENT_FLAG_CALL, parkeduser::exten, ast_channel::exten, ast_park_call_args::extout, parkeduser::hold_method, ast_party_caller::id, ast_party_connected_line::id, if(), ast_channel::language, LOG_ERROR, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, parkinglot_cfg::mohclass, ast_party_id::name, ast_parkinglot::name, ast_channel::name, notify_metermaids(), parkeduser::notquiteyet, ast_party_id::number, parkeduser::options_specified, ast_park_call_args::orig_chan_name, park_space_reserve(), parkinglot_cfg::parking_con, parking_thread, parkeduser::parkingexten, parkeduser::parkinglot, parkeduser::parkingnum, ast_parkinglot::parkings, parkeduser::parkingtime, parkinglot_cfg::parkingtime, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), parkeduser::peername, parkeduser::priority, ast_channel::priority, ast_park_call_args::pu, registrar, ast_park_call_args::return_con, ast_park_call_args::return_ext, ast_park_call_args::return_pri, S_COR, S_OR, parkeduser::start, ast_party_name::str, ast_party_number::str, ast_channel::tech, ast_park_call_args::timeout, ast_channel_tech::type, ast_channel::uniqueid, ast_party_name::valid, and ast_party_number::valid.

Referenced by ast_park_call(), ast_park_call_exten(), and masq_park_call().

1471 {
1472  struct parkeduser *pu = args->pu;
1473  const char *event_from; /*!< Channel name that is parking the call. */
1474  char app_data[AST_MAX_EXTENSION + AST_MAX_CONTEXT];
1475 
1476  if (pu == NULL) {
1477  args->pu = pu = park_space_reserve(chan, peer, args);
1478  if (pu == NULL) {
1479  return -1;
1480  }
1481  }
1482 
1483  chan->appl = "Parked Call";
1484  chan->data = NULL;
1485 
1486  pu->chan = chan;
1487 
1488  /* Put the parked channel on hold if we have two different channels */
1489  if (chan != peer) {
1490  if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
1493  } else {
1496  S_OR(pu->parkinglot->cfg.mohclass, NULL),
1497  !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
1498  }
1499  }
1500 
1501  pu->start = ast_tvnow();
1502  pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->cfg.parkingtime;
1503  if (args->extout)
1504  *(args->extout) = pu->parkingnum;
1505 
1506  if (peer) {
1507  event_from = S_OR(args->orig_chan_name, peer->name);
1508 
1509  /*
1510  * This is so ugly that it hurts, but implementing
1511  * get_base_channel() on local channels could have ugly side
1512  * effects. We could have
1513  * transferer<->local,1<->local,2<->parking and we need the
1514  * callback name to be that of transferer. Since local,1/2 have
1515  * the same name we can be tricky and just grab the bridged
1516  * channel from the other side of the local.
1517  */
1518  if (!strcasecmp(peer->tech->type, "Local")) {
1519  struct ast_channel *tmpchan, *base_peer;
1520  char other_side[AST_CHANNEL_NAME];
1521  char *c;
1522 
1523  ast_copy_string(other_side, event_from, sizeof(other_side));
1524  if ((c = strrchr(other_side, ';'))) {
1525  *++c = '1';
1526  }
1527  if ((tmpchan = ast_channel_get_by_name(other_side))) {
1528  ast_channel_lock(tmpchan);
1529  if ((base_peer = ast_bridged_channel(tmpchan))) {
1530  ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
1531  }
1532  ast_channel_unlock(tmpchan);
1533  tmpchan = ast_channel_unref(tmpchan);
1534  }
1535  } else {
1536  ast_copy_string(pu->peername, event_from, sizeof(pu->peername));
1537  }
1538  } else {
1539  event_from = S_OR(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"), chan->name);
1540  }
1541 
1542  /*
1543  * Remember what had been dialed, so that if the parking
1544  * expires, we try to come back to the same place
1545  */
1547 
1548  /*
1549  * If extension has options specified, they override all other
1550  * possibilities such as the returntoorigin flag and transferred
1551  * context. Information on extension options is lost here, so
1552  * we set a flag
1553  */
1554  ast_copy_string(pu->context,
1555  S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)),
1556  sizeof(pu->context));
1557  ast_copy_string(pu->exten,
1558  S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)),
1559  sizeof(pu->exten));
1560  pu->priority = args->return_pri ? args->return_pri :
1561  (chan->macropriority ? chan->macropriority : chan->priority);
1562 
1563  /* Mark channel as parked */
1564  pbx_builtin_setvar_helper(pu->chan, "PARKED_CALL", "1");
1565 
1566  /*
1567  * If parking a channel directly, don't quite yet get parking
1568  * running on it. All parking lot entries are put into the
1569  * parking lot with notquiteyet on.
1570  */
1571  if (peer != chan) {
1572  pu->notquiteyet = 0;
1573  }
1574 
1575  /* Wake up the (presumably select()ing) thread */
1576  pthread_kill(parking_thread, SIGURG);
1577  ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n",
1578  chan->name, pu->parkingnum, pu->parkinglot->name,
1579  pu->context, pu->exten, pu->priority, (pu->parkingtime / 1000));
1580 
1581  ast_cel_report_event(chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
1582 
1583  ast_manager_event(chan, EVENT_FLAG_CALL, "ParkedCall",
1584  "Exten: %s\r\n"
1585  "Channel: %s\r\n"
1586  "Parkinglot: %s\r\n"
1587  "From: %s\r\n"
1588  "Timeout: %ld\r\n"
1589  "CallerIDNum: %s\r\n"
1590  "CallerIDName: %s\r\n"
1591  "ConnectedLineNum: %s\r\n"
1592  "ConnectedLineName: %s\r\n"
1593  "Uniqueid: %s\r\n",
1594  pu->parkingexten, chan->name, pu->parkinglot->name, event_from,
1595  (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
1596  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"),
1597  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>"),
1598  S_COR(chan->connected.id.number.valid, chan->connected.id.number.str, "<unknown>"),
1599  S_COR(chan->connected.id.name.valid, chan->connected.id.name.str, "<unknown>"),
1600  chan->uniqueid
1601  );
1602  ast_debug(4, "peer->name: %s\n", peer ? peer->name : "-No peer-");
1603  ast_debug(4, "args->orig_chan_name: %s\n", args->orig_chan_name ? args->orig_chan_name : "-none-");
1604  ast_debug(4, "pu->peername: %s\n", pu->peername);
1605  ast_debug(4, "AMI ParkedCall Channel: %s\n", chan->name);
1606  ast_debug(4, "AMI ParkedCall From: %s\n", event_from);
1607 
1608  if (peer && adsipark && ast_adsi_available(peer)) {
1609  adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
1611  }
1612 
1613  snprintf(app_data, sizeof(app_data), "%s,%s", pu->parkingexten,
1614  pu->parkinglot->name);
1616  NULL, NULL, parkedcall, ast_strdup(app_data), ast_free_ptr, registrar)) {
1617  ast_log(LOG_ERROR, "Could not create parked call exten: %s@%s\n",
1619  } else {
1621  }
1622 
1624 
1625  /* Only say number if it's a number and the channel hasn't been masqueraded away */
1626  if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE)
1627  && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
1628  /*
1629  * If a channel is masqueraded into peer while playing back the
1630  * parking space number do not continue playing it back. This
1631  * is the case if an attended transfer occurs.
1632  */
1634  /* Tell the peer channel the number of the parking space */
1635  ast_say_digits(peer, pu->parkingnum, "", peer->language);
1637  }
1638  if (peer == chan) { /* pu->notquiteyet = 1 */
1639  /* Wake up parking thread if we're really done */
1640  if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
1643  } else {
1646  S_OR(pu->parkinglot->cfg.mohclass, NULL),
1647  !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
1648  }
1649  pu->notquiteyet = 0;
1650  pthread_kill(parking_thread, SIGURG);
1651  }
1652  return 0;
1653 }
char context[AST_MAX_CONTEXT]
Definition: features.c:475
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
static const char * parkedcall
Definition: features.c:419
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
const char *const type
Definition: channel.h:508
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int priority
Definition: channel.h:841
const ast_string_field uniqueid
Definition: channel.h:787
#define ast_strdup(a)
Definition: astmm.h:109
char exten[AST_MAX_EXTENSION]
Definition: features.c:476
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
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
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define EVENT_FLAG_CALL
Definition: manager.h:72
struct ast_channel * chan
Definition: features.c:471
char * str
Subscriber name (Malloced)
Definition: channel.h:214
int ast_say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang)
says digits
Definition: channel.c:8409
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
const char * orig_chan_name
Definition: features.c:1144
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
const char * data
Definition: channel.h:755
void ast_free_ptr(void *ptr)
#define ast_verb(level,...)
Definition: logger.h:243
const char * appl
Definition: channel.h:754
const char * return_con
Definition: features.c:1145
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
struct parkeduser * pu
Definition: features.c:1150
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
int priority
Definition: features.c:477
unsigned int options_specified
Definition: features.c:482
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
Announce call parking by ADSI.
Definition: features.c:1063
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
Description of one parked call, added to a list while active, then removed. The list belongs to a par...
Definition: features.c:470
int macropriority
Definition: channel.h:842
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_MAX_EXTENSION
Definition: channel.h:135
#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
const char * return_ext
Definition: features.c:1146
static pthread_t parking_thread
Definition: features.c:648
a channel is parked
Definition: cel.h:70
#define LOG_ERROR
Definition: logger.h:155
struct parkinglot_cfg cfg
Definition: features.c:560
static struct parkeduser * park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
Definition: features.c:1299
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_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
#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
struct timeval start
Definition: features.c:472
enum ast_control_frame_type hold_method
Definition: features.c:480
static char * registrar
Definition: features.c:623
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
#define ast_clear_flag(p, flag)
Definition: utils.h:77
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
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
struct ast_parkinglot::parkinglot_parklist parkings
static int adsipark
Definition: features.c:612
char parkingexten[AST_MAX_EXTENSION]
Definition: features.c:474
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:8691
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_parkinglot * parkinglot
Definition: features.c:486
#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
char name[AST_MAX_CONTEXT]
Definition: features.c:558
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
Notify metermaids that we&#39;ve changed an extension.
Definition: features.c:1096
int parkingnum
Definition: features.c:473
int ast_adsi_unload_session(struct ast_channel *chan)
Definition: adsi.c:87
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
char peername[AST_CHANNEL_NAME]
Definition: features.c:483
struct ast_channel_tech * tech
Definition: channel.h:743
unsigned int notquiteyet
Definition: features.c:481
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
int parkingtime
Definition: features.c:478
const ast_string_field language
Definition: channel.h:787
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
char mohclass[MAX_MUSICCLASS]
Definition: features.c:493
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static void park_space_abort ( struct parkeduser pu)
static

Definition at line 1272 of file features.c.

References ast_free, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_parkinglot::next_parking_space, parkinglot, parkeduser::parkinglot, parkinglot_unref(), and ast_parkinglot::parkings.

Referenced by masq_park_call().

1273 {
1274  struct ast_parkinglot *parkinglot;
1275 
1276  parkinglot = pu->parkinglot;
1277 
1278  /* Put back the parking space just allocated. */
1279  --parkinglot->next_parking_space;
1280 
1281  AST_LIST_REMOVE(&parkinglot->parkings, pu, list);
1282 
1283  AST_LIST_UNLOCK(&parkinglot->parkings);
1284  parkinglot_unref(parkinglot);
1285  ast_free(pu);
1286 }
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:841
Structure for parking lots which are put in a container.
Definition: features.c:556
int next_parking_space
Definition: features.c:563
#define ast_free(a)
Definition: astmm.h:97
struct ast_parkinglot::parkinglot_parklist parkings
struct ast_parkinglot * parkinglot
Definition: features.c:486
static struct parkeduser* park_space_reserve ( struct ast_channel park_me,
struct ast_channel parker,
struct ast_park_call_args args 
)
static
Note
The API forces us to specify a numeric parking slot, even though the architecture would tend to support non-numeric extensions (as are possible with SIP, for example). Hence, we enforce that limitation here. If extout was not numeric, we could permit arbitrary non-numeric extensions.

Definition at line 1299 of file features.c.

References ast_calloc, ast_debug, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_PARK_OPT_RANDOMIZE, ast_random(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_parkinglot::cfg, create_dynamic_parkinglot(), default_parkinglot, ast_parkinglot::disabled, find_parkinglot(), findparkinglotname(), parkinglot_cfg::is_invalid, LOG_WARNING, ast_parkinglot::name, ast_channel::name, ast_parkinglot::next_parking_space, parkeduser::notquiteyet, parkeddynamic, parkinglot_cfg::parkfindnext, parkinglot_cfg::parking_start, parkinglot_cfg::parking_stop, parkeduser::parkingexten, parkinglot, parkeduser::parkinglot, ast_park_call_args::parkinglot, parkinglot_addref(), parkinglot_unref(), parkeduser::parkingnum, ast_parkinglot::parkings, pbx_builtin_getvar_helper(), and S_OR.

Referenced by masq_park_call(), and park_call_full().

1300 {
1301  struct parkeduser *pu;
1302  int i;
1303  int parking_space = -1;
1304  const char *parkinglotname;
1305  const char *parkingexten;
1306  struct parkeduser *cur;
1307  struct ast_parkinglot *parkinglot = NULL;
1308 
1309  if (args->parkinglot) {
1310  parkinglot = parkinglot_addref(args->parkinglot);
1311  parkinglotname = parkinglot->name;
1312  } else {
1313  if (parker) {
1314  parkinglotname = findparkinglotname(parker);
1315  } else { /* parker was NULL, check park_me (ParkAndAnnounce / res_agi) */
1316  parkinglotname = findparkinglotname(park_me);
1317  }
1318  if (!ast_strlen_zero(parkinglotname)) {
1319  parkinglot = find_parkinglot(parkinglotname);
1320  } else {
1321  /* Parking lot is not specified, so use the default parking lot. */
1322  ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
1323  parkinglot = parkinglot_addref(default_parkinglot);
1324  }
1325  }
1326 
1327  /* Dynamically create parkinglot */
1328  if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
1329  parkinglot = create_dynamic_parkinglot(parkinglotname, park_me);
1330  }
1331 
1332  if (!parkinglot) {
1333  ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", park_me->name);
1334  return NULL;
1335  }
1336 
1337  ast_debug(1, "Parking lot: %s\n", parkinglot->name);
1338  if (parkinglot->disabled || parkinglot->cfg.is_invalid) {
1339  ast_log(LOG_WARNING, "Parking lot %s is not in a useable state.\n",
1340  parkinglot->name);
1341  parkinglot_unref(parkinglot);
1342  return NULL;
1343  }
1344 
1345  /* Allocate memory for parking data */
1346  if (!(pu = ast_calloc(1, sizeof(*pu)))) {
1347  parkinglot_unref(parkinglot);
1348  return NULL;
1349  }
1350 
1351  /* Lock parking list */
1352  AST_LIST_LOCK(&parkinglot->parkings);
1353 
1354  /* Check for channel variable PARKINGEXTEN */
1355  parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(park_me, "PARKINGEXTEN"), ""));
1356  if (!ast_strlen_zero(parkingexten)) {
1357  /*!
1358  * \note The API forces us to specify a numeric parking slot, even
1359  * though the architecture would tend to support non-numeric extensions
1360  * (as are possible with SIP, for example). Hence, we enforce that
1361  * limitation here. If extout was not numeric, we could permit
1362  * arbitrary non-numeric extensions.
1363  */
1364  if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space <= 0) {
1365  ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n",
1366  parkingexten);
1367  AST_LIST_UNLOCK(&parkinglot->parkings);
1368  parkinglot_unref(parkinglot);
1369  ast_free(pu);
1370  return NULL;
1371  }
1372 
1373  if (parking_space < parkinglot->cfg.parking_start
1374  || parkinglot->cfg.parking_stop < parking_space) {
1375  /*
1376  * Cannot allow park because parking lots are not setup for
1377  * spaces outside of the lot. (Things like dialplan hints don't
1378  * exist for outside lot space.)
1379  */
1380  ast_log(LOG_WARNING, "PARKINGEXTEN=%d is not in %s (%d-%d).\n",
1381  parking_space, parkinglot->name, parkinglot->cfg.parking_start,
1382  parkinglot->cfg.parking_stop);
1383  AST_LIST_UNLOCK(&parkinglot->parkings);
1384  parkinglot_unref(parkinglot);
1385  ast_free(pu);
1386  return NULL;
1387  }
1388 
1389  /* Check if requested parking space is in use. */
1390  AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1391  if (cur->parkingnum == parking_space) {
1392  ast_log(LOG_WARNING, "PARKINGEXTEN=%d is already in use in %s\n",
1393  parking_space, parkinglot->name);
1394  AST_LIST_UNLOCK(&parkinglot->parkings);
1395  parkinglot_unref(parkinglot);
1396  ast_free(pu);
1397  return NULL;
1398  }
1399  }
1400  } else {
1401  /* PARKINGEXTEN is empty, so find a usable extension in the lot to park the call */
1402  int start; /* The first slot we look in the parkinglot. It can be randomized. */
1403  int start_checked = 0; /* flag raised once the first slot is checked */
1404 
1405  /* If using randomize mode, set start to random position on parking range */
1407  start = ast_random() % (parkinglot->cfg.parking_stop - parkinglot->cfg.parking_start + 1);
1408  start += parkinglot->cfg.parking_start;
1409  } else if (parkinglot->cfg.parkfindnext
1410  && parkinglot->cfg.parking_start <= parkinglot->next_parking_space
1411  && parkinglot->next_parking_space <= parkinglot->cfg.parking_stop) {
1412  /* Start looking with the next parking space in the lot. */
1413  start = parkinglot->next_parking_space;
1414  } else {
1415  /* Otherwise, just set it to the start position. */
1416  start = parkinglot->cfg.parking_start;
1417  }
1418 
1419  /* free parking extension linear search: O(n^2) */
1420  for (i = start; ; i++) {
1421  /* If we are past the end, wrap around to the first parking slot*/
1422  if (i == parkinglot->cfg.parking_stop + 1) {
1423  i = parkinglot->cfg.parking_start;
1424  }
1425 
1426  if (i == start) {
1427  /* At this point, if start_checked, we've exhausted all the possible slots. */
1428  if (start_checked) {
1429  break;
1430  } else {
1431  start_checked = 1;
1432  }
1433  }
1434 
1435  /* Search the list of parked calls already in use for i. If we find it, it's in use. */
1436  AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1437  if (cur->parkingnum == i) {
1438  break;
1439  }
1440  }
1441  if (!cur) {
1442  /* We found a parking space. */
1443  parking_space = i;
1444  break;
1445  }
1446  }
1447  if (parking_space == -1) {
1448  /* We did not find a parking space. Lot is full. */
1449  ast_log(LOG_WARNING, "No more parking spaces in %s\n", parkinglot->name);
1450  AST_LIST_UNLOCK(&parkinglot->parkings);
1451  parkinglot_unref(parkinglot);
1452  ast_free(pu);
1453  return NULL;
1454  }
1455  }
1456 
1457  /* Prepare for next parking space search. */
1458  parkinglot->next_parking_space = parking_space + 1;
1459 
1460  snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
1461  pu->notquiteyet = 1;
1462  pu->parkingnum = parking_space;
1463  pu->parkinglot = parkinglot;
1464  AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
1465 
1466  return pu;
1467 }
int parking_stop
Definition: features.c:501
static struct ast_parkinglot * parkinglot_addref(struct ast_parkinglot *parkinglot)
Definition: features.c:5435
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static struct ast_parkinglot * default_parkinglot
Default parking lot.
Definition: features.c:582
static const char * findparkinglotname(struct ast_channel *chan)
Find parking lot name from channel.
Definition: features.c:1082
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
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
unsigned int is_invalid
Definition: features.c:552
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
Description of one parked call, added to a list while active, then removed. The list belongs to a par...
Definition: features.c:470
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
long int ast_random(void)
Definition: utils.c:1640
static int parkeddynamic
Definition: features.c:588
int parking_start
Definition: features.c:499
unsigned int disabled
Definition: features.c:568
Structure for parking lots which are put in a container.
Definition: features.c:556
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
struct parkinglot_cfg cfg
Definition: features.c:560
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 next_parking_space
Definition: features.c:563
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:97
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
unsigned int parkfindnext
Definition: features.c:546
struct ast_parkinglot::parkinglot_parklist parkings
char parkingexten[AST_MAX_EXTENSION]
Definition: features.c:474
#define ast_calloc(a, b)
Definition: astmm.h:82
struct ast_parkinglot * parkinglot
Definition: features.c:486
#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
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
Definition: features.c:5017
int parkingnum
Definition: features.c:473
unsigned int notquiteyet
Definition: features.c:481
static int parked_call_exec ( struct ast_channel chan,
const char *  data 
)
static

Pickup parked call.

< Parking lot space to retrieve if present.

< Parking lot name to use if present.

< Place to put any remaining args string.

Definition at line 5173 of file features.c.

References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_bridge_call(), ast_cdr_setdestchan(), AST_CEL_PARK_END, ast_cel_report_event(), ast_channel_connected_line_macro(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_unlock, ast_channel_update_connected_line(), ast_connected_line_copy_from_caller(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, ast_context_find(), ast_context_remove_extension2(), AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_flags, AST_DECLARE_APP_ARGS, AST_DEVICE_NOT_INUSE, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_FLAG_BYBOTH, AST_FEATURE_FLAG_BYCALLEE, AST_FEATURE_FLAG_BYCALLER, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, AST_FLAGS_ALL, ast_free, ast_hangup(), ast_indicate(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_manager_event, ast_party_connected_line_free(), ast_party_connected_line_init(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_verb, ast_channel::caller, ast_channel::cdr, ast_parkinglot::cfg, parkeduser::chan, ast_channel::connected, courtesytone, ast_datastore::data, default_parkinglot, dial_features_info, EVENT_FLAG_CALL, ast_bridge_config::features_callee, ast_bridge_config::features_caller, find_parkinglot(), findparkinglotname(), parkeduser::hold_method, ast_party_caller::id, ast_party_connected_line::id, LOG_WARNING, ast_dial_features::my_features, ast_party_id::name, ast_parkinglot::name, ast_channel::name, notify_metermaids(), parkeduser::notquiteyet, ast_party_id::number, parkinglot_cfg::parkedcallhangup, parkinglot_cfg::parkedcallrecording, parkinglot_cfg::parkedcallreparking, parkinglot_cfg::parkedcalltransfers, parkedplay, parkinglot_cfg::parking_con, parkeduser::parkingexten, parkinglot, parkeduser::parkinglot, parkinglot_addref(), parkinglot_unref(), parkeduser::parkingnum, ast_parkinglot::parkings, parse(), ast_channel::pbx, pbx_builtin_setvar_helper(), play_message_to_chans(), S_COR, ast_party_connected_line::source, ast_party_name::str, ast_party_number::str, ast_channel::uniqueid, ast_party_name::valid, and ast_party_number::valid.

Referenced by ast_features_init().

5174 {
5175  int res;
5176  struct ast_channel *peer = NULL;
5177  struct parkeduser *pu;
5178  struct ast_context *con;
5179  char *parse;
5180  const char *pl_name;
5181  unsigned int park = 0;
5182  struct ast_bridge_config config;
5183  struct ast_parkinglot *parkinglot;
5184  AST_DECLARE_APP_ARGS(app_args,
5185  AST_APP_ARG(pl_space); /*!< Parking lot space to retrieve if present. */
5186  AST_APP_ARG(pl_name); /*!< Parking lot name to use if present. */
5187  AST_APP_ARG(dummy); /*!< Place to put any remaining args string. */
5188  );
5189 
5190  parse = ast_strdupa(data);
5191  AST_STANDARD_APP_ARGS(app_args, parse);
5192 
5193  if (!ast_strlen_zero(app_args.pl_space)) {
5194  if (sscanf(app_args.pl_space, "%30u", &park) != 1) {
5195  ast_log(LOG_WARNING, "Specified parking extension not a number: %s\n",
5196  app_args.pl_space);
5197  park = -1;
5198  }
5199  }
5200 
5201  if (!ast_strlen_zero(app_args.pl_name)) {
5202  pl_name = app_args.pl_name;
5203  } else {
5204  pl_name = findparkinglotname(chan);
5205  }
5206  if (ast_strlen_zero(pl_name)) {
5207  /* Parking lot is not specified, so use the default parking lot. */
5208  parkinglot = parkinglot_addref(default_parkinglot);
5209  } else {
5210  parkinglot = find_parkinglot(pl_name);
5211  if (!parkinglot) {
5212  /* It helps to answer the channel if not already up. :) */
5213  if (chan->_state != AST_STATE_UP) {
5214  ast_answer(chan);
5215  }
5216  if (ast_stream_and_wait(chan, "pbx-invalidpark", "")) {
5217  ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n",
5218  "pbx-invalidpark", chan->name);
5219  }
5221  "Channel %s tried to retrieve parked call from unknown parking lot '%s'\n",
5222  chan->name, pl_name);
5223  return -1;
5224  }
5225  }
5226 
5227  AST_LIST_LOCK(&parkinglot->parkings);
5228  AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
5229  if ((ast_strlen_zero(app_args.pl_space) || pu->parkingnum == park)
5230  && !pu->notquiteyet && !pu->chan->pbx) {
5231  /* The parking space has a call and can be picked up now. */
5233  break;
5234  }
5235  }
5237  if (pu) {
5238  /* Found a parked call to pickup. */
5239  peer = pu->chan;
5240  con = ast_context_find(parkinglot->cfg.parking_con);
5241  if (con) {
5242  if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
5243  ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
5244  } else {
5246  }
5247  } else {
5248  ast_log(LOG_WARNING, "Whoa, no parking context?\n");
5249  }
5250 
5251  ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "UnParkedCall", chan);
5252  ast_manager_event(pu->chan, EVENT_FLAG_CALL, "UnParkedCall",
5253  "Exten: %s\r\n"
5254  "Channel: %s\r\n"
5255  "Parkinglot: %s\r\n"
5256  "From: %s\r\n"
5257  "CallerIDNum: %s\r\n"
5258  "CallerIDName: %s\r\n"
5259  "ConnectedLineNum: %s\r\n"
5260  "ConnectedLineName: %s\r\n"
5261  "Uniqueid: %s\r\n",
5262  pu->parkingexten, pu->chan->name, pu->parkinglot->name, chan->name,
5263  S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
5264  S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
5265  S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
5266  S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
5267  pu->chan->uniqueid
5268  );
5269 
5270  /* Stop entertaining the caller. */
5271  switch (pu->hold_method) {
5272  case AST_CONTROL_HOLD:
5274  break;
5275  case AST_CONTROL_RINGING:
5276  ast_indicate(pu->chan, -1);
5277  break;
5278  default:
5279  break;
5280  }
5281  pu->hold_method = 0;
5282 
5284  ast_free(pu);
5285  }
5286  AST_LIST_UNLOCK(&parkinglot->parkings);
5287 
5288  if (peer) {
5289  /* Update connected line between retrieving call and parked call. */
5291 
5293 
5294  /* Send our caller-id to peer. */
5295  ast_channel_lock(chan);
5297  ast_channel_unlock(chan);
5299  if (ast_channel_connected_line_macro(chan, peer, &connected, 0, 0)) {
5301  }
5302 
5303  /*
5304  * Get caller-id from peer.
5305  *
5306  * Update the retrieving call before it is answered if possible
5307  * for best results. Some phones do not support updating the
5308  * connected line information after connection.
5309  */
5310  ast_channel_lock(peer);
5312  ast_channel_unlock(peer);
5314  if (ast_channel_connected_line_macro(peer, chan, &connected, 1, 0)) {
5316  }
5317 
5319  }
5320 
5321  /* JK02: it helps to answer the channel if not already up */
5322  if (chan->_state != AST_STATE_UP) {
5323  ast_answer(chan);
5324  }
5325 
5326  if (peer) {
5327  struct ast_datastore *features_datastore;
5328  struct ast_dial_features *dialfeatures;
5329 
5330  /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
5331  if (!ast_strlen_zero(courtesytone)) {
5332  static const char msg[] = "courtesy tone";
5333 
5334  switch (parkedplay) {
5335  case 0:/* Courtesy tone to pickup chan */
5336  res = play_message_to_chans(chan, peer, -1, msg, courtesytone);
5337  break;
5338  case 1:/* Courtesy tone to parked chan */
5339  res = play_message_to_chans(chan, peer, 1, msg, courtesytone);
5340  break;
5341  case 2:/* Courtesy tone to both chans */
5342  res = play_message_to_chans(chan, peer, 0, msg, courtesytone);
5343  break;
5344  default:
5345  res = 0;
5346  break;
5347  }
5348  if (res) {
5349  ast_hangup(peer);
5350  parkinglot_unref(parkinglot);
5351  return -1;
5352  }
5353  }
5354 
5355  res = ast_channel_make_compatible(chan, peer);
5356  if (res < 0) {
5357  ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
5358  ast_hangup(peer);
5359  parkinglot_unref(parkinglot);
5360  return -1;
5361  }
5362  /* This runs sorta backwards, since we give the incoming channel control, as if it
5363  were the person called. */
5364  ast_verb(3, "Channel %s connected to parked call %u\n", chan->name, park);
5365 
5366  pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
5367  ast_cdr_setdestchan(chan->cdr, peer->name);
5368  memset(&config, 0, sizeof(struct ast_bridge_config));
5369 
5370  /* Get datastore for peer and apply it's features to the callee side of the bridge config */
5371  ast_channel_lock(peer);
5372  features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL);
5373  if (features_datastore && (dialfeatures = features_datastore->data)) {
5374  ast_copy_flags(&config.features_callee, &dialfeatures->my_features,
5375  AST_FLAGS_ALL);
5376  }
5377  ast_channel_unlock(peer);
5378 
5380  ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
5381  }
5383  ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
5384  }
5386  ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
5387  }
5389  ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
5390  }
5392  ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
5393  }
5395  ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
5396  }
5398  ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
5399  }
5401  ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
5402  }
5403 
5404  res = ast_bridge_call(chan, peer, &config);
5405 
5406  pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
5407  ast_cdr_setdestchan(chan->cdr, peer->name);
5408 
5409  /* Simulate the PBX hanging up */
5410  ast_hangup(peer);
5411  } else {
5412  if (ast_stream_and_wait(chan, "pbx-invalidpark", "")) {
5413  ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark",
5414  chan->name);
5415  }
5416  ast_verb(3, "Channel %s tried to retrieve nonexistent parked call %u\n",
5417  chan->name, park);
5418  res = -1;
5419  }
5420 
5421  parkinglot_unref(parkinglot);
5422  return res;
5423 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
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
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
static struct ast_parkinglot * parkinglot_addref(struct ast_parkinglot *parkinglot)
Definition: features.c:5435
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
Definition: features.c:2059
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static const char config[]
Definition: cdr_csv.c:57
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
const ast_string_field uniqueid
Definition: channel.h:787
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
#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
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
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
static struct ast_parkinglot * default_parkinglot
Default parking lot.
Definition: features.c:582
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define EVENT_FLAG_CALL
Definition: manager.h:72
struct ast_channel * chan
Definition: features.c:471
char * str
Subscriber name (Malloced)
Definition: channel.h:214
static int parkedplay
Definition: features.c:587
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
Definition: features.c:3960
int parkedcallreparking
Enable DTMF based parking on bridge when picking up parked calls.
Definition: features.c:523
struct ast_flags my_features
Definition: features.c:651
struct ast_cdr * cdr
Definition: channel.h:766
static const char * findparkinglotname(struct ast_channel *chan)
Find parking lot name from channel.
Definition: features.c:1082
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
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
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
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
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
#define ast_verb(level,...)
Definition: logger.h:243
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
Description of one parked call, added to a list while active, then removed. The list belongs to a par...
Definition: features.c:470
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
bridge configuration
Definition: channel.h:974
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#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
static struct ast_datastore_info dial_features_info
Definition: features.c:752
Structure for parking lots which are put in a container.
Definition: features.c:556
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
struct parkinglot_cfg cfg
Definition: features.c:560
enum ast_channel_state _state
Definition: channel.h:839
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
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static char courtesytone[256]
Definition: features.c:589
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define ast_free(a)
Definition: astmm.h:97
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
#define AST_FLAGS_ALL
Definition: utils.h:196
enum ast_control_frame_type hold_method
Definition: features.c:480
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
int parkedcallrecording
Enable DTMF based recording on a bridge when picking up parked calls.
Definition: features.c:543
struct ast_parkinglot::parkinglot_parklist parkings
int parkedcalltransfers
Enable DTMF based transfers on bridge when picking up parked calls.
Definition: features.c:513
char parkingexten[AST_MAX_EXTENSION]
Definition: features.c:474
void * data
Definition: datastore.h:56
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
Definition: channel.c:5970
int parkedcallhangup
Enable DTMF based hangup on a bridge when pickup up parked calls.
Definition: features.c:533
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
struct ast_parkinglot * parkinglot
Definition: features.c:486
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
channel out of the park
Definition: cel.h:72
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Definition: pbx.c:6144
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
Definition: features.c:5017
static int connected
Definition: cdr_pgsql.c:57
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
Notify metermaids that we&#39;ve changed an extension.
Definition: features.c:1096
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
int parkingnum
Definition: features.c:473
ast_context: An extension context
Definition: pbx.c:955
void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan)
Set the destination channel, if there was one.
Definition: cdr.c:812
unsigned int notquiteyet
Definition: features.c:481
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2971
struct ast_pbx * pbx
Definition: channel.h:761
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int parkinglot_activate ( struct ast_parkinglot parkinglot)
static

Definition at line 5640 of file features.c.

References ast_add_extension(), ast_context_find_or_create(), AST_DEVICE_INUSE, ast_free_ptr(), ast_log(), AST_MAX_CONTEXT, ast_strdup, ast_parkinglot::cfg, ast_parkinglot::disabled, LOG_ERROR, ast_parkinglot::name, notify_metermaids(), park_add_hints(), parkinglot_cfg::parkaddhints, parkcall, parkinglot_cfg::parkext, parkinglot_cfg::parkext_exclusive, parkinglot_cfg::parking_con, parkinglot_cfg::parking_start, parkinglot_cfg::parking_stop, and registrar.

Referenced by create_dynamic_parkinglot(), and parkinglot_activate_cb().

5641 {
5642  int disabled = 0;
5643  char app_data[5 + AST_MAX_CONTEXT];
5644 
5645  /* Create Park option list. Must match with struct park_app_args options. */
5646  if (parkinglot->cfg.parkext_exclusive) {
5647  /* Specify the parking lot this parking extension parks calls. */
5648  snprintf(app_data, sizeof(app_data), ",,,,,%s", parkinglot->name);
5649  } else {
5650  /* The dialplan must specify which parking lot to use. */
5651  app_data[0] = '\0';
5652  }
5653 
5654  /* Create context */
5655  if (!ast_context_find_or_create(NULL, NULL, parkinglot->cfg.parking_con, registrar)) {
5656  ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n",
5657  parkinglot->cfg.parking_con);
5658  disabled = 1;
5659 
5660  /* Add a parking extension into the context */
5661  } else if (ast_add_extension(parkinglot->cfg.parking_con, 1, parkinglot->cfg.parkext,
5662  1, NULL, NULL, parkcall, ast_strdup(app_data), ast_free_ptr, registrar)) {
5663  ast_log(LOG_ERROR, "Could not create parking lot %s access exten %s@%s\n",
5664  parkinglot->name, parkinglot->cfg.parkext, parkinglot->cfg.parking_con);
5665  disabled = 1;
5666  } else {
5667  /* Add parking hints */
5668  if (parkinglot->cfg.parkaddhints) {
5669  park_add_hints(parkinglot->cfg.parking_con, parkinglot->cfg.parking_start,
5670  parkinglot->cfg.parking_stop);
5671  }
5672 
5673  /*
5674  * XXX Not sure why we should need to notify the metermaids for
5675  * this exten. It was originally done for the default parking
5676  * lot entry exten only but should be done for all entry extens
5677  * if we do it for one.
5678  */
5679  /* Notify metermaids about parking lot entry exten state. */
5680  notify_metermaids(parkinglot->cfg.parkext, parkinglot->cfg.parking_con,
5682  }
5683 
5684  parkinglot->disabled = disabled;
5685  return disabled ? -1 : 0;
5686 }
int parking_stop
Definition: features.c:501
unsigned int parkaddhints
Definition: features.c:550
#define ast_strdup(a)
Definition: astmm.h:109
void ast_free_ptr(void *ptr)
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
unsigned int parkext_exclusive
Definition: features.c:548
int parking_start
Definition: features.c:499
unsigned int disabled
Definition: features.c:568
#define LOG_ERROR
Definition: logger.h:155
struct parkinglot_cfg cfg
Definition: features.c:560
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_MAX_CONTEXT
Definition: channel.h:136
char parkext[AST_MAX_EXTENSION]
Definition: features.c:495
static char * registrar
Definition: features.c:623
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:8691
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
Notify metermaids that we&#39;ve changed an extension.
Definition: features.c:1096
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:7726
static const char * parkcall
Definition: features.c:637
static void park_add_hints(const char *context, int start, int stop)
Add parking hints for all defined parking spaces.
Definition: features.c:5484
static int parkinglot_activate_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 6689 of file features.c.

References ast_debug, ast_log(), ast_parkinglot::cfg, force_reload_load, LOG_WARNING, ast_parkinglot::name, parkinglot_cfg::parking_start, parkinglot_cfg::parking_stop, parkinglot_activate(), and ast_parkinglot::the_mark.

Referenced by load_config().

6690 {
6691  struct ast_parkinglot *parkinglot = obj;
6692 
6693  if (parkinglot->the_mark) {
6694  /*
6695  * Don't activate a parking lot that still bears the_mark since
6696  * it is effectively deleted.
6697  */
6698  return 0;
6699  }
6700 
6701  if (parkinglot_activate(parkinglot)) {
6702  /*
6703  * The parking lot failed to activate. Allow reloading later to
6704  * see if that fixes it.
6705  */
6706  force_reload_load = 1;
6707  ast_log(LOG_WARNING, "Parking lot %s not open for business.\n", parkinglot->name);
6708  } else {
6709  ast_debug(1, "Parking lot %s now open for business. (parkpos %d-%d)\n",
6710  parkinglot->name, parkinglot->cfg.parking_start,
6711  parkinglot->cfg.parking_stop);
6712  }
6713 
6714  return 0;
6715 }
int parking_stop
Definition: features.c:501
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
#define LOG_WARNING
Definition: logger.h:144
unsigned int the_mark
Definition: features.c:566
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int parking_start
Definition: features.c:499
static int parkinglot_activate(struct ast_parkinglot *parkinglot)
Definition: features.c:5640
static int force_reload_load
Definition: features.c:585
Structure for parking lots which are put in a container.
Definition: features.c:556
struct parkinglot_cfg cfg
Definition: features.c:560
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
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ast_parkinglot * parkinglot_addref ( struct ast_parkinglot parkinglot)
static

Definition at line 5435 of file features.c.

References ao2_ref, ast_debug, ast_parkinglot::name, and parkinglot.

Referenced by create_dynamic_parkinglot(), park_call_exec(), park_space_reserve(), parked_call_exec(), and xfer_park_call_helper().

5436 {
5437  int refcount;
5438 
5439  refcount = ao2_ref(parkinglot, +1);
5440  ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
5441  return parkinglot;
5442 }
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define ao2_ref(o, delta)
Definition: astobj2.h:472
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static int parkinglot_cmp_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 869 of file features.c.

References CMP_MATCH, CMP_STOP, and ast_parkinglot::name.

Referenced by ast_features_init().

870 {
871  struct ast_parkinglot *parkinglot = obj;
872  struct ast_parkinglot *parkinglot2 = arg;
873 
874  return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
875 }
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
Structure for parking lots which are put in a container.
Definition: features.c:556
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static int parkinglot_config_read ( const char *  pl_name,
struct parkinglot_cfg cfg,
struct ast_variable var 
)
static

Definition at line 5546 of file features.c.

References ast_copy_string(), ast_log(), ast_strlen_zero(), ast_true(), ast_variable::file, parkinglot_cfg::is_invalid, ast_variable::lineno, LOG_WARNING, parkinglot_cfg::mohclass, ast_variable::name, ast_variable::next, parkinglot_cfg::parkaddhints, parkinglot_cfg::parkedcallhangup, parkinglot_cfg::parkedcallrecording, parkinglot_cfg::parkedcallreparking, parkinglot_cfg::parkedcalltransfers, parkinglot_cfg::parkext, parkinglot_cfg::parkext_exclusive, parkinglot_cfg::parkfindnext, parkinglot_cfg::parking_con, parkinglot_cfg::parking_start, parkinglot_cfg::parking_stop, parkinglot_feature_flag_cfg(), parkingretalertinfo, parkingretcidname, parkingretdahdiring, parkinglot_cfg::parkingtime, and ast_variable::value.

Referenced by build_parkinglot().

5547 {
5548  int error = 0;
5549 
5550  while (var) {
5551  if (!strcasecmp(var->name, "context")) {
5552  ast_copy_string(cfg->parking_con, var->value, sizeof(cfg->parking_con));
5553  } else if (!strcasecmp(var->name, "parkext")) {
5554  ast_copy_string(cfg->parkext, var->value, sizeof(cfg->parkext));
5555  } else if (!strcasecmp(var->name, "parkext_exclusive")) {
5556  cfg->parkext_exclusive = ast_true(var->value);
5557  } else if (!strcasecmp(var->name, "parkinghints")) {
5558  cfg->parkaddhints = ast_true(var->value);
5559  } else if (!strcasecmp(var->name, "parkedmusicclass")) {
5560  ast_copy_string(cfg->mohclass, var->value, sizeof(cfg->mohclass));
5561  } else if (!strcasecmp(var->name, "parkingtime")) {
5562  int parkingtime = 0;
5563 
5564  if ((sscanf(var->value, "%30d", &parkingtime) != 1) || parkingtime < 1) {
5565  ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
5566  error = -1;
5567  } else {
5568  cfg->parkingtime = parkingtime * 1000;
5569  }
5570  } else if (!strcasecmp(var->name, "parkpos")) {
5571  int start = 0;
5572  int end = 0;
5573 
5574  if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
5576  "Format for parking positions is a-b, where a and b are numbers at line %d of %s\n",
5577  var->lineno, var->file);
5578  error = -1;
5579  } else if (end < start || start <= 0 || end <= 0) {
5580  ast_log(LOG_WARNING, "Parking range is invalid. Must be a <= b, at line %d of %s\n",
5581  var->lineno, var->file);
5582  error = -1;
5583  } else {
5584  cfg->parking_start = start;
5585  cfg->parking_stop = end;
5586  }
5587  } else if (!strcasecmp(var->name, "findslot")) {
5588  cfg->parkfindnext = (!strcasecmp(var->value, "next"));
5589  } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
5590  parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcalltransfers, var);
5591  } else if (!strcasecmp(var->name, "parkedcallreparking")) {
5592  parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallreparking, var);
5593  } else if (!strcasecmp(var->name, "parkedcallhangup")) {
5594  parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallhangup, var);
5595  } else if (!strcasecmp(var->name, "parkedcallrecording")) {
5596  parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallrecording, var);
5597  } else if (!strcasecmp(var->name, "parkingretcidname")) {
5599  } else if (!strcasecmp(var->name, "parkingretdahdiring")) {
5601  } else if (!strcasecmp(var->name, "parkingretalertinfo")) {
5603  }
5604  var = var->next;
5605  }
5606 
5607  /* Check for configuration errors */
5608  if (ast_strlen_zero(cfg->parking_con)) {
5609  ast_log(LOG_WARNING, "Parking lot %s needs context\n", pl_name);
5610  error = -1;
5611  }
5612  if (ast_strlen_zero(cfg->parkext)) {
5613  ast_log(LOG_WARNING, "Parking lot %s needs parkext\n", pl_name);
5614  error = -1;
5615  }
5616  if (!cfg->parking_start) {
5617  ast_log(LOG_WARNING, "Parking lot %s needs parkpos\n", pl_name);
5618  error = -1;
5619  }
5620  if (error) {
5621  cfg->is_invalid = 1;
5622  }
5623 
5624  return error;
5625 }
int parking_stop
Definition: features.c:501
unsigned int parkaddhints
Definition: features.c:550
#define LOG_WARNING
Definition: logger.h:144
int lineno
Definition: config.h:87
int parkedcallreparking
Enable DTMF based parking on bridge when picking up parked calls.
Definition: features.c:523
static char parkingretdahdiring[3]
Definition: features.c:596
unsigned int is_invalid
Definition: features.c:552
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
const char * value
Definition: config.h:79
unsigned int parkext_exclusive
Definition: features.c:548
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int parking_start
Definition: features.c:499
const char * name
Definition: config.h:77
static char parkingretcidname[256]
Definition: features.c:595
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
const char * file
Definition: config.h:85
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
static char parkingretalertinfo[256]
Definition: features.c:597
char parkext[AST_MAX_EXTENSION]
Definition: features.c:495
unsigned int parkfindnext
Definition: features.c:546
static void parkinglot_feature_flag_cfg(const char *pl_name, int *param, struct ast_variable *var)
Definition: features.c:5523
int parkedcallrecording
Enable DTMF based recording on a bridge when picking up parked calls.
Definition: features.c:543
int parkedcalltransfers
Enable DTMF based transfers on bridge when picking up parked calls.
Definition: features.c:513
int parkedcallhangup
Enable DTMF based hangup on a bridge when pickup up parked calls.
Definition: features.c:533
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_variable * next
Definition: config.h:82
char mohclass[MAX_MUSICCLASS]
Definition: features.c:493
static void parkinglot_destroy ( void *  obj)
static

Destroy a parking lot.

Definition at line 5445 of file features.c.

References ast_assert, AST_LIST_EMPTY, AST_LIST_HEAD_DESTROY, and ast_parkinglot::parkings.

Referenced by create_parkinglot().

5446 {
5447  struct ast_parkinglot *doomed = obj;
5448 
5449  /*
5450  * No need to destroy parked calls here because any parked call
5451  * holds a parking lot reference. Therefore the parkings list
5452  * must be empty.
5453  */
5454  ast_assert(AST_LIST_EMPTY(&doomed->parkings));
5455  AST_LIST_HEAD_DESTROY(&doomed->parkings);
5456 }
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define ast_assert(a)
Definition: utils.h:738
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:638
Structure for parking lots which are put in a container.
Definition: features.c:556
struct ast_parkinglot::parkinglot_parklist parkings
static void parkinglot_feature_flag_cfg ( const char *  pl_name,
int *  param,
struct ast_variable var 
)
static

Definition at line 5523 of file features.c.

References ast_debug, AST_FEATURE_FLAG_BYBOTH, AST_FEATURE_FLAG_BYCALLEE, AST_FEATURE_FLAG_BYCALLER, ast_variable::name, and ast_variable::value.

Referenced by parkinglot_config_read().

5524 {
5525  ast_debug(1, "Setting parking lot %s %s to %s\n", pl_name, var->name, var->value);
5526  if (!strcasecmp(var->value, "both")) {
5527  *param = AST_FEATURE_FLAG_BYBOTH;
5528  } else if (!strcasecmp(var->value, "caller")) {
5529  *param = AST_FEATURE_FLAG_BYCALLER;
5530  } else if (!strcasecmp(var->value, "callee")) {
5531  *param = AST_FEATURE_FLAG_BYCALLEE;
5532  }
5533 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * value
Definition: config.h:79
const char * name
Definition: config.h:77
static int parkinglot_hash_cb ( const void *  obj,
const int  flags 
)
static

Definition at line 862 of file features.c.

References ast_str_case_hash(), and ast_parkinglot::name.

Referenced by ast_features_init().

863 {
864  const struct ast_parkinglot *parkinglot = obj;
865 
866  return ast_str_case_hash(parkinglot->name);
867 }
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
Structure for parking lots which are put in a container.
Definition: features.c:556
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:989
static int parkinglot_is_marked_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 6669 of file features.c.

References AST_LIST_EMPTY, ast_log(), CMP_MATCH, ast_parkinglot::disabled, force_reload_load, LOG_WARNING, ast_parkinglot::name, ast_parkinglot::parkings, and ast_parkinglot::the_mark.

Referenced by load_config().

6670 {
6671  struct ast_parkinglot *parkinglot = obj;
6672 
6673  if (parkinglot->the_mark) {
6674  if (AST_LIST_EMPTY(&parkinglot->parkings)) {
6675  /* This parking lot can actually be deleted. */
6676  return CMP_MATCH;
6677  }
6678  /* Try reloading later when parking lot is empty. */
6680  "Parking lot %s has parked calls. Could not remove.\n",
6681  parkinglot->name);
6682  parkinglot->disabled = 1;
6683  force_reload_load = 1;
6684  }
6685 
6686  return 0;
6687 }
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
#define LOG_WARNING
Definition: logger.h:144
unsigned int the_mark
Definition: features.c:566
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
static int force_reload_load
Definition: features.c:585
unsigned int disabled
Definition: features.c:568
Structure for parking lots which are put in a container.
Definition: features.c:556
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_parkinglot::parkinglot_parklist parkings
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static int parkinglot_markall_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 6661 of file features.c.

References ast_parkinglot::the_mark.

Referenced by load_config().

6662 {
6663  struct ast_parkinglot *parkinglot = obj;
6664 
6665  parkinglot->the_mark = 1;
6666  return 0;
6667 }
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
unsigned int the_mark
Definition: features.c:566
Structure for parking lots which are put in a container.
Definition: features.c:556
static void parkinglot_unref ( struct ast_parkinglot parkinglot)
static

Unreference parkinglot object.

Definition at line 5428 of file features.c.

References ao2_ref, ast_debug, and ast_parkinglot::name.

Referenced by ast_masq_park_call_exten(), ast_park_call_exten(), build_parkinglot(), create_dynamic_parkinglot(), manage_parkinglot(), manager_park(), park_call_exec(), park_space_abort(), park_space_reserve(), parked_call_exec(), and xfer_park_call_helper().

5429 {
5430  ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name,
5431  ao2_ref(parkinglot, 0) - 1);
5432  ao2_ref(parkinglot, -1);
5433 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define ao2_ref(o, delta)
Definition: astobj2.h:472
char name[AST_MAX_CONTEXT]
Definition: features.c:558
static struct ast_cdr* pick_unlocked_cdr ( struct ast_cdr cdr)
static

return the first unlocked cdr in a possible chain

Definition at line 3854 of file features.c.

References AST_CDR_FLAG_LOCKED, ast_test_flag, and ast_cdr::next.

Referenced by ast_bridge_call().

3855 {
3856  struct ast_cdr *cdr_orig = cdr;
3857  while (cdr) {
3859  return cdr;
3860  cdr = cdr->next;
3861  }
3862  return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
3863 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_cdr * next
Definition: cdr.h:132
Responsible for call detail data.
Definition: cdr.h:82
static int play_message_in_bridged_call ( struct ast_channel caller_chan,
struct ast_channel callee_chan,
const char *  audiofile 
)
static

Play message to both caller and callee in bridged call, plays synchronously, autoservicing the other channel during the message, so please don't use this for very long messages.

Definition at line 2078 of file features.c.

References play_message_to_chans().

Referenced by builtin_automonitor().

2079 {
2080  return play_message_to_chans(caller_chan, callee_chan, 0, "automon message",
2081  audiofile);
2082 }
static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
Definition: features.c:2059
static int play_message_on_chan ( struct ast_channel play_to,
struct ast_channel other,
const char *  msg,
const char *  audiofile 
)
static

Definition at line 2024 of file features.c.

References ast_autoservice_ignore(), ast_autoservice_start(), ast_autoservice_stop(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_stream_and_wait(), and LOG_WARNING.

Referenced by masq_park_call(), and play_message_to_chans().

2025 {
2026  /* Put other channel in autoservice. */
2027  if (ast_autoservice_start(other)) {
2028  return -1;
2029  }
2032  if (ast_stream_and_wait(play_to, audiofile, "")) {
2033  ast_log(LOG_WARNING, "Failed to play %s '%s'!\n", msg, audiofile);
2034  ast_autoservice_stop(other);
2035  return -1;
2036  }
2037  if (ast_autoservice_stop(other)) {
2038  return -1;
2039  }
2040  return 0;
2041 }
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
#define LOG_WARNING
Definition: logger.h:144
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
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 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 ast_autoservice_ignore(struct ast_channel *chan, enum ast_frame_type ftype)
Ignore certain frame types.
Definition: autoservice.c:307
static int play_message_to_chans ( struct ast_channel left,
struct ast_channel right,
int  which,
const char *  msg,
const char *  audiofile 
)
static

Definition at line 2059 of file features.c.

References play_message_on_chan().

Referenced by parked_call_exec(), and play_message_in_bridged_call().

2060 {
2061  /* First play the file to the left channel if requested. */
2062  if (which <= 0 && play_message_on_chan(left, right, msg, audiofile)) {
2063  return -1;
2064  }
2065 
2066  /* Then play the file to the right channel if requested. */
2067  if (which >= 0 && play_message_on_chan(right, left, msg, audiofile)) {
2068  return -1;
2069  }
2070 
2071  return 0;
2072 }
static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
Definition: features.c:2024
static void post_manager_event ( const char *  s,
struct parkeduser pu 
)
static

Output parking event to manager.

Definition at line 4629 of file features.c.

References ast_channel::caller, parkeduser::chan, ast_channel::connected, EVENT_FLAG_CALL, ast_party_caller::id, ast_party_connected_line::id, manager_event, ast_party_id::name, ast_parkinglot::name, ast_channel::name, ast_party_id::number, parkeduser::parkingexten, parkeduser::parkinglot, S_COR, ast_party_name::str, ast_party_number::str, ast_channel::uniqueid, ast_party_name::valid, and ast_party_number::valid.

Referenced by manage_parked_call().

4630 {
4632  "Exten: %s\r\n"
4633  "Channel: %s\r\n"
4634  "Parkinglot: %s\r\n"
4635  "CallerIDNum: %s\r\n"
4636  "CallerIDName: %s\r\n"
4637  "ConnectedLineNum: %s\r\n"
4638  "ConnectedLineName: %s\r\n"
4639  "UniqueID: %s\r\n",
4640  pu->parkingexten,
4641  pu->chan->name,
4642  pu->parkinglot->name,
4643  S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
4644  S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
4645  S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
4646  S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
4647  pu->chan->uniqueid
4648  );
4649 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
const ast_string_field uniqueid
Definition: channel.h:787
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
#define EVENT_FLAG_CALL
Definition: manager.h:72
struct ast_channel * chan
Definition: features.c:471
char * str
Subscriber name (Malloced)
Definition: channel.h:214
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#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
const ast_string_field name
Definition: channel.h:787
char parkingexten[AST_MAX_EXTENSION]
Definition: features.c:474
struct ast_parkinglot * parkinglot
Definition: features.c:486
char name[AST_MAX_CONTEXT]
Definition: features.c:558
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static void process_applicationmap_line ( struct ast_variable var)
static

Definition at line 5768 of file features.c.

References app, ast_call_feature::app, ast_call_feature::app_args, args, AST_APP_ARG, ast_calloc, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_FEATURE_FLAG_BYBOTH, AST_FEATURE_FLAG_BYCALLEE, AST_FEATURE_FLAG_BYCALLER, AST_FEATURE_FLAG_NEEDSDTMF, AST_FEATURE_FLAG_ONPEER, AST_FEATURE_FLAG_ONSELF, ast_free, ast_log(), ast_register_feature(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_set_flag, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_verb, ast_call_feature::exten, feature_group_exten::feature, FEATURE_APP_ARGS_LEN, FEATURE_APP_LEN, feature_exec_app(), FEATURE_EXTEN_LEN, FEATURE_MOH_LEN, FEATURE_SNAME_LEN, find_dynamic_feature(), LOG_NOTICE, LOG_WARNING, ast_call_feature::moh_class, ast_variable::name, ast_call_feature::operation, ast_call_feature::sname, strsep(), and ast_variable::value.

Referenced by process_config().

5769 {
5770  char *tmp_val = ast_strdupa(var->value);
5771  char *activateon, *new_syn;
5772  struct ast_call_feature *feature;
5774  AST_APP_ARG(exten);
5775  AST_APP_ARG(activatedby);
5776  AST_APP_ARG(app);
5779  );
5780 
5781  AST_STANDARD_APP_ARGS(args, tmp_val);
5782 
5783  activateon = strsep(&args.activatedby, "/");
5784 
5785  if (ast_strlen_zero(args.app)
5786  || ast_strlen_zero(args.exten)
5787  || ast_strlen_zero(activateon)
5788  || ast_strlen_zero(var->name)) {
5790  "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
5791  args.app, args.exten, activateon, var->name);
5792  return;
5793  }
5794 
5795  if ((new_syn = strchr(args.app, '('))) {
5796  /* New syntax */
5797  args.moh_class = args.app_args;
5798  args.app_args = new_syn;
5799  *args.app_args++ = '\0';
5800  if (args.app_args[strlen(args.app_args) - 1] == ')') {
5801  args.app_args[strlen(args.app_args) - 1] = '\0';
5802  }
5803  }
5804 
5806  if (find_dynamic_feature(var->name)) {
5808  ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n",
5809  var->name);
5810  return;
5811  }
5813 
5814  if (!(feature = ast_calloc(1, sizeof(*feature)))) {
5815  return;
5816  }
5817 
5818  ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
5819  ast_copy_string(feature->app, args.app, FEATURE_APP_LEN);
5820  ast_copy_string(feature->exten, args.exten, FEATURE_EXTEN_LEN);
5821 
5822  if (args.app_args) {
5823  ast_copy_string(feature->app_args, args.app_args, FEATURE_APP_ARGS_LEN);
5824  }
5825 
5826  if (args.moh_class) {
5827  ast_copy_string(feature->moh_class, args.moh_class, FEATURE_MOH_LEN);
5828  }
5829 
5830  ast_copy_string(feature->exten, args.exten, sizeof(feature->exten));
5831  feature->operation = feature_exec_app;
5833 
5834  /* Allow caller and callee to be specified for backwards compatability */
5835  if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller")) {
5837  } else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee")) {
5839  } else {
5840  ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
5841  " must be 'self', or 'peer'\n", var->name);
5842  ast_free(feature);
5843  return;
5844  }
5845 
5846  if (ast_strlen_zero(args.activatedby)) {
5848  } else if (!strcasecmp(args.activatedby, "caller")) {
5850  } else if (!strcasecmp(args.activatedby, "callee")) {
5852  } else if (!strcasecmp(args.activatedby, "both")) {
5854  } else {
5855  ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
5856  " must be 'caller', or 'callee', or 'both'\n", var->name);
5857  ast_free(feature);
5858  return;
5859  }
5860 
5861  ast_register_feature(feature);
5862 
5863  ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n",
5864  var->name, args.app, args.app_args, args.exten);
5865 }
char exten[FEATURE_MAX_LEN]
Definition: features.h:69
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
static struct ast_call_feature * find_dynamic_feature(const char *name)
find a call feature by name
Definition: features.c:3100
char * strsep(char **str, const char *delims)
static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
exec an app by feature
Definition: features.c:3179
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define FEATURE_APP_LEN
Definition: features.h:31
#define ast_verb(level,...)
Definition: logger.h:243
void ast_register_feature(struct ast_call_feature *feature)
register new feature into feature_set
Definition: features.c:2994
char app[FEATURE_APP_LEN]
Definition: features.h:73
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const char * value
Definition: config.h:79
static const char app[]
Definition: app_adsiprog.c:49
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char app_args[FEATURE_APP_ARGS_LEN]
Definition: features.h:74
const char * name
Definition: config.h:77
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
char moh_class[FEATURE_MOH_LEN]
Definition: features.h:75
static struct @350 args
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_free(a)
Definition: astmm.h:97
char sname[FEATURE_SNAME_LEN]
Definition: features.h:68
#define FEATURE_SNAME_LEN
Definition: features.h:33
#define FEATURE_MOH_LEN
Definition: features.h:35
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
ast_feature_operation operation
Definition: features.h:71
#define FEATURE_APP_ARGS_LEN
Definition: features.h:32
#define FEATURE_EXTEN_LEN
Definition: features.h:34
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int process_config ( struct ast_config cfg)
static

Definition at line 5867 of file features.c.

References adsipark, ARRAY_LEN, ast_category_browse(), ast_copy_string(), ast_debug, ast_find_call_feature(), ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_true(), ast_unregister_features(), ast_unregister_groups(), ast_variable_browse(), atxfercallbackretries, atxferdropcall, atxferloopdelay, atxfernoanswertimeout, build_parkinglot(), comebacktoorigin, courtesytone, DEFAULT_ATXFER_CALLBACK_RETRIES, DEFAULT_ATXFER_DROP_CALL, DEFAULT_ATXFER_LOOP_DELAY, DEFAULT_FEATURE_DIGIT_TIMEOUT, DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER, DEFAULT_PARKINGLOT, DEFAULT_TRANSFER_DIGIT_TIMEOUT, feature_group_exten::feature, featuredigittimeout, find_dynamic_feature(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, parkeddynamic, parkedplay, pickupfailsound, pickupsound, process_applicationmap_line(), register_group(), register_group_feature(), remap_feature(), transferdigittimeout, unmap_features(), ast_variable::value, var, xferfailsound, and xfersound.

Referenced by load_config().

5868 {
5869  int i;
5870  struct ast_variable *var = NULL;
5871  struct feature_group *fg = NULL;
5872  char *ctg;
5873  static const char * const categories[] = {
5874  /* Categories in features.conf that are not
5875  * to be parsed as group categories
5876  */
5877  "general",
5878  "featuremap",
5879  "applicationmap"
5880  };
5881 
5882  /* Set general features global defaults. */
5884 
5885  /* Set global call pickup defaults. */
5886  strcpy(pickup_ext, "*8");
5887  pickupsound[0] = '\0';
5888  pickupfailsound[0] = '\0';
5889 
5890  /* Set global call transfer defaults. */
5891  strcpy(xfersound, "beep");
5892  strcpy(xferfailsound, "beeperr");
5898 
5899  /* Set global call parking defaults. */
5900  comebacktoorigin = 1;
5901  courtesytone[0] = '\0';
5902  parkedplay = 0;
5903  adsipark = 0;
5904  parkeddynamic = 0;
5905 
5906  var = ast_variable_browse(cfg, "general");
5908  for (; var; var = var->next) {
5909  if (!strcasecmp(var->name, "parkeddynamic")) {
5910  parkeddynamic = ast_true(var->value);
5911  } else if (!strcasecmp(var->name, "adsipark")) {
5912  adsipark = ast_true(var->value);
5913  } else if (!strcasecmp(var->name, "transferdigittimeout")) {
5914  if ((sscanf(var->value, "%30d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
5915  ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
5917  } else {
5919  }
5920  } else if (!strcasecmp(var->name, "featuredigittimeout")) {
5921  if ((sscanf(var->value, "%30d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
5922  ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
5924  }
5925  } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
5926  if ((sscanf(var->value, "%30d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
5927  ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
5929  } else {
5931  }
5932  } else if (!strcasecmp(var->name, "atxferloopdelay")) {
5933  if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
5934  ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
5936  } else {
5937  atxferloopdelay *= 1000;
5938  }
5939  } else if (!strcasecmp(var->name, "atxferdropcall")) {
5940  atxferdropcall = ast_true(var->value);
5941  } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
5942  if ((sscanf(var->value, "%30u", &atxfercallbackretries) != 1)) {
5943  ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
5945  }
5946  } else if (!strcasecmp(var->name, "courtesytone")) {
5948  } else if (!strcasecmp(var->name, "parkedplay")) {
5949  if (!strcasecmp(var->value, "both")) {
5950  parkedplay = 2;
5951  } else if (!strcasecmp(var->value, "parked")) {
5952  parkedplay = 1;
5953  } else {
5954  parkedplay = 0;
5955  }
5956  } else if (!strcasecmp(var->name, "xfersound")) {
5957  ast_copy_string(xfersound, var->value, sizeof(xfersound));
5958  } else if (!strcasecmp(var->name, "xferfailsound")) {
5960  } else if (!strcasecmp(var->name, "pickupexten")) {
5961  ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
5962  } else if (!strcasecmp(var->name, "pickupsound")) {
5963  ast_copy_string(pickupsound, var->value, sizeof(pickupsound));
5964  } else if (!strcasecmp(var->name, "pickupfailsound")) {
5966  } else if (!strcasecmp(var->name, "comebacktoorigin")) {
5968  }
5969  }
5970 
5971  unmap_features();
5972  for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
5973  if (remap_feature(var->name, var->value)) {
5974  ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
5975  }
5976  }
5977 
5978  /* Map a key combination to an application */
5980  for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
5982  }
5983 
5986 
5987  ctg = NULL;
5988  while ((ctg = ast_category_browse(cfg, ctg))) {
5989  /* Is this a parkinglot definition ? */
5990  if (!strncasecmp(ctg, "parkinglot_", strlen("parkinglot_"))) {
5991  ast_debug(2, "Found configuration section %s, assume parking context\n", ctg);
5992  if (!build_parkinglot(ctg, ast_variable_browse(cfg, ctg))) {
5993  ast_log(LOG_ERROR, "Could not build parking lot %s. Configuration error.\n", ctg);
5994  } else {
5995  ast_debug(1, "Configured parking context %s\n", ctg);
5996  }
5997  continue;
5998  }
5999 
6000  /* No, check if it's a group */
6001  for (i = 0; i < ARRAY_LEN(categories); i++) {
6002  if (!strcasecmp(categories[i], ctg)) {
6003  break;
6004  }
6005  }
6006  if (i < ARRAY_LEN(categories)) {
6007  continue;
6008  }
6009 
6010  if (!(fg = register_group(ctg))) {
6011  continue;
6012  }
6013 
6014  for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
6015  struct ast_call_feature *feature;
6016 
6018  if (!(feature = find_dynamic_feature(var->name)) &&
6019  !(feature = ast_find_call_feature(var->name))) {
6021  ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
6022  continue;
6023  }
6025 
6026  register_group_feature(fg, var->value, feature);
6027  }
6028  }
6029 
6031 
6032  return 0;
6033 }
static void process_applicationmap_line(struct ast_variable *var)
Definition: features.c:5768
static int transferdigittimeout
Definition: features.c:614
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_call_feature * find_dynamic_feature(const char *name)
find a call feature by name
Definition: features.c:3100
static void unmap_features(void)
Definition: features.c:3248
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static unsigned int atxferloopdelay
Definition: features.c:620
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
static char xferfailsound[256]
Definition: features.c:591
static int parkedplay
Definition: features.c:587
static int atxfernoanswertimeout
Definition: features.c:618
#define DEFAULT_ATXFER_DROP_CALL
Definition: features.c:388
static unsigned int atxferdropcall
Definition: features.c:619
static void ast_unregister_groups(void)
Remove all feature groups in the list.
Definition: features.c:3114
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
static void ast_unregister_features(void)
Remove all features in the list.
Definition: features.c:3088
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * value
Definition: config.h:79
static char pickup_ext[AST_MAX_EXTENSION]
Definition: features.c:421
static struct feature_group * register_group(const char *fgname)
Add new feature group.
Definition: features.c:3015
static char pickupsound[256]
Definition: features.c:592
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
static int parkeddynamic
Definition: features.c:588
const char * name
Definition: config.h:77
#define DEFAULT_ATXFER_CALLBACK_RETRIES
Definition: features.c:390
#define LOG_ERROR
Definition: logger.h:155
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
static unsigned int atxfercallbackretries
Definition: features.c:621
static int remap_feature(const char *name, const char *value)
Definition: features.c:3258
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
static char courtesytone[256]
Definition: features.c:589
static char xfersound[256]
Definition: features.c:590
static int featuredigittimeout
Definition: features.c:615
static int adsipark
Definition: features.c:612
#define DEFAULT_PARKINGLOT
Definition: features.h:37
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char pickupfailsound[256]
Definition: features.c:593
#define DEFAULT_FEATURE_DIGIT_TIMEOUT
Definition: features.c:386
#define DEFAULT_ATXFER_LOOP_DELAY
Definition: features.c:389
struct ast_variable * next
Definition: config.h:82
static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
Add feature to group.
Definition: features.c:3046
static struct ast_parkinglot * build_parkinglot(const char *pl_name, struct ast_variable *var)
Build parkinglot from configuration and chain it in if it doesn&#39;t already exist.
Definition: features.c:5689
#define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER
Definition: features.c:387
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT
Definition: features.c:385
struct ast_call_feature * ast_find_call_feature(const char *name)
look for a call feature entry by its sname
Definition: features.c:3160
static int comebacktoorigin
Definition: features.c:616
static const char* real_ctx ( struct ast_channel transferer,
struct ast_channel transferee 
)
static

Find the context for the transfer.

Parameters
transferer
transfereeGrab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
Returns
a context string

Definition at line 2321 of file features.c.

References ast_strlen_zero(), ast_channel::context, ast_channel::macrocontext, and pbx_builtin_getvar_helper().

Referenced by builtin_atxfer(), and builtin_blindtransfer().

2322 {
2323  const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
2324  if (ast_strlen_zero(s)) {
2325  s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
2326  }
2327  if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
2328  s = transferer->macrocontext;
2329  }
2330  if (ast_strlen_zero(s)) {
2331  s = transferer->context;
2332  }
2333  return s;
2334 }
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
static struct feature_group* register_group ( const char *  fgname)
static

Add new feature group.

Parameters
fgnamefeature group name.

Add new feature group to the feature group list insert at head of list.

Note
This function MUST be called while feature_groups is locked.

Definition at line 3015 of file features.c.

References ast_calloc_with_stringfields, AST_LIST_INSERT_HEAD, ast_log(), ast_string_field_set, ast_verb, feature_group::gname, and LOG_NOTICE.

Referenced by process_config().

3016 {
3017  struct feature_group *fg;
3018 
3019  if (!fgname) {
3020  ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
3021  return NULL;
3022  }
3023 
3024  if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
3025  return NULL;
3026  }
3027 
3028  ast_string_field_set(fg, gname, fgname);
3029 
3031 
3032  ast_verb(2, "Registered group '%s'\n", fg->gname);
3033 
3034  return fg;
3035 }
const ast_string_field gname
Definition: features.c:407
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:275
#define ast_verb(level,...)
Definition: logger.h:243
struct feature_group::@265 entry
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_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static void register_group_feature ( struct feature_group fg,
const char *  exten,
struct ast_call_feature feature 
)
static

Add feature to group.

Parameters
fgfeature group
exten
featurefeature to add.

Check fg and feature specified, add feature to list

Note
This function MUST be called while feature_groups is locked.

Definition at line 3046 of file features.c.

References ast_calloc_with_stringfields, AST_LIST_INSERT_HEAD, ast_log(), ast_string_field_set, ast_verb, ast_call_feature::exten, feature_group_exten::exten, feature_group_exten::feature, feature_group::features, feature_group::gname, LOG_NOTICE, S_OR, and ast_call_feature::sname.

Referenced by process_config().

3047 {
3048  struct feature_group_exten *fge;
3049 
3050  if (!fg) {
3051  ast_log(LOG_NOTICE, "You didn't pass a group!\n");
3052  return;
3053  }
3054 
3055  if (!feature) {
3056  ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
3057  return;
3058  }
3059 
3060  if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
3061  return;
3062  }
3063 
3064  ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
3065 
3066  fge->feature = feature;
3067 
3068  AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
3069 
3070  ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
3071  feature->sname, fg->gname, fge->exten);
3072 }
char exten[FEATURE_MAX_LEN]
Definition: features.h:69
const ast_string_field gname
Definition: features.c:407
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
struct feature_group::@266 features
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:275
#define ast_verb(level,...)
Definition: logger.h:243
struct ast_call_feature * feature
Definition: features.c:400
const ast_string_field exten
Definition: features.c:399
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_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
char sname[FEATURE_SNAME_LEN]
Definition: features.h:68
struct feature_group_exten::@264 entry
#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
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static int remap_feature ( const char *  name,
const char *  value 
)
static

Definition at line 3258 of file features.c.

References ast_copy_string(), ast_rwlock_unlock, ast_rwlock_wrlock, FEATURES_COUNT, and features_lock.

Referenced by process_config().

3259 {
3260  int x, res = -1;
3261 
3263  for (x = 0; x < FEATURES_COUNT; x++) {
3264  if (strcasecmp(builtin_features[x].sname, name))
3265  continue;
3266 
3268  res = 0;
3269  break;
3270  }
3272 
3273  return res;
3274 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
static ast_rwlock_t features_lock
Definition: features.c:2979
int value
Definition: syslog.c:39
#define ast_rwlock_unlock(a)
Definition: lock.h:200
#define FEATURES_COUNT
Definition: features.c:2977
static const char name[]
static struct ast_call_feature builtin_features[]
Definition: features.c:2981
#define ast_rwlock_wrlock(a)
Definition: lock.h:202
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static void remove_dead_context_usage ( const char *  context,
struct parking_dp_context old_ctx,
struct parking_dp_context new_ctx 
)
static

Definition at line 6594 of file features.c.

References parking_dp_context::access_extens, destroy_space(), parking_dp_context::hints, remove_dead_ramp_usage(), remove_dead_spaces_usage(), and parking_dp_context::spaces.

Referenced by remove_dead_dialplan_useage().

6595 {
6598 #if 0
6599  /* I don't think we should destroy hints if the parking space still exists. */
6600  remove_dead_spaces_usage(context, &old_ctx->hints, &new_ctx->hints, destroy_space_hint);
6601 #endif
6602 }
static void remove_dead_ramp_usage(const char *context, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
Definition: features.c:6453
struct parking_dp_space_map hints
Definition: features.c:458
struct parking_dp_ramp_map access_extens
Definition: features.c:454
static void remove_dead_spaces_usage(const char *context, struct parking_dp_space_map *old_spaces, struct parking_dp_space_map *new_spaces, void(*destroy_space)(const char *context, int space))
Definition: features.c:6523
static void destroy_space(const char *context, int space)
Definition: features.c:6498
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
struct parking_dp_space_map spaces
Definition: features.c:456
static void remove_dead_dialplan_useage ( struct parking_dp_map old_map,
struct parking_dp_map new_map 
)
static

Definition at line 6617 of file features.c.

References ast_context_destroy(), ast_context_find(), AST_LIST_FIRST, AST_LIST_NEXT, parking_dp_context::context, registrar, and remove_dead_context_usage().

Referenced by load_config().

6618 {
6619  struct parking_dp_context *old_ctx;
6620  struct parking_dp_context *new_ctx;
6621  struct ast_context *con;
6622  int cmp;
6623 
6624  old_ctx = AST_LIST_FIRST(old_map);
6625  new_ctx = AST_LIST_FIRST(new_map);
6626 
6627  while (new_ctx) {
6628  if (!old_ctx) {
6629  /* No old contexts left, so no dead stuff can remain. */
6630  return;
6631  }
6632  cmp = strcmp(old_ctx->context, new_ctx->context);
6633  if (cmp < 0) {
6634  /* New map does not have old map context. */
6635  con = ast_context_find(old_ctx->context);
6636  if (con) {
6638  }
6639  old_ctx = AST_LIST_NEXT(old_ctx, node);
6640  continue;
6641  }
6642  if (cmp == 0) {
6643  /* Old and new map have this context. */
6644  remove_dead_context_usage(old_ctx->context, old_ctx, new_ctx);
6645  old_ctx = AST_LIST_NEXT(old_ctx, node);
6646  } else {
6647  /* Old map does not have new map context. */
6648  }
6649  new_ctx = AST_LIST_NEXT(new_ctx, node);
6650  }
6651 
6652  /* Any old contexts left must be dead. */
6653  for (; old_ctx; old_ctx = AST_LIST_NEXT(old_ctx, node)) {
6654  con = ast_context_find(old_ctx->context);
6655  if (con) {
6657  }
6658  }
6659 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
static void remove_dead_context_usage(const char *context, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
Definition: features.c:6594
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
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
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
static void remove_dead_ramp_usage ( const char *  context,
struct parking_dp_ramp_map old_ramps,
struct parking_dp_ramp_map new_ramps 
)
static

Definition at line 6453 of file features.c.

References AST_LIST_FIRST, AST_LIST_NEXT, parking_dp_ramp::exten, and remove_exten_if_exist().

Referenced by remove_dead_context_usage().

6454 {
6455  struct parking_dp_ramp *old_ramp;
6456  struct parking_dp_ramp *new_ramp;
6457  int cmp;
6458 
6459  old_ramp = AST_LIST_FIRST(old_ramps);
6460  new_ramp = AST_LIST_FIRST(new_ramps);
6461 
6462  while (new_ramp) {
6463  if (!old_ramp) {
6464  /* No old ramps left, so no dead ramps can remain. */
6465  return;
6466  }
6467  cmp = strcmp(old_ramp->exten, new_ramp->exten);
6468  if (cmp < 0) {
6469  /* New map does not have old ramp. */
6470  remove_exten_if_exist(context, old_ramp->exten, 1);
6471  old_ramp = AST_LIST_NEXT(old_ramp, node);
6472  continue;
6473  }
6474  if (cmp == 0) {
6475  /* Old and new map have this ramp. */
6476  old_ramp = AST_LIST_NEXT(old_ramp, node);
6477  } else {
6478  /* Old map does not have new ramp. */
6479  }
6480  new_ramp = AST_LIST_NEXT(new_ramp, node);
6481  }
6482 
6483  /* Any old ramps left must be dead. */
6484  for (; old_ramp; old_ramp = AST_LIST_NEXT(old_ramp, node)) {
6485  remove_exten_if_exist(context, old_ramp->exten, 1);
6486  }
6487 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
struct parking_dp_ramp::@267 node
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
static void remove_exten_if_exist(const char *context, const char *exten, int priority)
Definition: features.c:6427
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
char exten[1]
Definition: features.c:430
static void remove_dead_spaces_usage ( const char *  context,
struct parking_dp_space_map old_spaces,
struct parking_dp_space_map new_spaces,
void(*)(const char *context, int space)  destroy_space 
)
static

< Current position in the current old range.

Definition at line 6523 of file features.c.

References AST_LIST_FIRST, AST_LIST_NEXT, destroy_space(), parking_dp_spaces::start, parking_dp_spaces::stop, and stop.

Referenced by remove_dead_context_usage().

6526 {
6527  struct parking_dp_spaces *old_range;
6528  struct parking_dp_spaces *new_range;
6529  int space;/*!< Current position in the current old range. */
6530  int stop;
6531 
6532  old_range = AST_LIST_FIRST(old_spaces);
6533  new_range = AST_LIST_FIRST(new_spaces);
6534  space = -1;
6535 
6536  while (old_range) {
6537  if (space < old_range->start) {
6538  space = old_range->start;
6539  }
6540  if (new_range) {
6541  if (space < new_range->start) {
6542  /* Current position in old range starts before new range. */
6543  if (old_range->stop < new_range->start) {
6544  /* Old range ends before new range. */
6545  stop = old_range->stop;
6546  old_range = AST_LIST_NEXT(old_range, node);
6547  } else {
6548  /* Tail of old range overlaps new range. */
6549  stop = new_range->start - 1;
6550  }
6551  } else if (/* new_range->start <= space && */ space <= new_range->stop) {
6552  /* Current position in old range overlaps new range. */
6553  if (old_range->stop <= new_range->stop) {
6554  /* Old range ends at or before new range. */
6555  old_range = AST_LIST_NEXT(old_range, node);
6556  } else {
6557  /* Old range extends beyond end of new range. */
6558  space = new_range->stop + 1;
6559  new_range = AST_LIST_NEXT(new_range, node);
6560  }
6561  continue;
6562  } else /* if (new_range->stop < space) */ {
6563  /* Current position in old range starts after new range. */
6564  new_range = AST_LIST_NEXT(new_range, node);
6565  continue;
6566  }
6567  } else {
6568  /* No more new ranges. All remaining old spaces are dead. */
6569  stop = old_range->stop;
6570  old_range = AST_LIST_NEXT(old_range, node);
6571  }
6572 
6573  /* Destroy dead parking spaces. */
6574  for (; space <= stop; ++space) {
6575  destroy_space(context, space);
6576  }
6577  }
6578 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
unsigned int stop
Definition: app_meetme.c:969
static void destroy_space(const char *context, int space)
Definition: features.c:6498
struct parking_dp_spaces::@268 node
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void remove_exten_if_exist ( const char *  context,
const char *  exten,
int  priority 
)
static

Definition at line 6427 of file features.c.

References ast_context_remove_extension(), ast_debug, E_MATCH, pbx_find_extension(), registrar, and pbx_find_info::stacklen.

Referenced by destroy_space(), and remove_dead_ramp_usage().

6428 {
6429  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
6430 
6431  if (pbx_find_extension(NULL, NULL, &q, context, exten, priority, NULL, NULL,
6432  E_MATCH)) {
6433  ast_debug(1, "Removing unneeded parking lot exten: %s@%s priority:%d\n",
6434  context, exten, priority);
6436  }
6437 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:6114
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int stacklen
Definition: extconf.h:234
static char * registrar
Definition: features.c:623
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: pbx.c:3013
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void set_bridge_features_on_config ( struct ast_bridge_config config,
const char *  features 
)
static

Definition at line 3865 of file features.c.

References AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, ast_log(), ast_set_flag, ast_strlen_zero(), feature_group_exten::feature, ast_bridge_config::features_caller, and LOG_WARNING.

Referenced by ast_bridge_call().

3866 {
3867  const char *feature;
3868 
3869  if (ast_strlen_zero(features)) {
3870  return;
3871  }
3872 
3873  for (feature = features; *feature; feature++) {
3874  switch (*feature) {
3875  case 'T' :
3876  case 't' :
3878  break;
3879  case 'K' :
3880  case 'k' :
3882  break;
3883  case 'H' :
3884  case 'h' :
3886  break;
3887  case 'W' :
3888  case 'w' :
3890  break;
3891  default :
3892  ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
3893  }
3894  }
3895 }
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct ast_flags features_caller
Definition: channel.h:975
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
static void set_c_e_p ( struct ast_channel chan,
const char *  context,
const char *  ext,
int  pri 
)
static

store context, extension and priority

Parameters
chan,context,ext,pri

Definition at line 881 of file features.c.

References ast_copy_string(), ast_channel::context, ast_channel::exten, and ast_channel::priority.

Referenced by builtin_blindtransfer(), manage_parked_call(), and masq_park_call().

882 {
883  ast_copy_string(chan->context, context, sizeof(chan->context));
884  ast_copy_string(chan->exten, ext, sizeof(chan->exten));
885  chan->priority = pri;
886 }
int priority
Definition: channel.h:841
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
const char * ext
Definition: http.c:112
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static int set_chan_app_data ( struct ast_channel chan,
const char *  src_app_data 
)
static

Definition at line 957 of file features.c.

References ast_channel_datastore_add(), ast_datastore_alloc(), ast_datastore_free(), ast_malloc, channel_app_data_datastore, ast_datastore::data, and ast_channel::data.

Referenced by bridge_call_thread().

958 {
959  struct ast_datastore *datastore;
960  char *dst_app_data;
961 
963  if (!datastore) {
964  return -1;
965  }
966 
967  dst_app_data = ast_malloc(strlen(src_app_data) + 1);
968  if (!dst_app_data) {
969  ast_datastore_free(datastore);
970  return -1;
971  }
972 
973  chan->data = strcpy(dst_app_data, src_app_data);
974  datastore->data = dst_app_data;
975  ast_channel_datastore_add(chan, datastore);
976  return 0;
977 }
Structure for a data store object.
Definition: datastore.h:54
const char * data
Definition: channel.h:755
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
static struct ast_datastore_info channel_app_data_datastore
Definition: features.c:952
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
void * data
Definition: datastore.h:56
#define ast_malloc(a)
Definition: astmm.h:91
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static void set_config_flags ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config 
)
static

Definition at line 3449 of file features.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, ast_clear_flag, AST_FEATURE_FLAG_BYCALLEE, AST_FEATURE_FLAG_BYCALLER, AST_FEATURE_FLAG_NEEDSDTMF, AST_FLAGS_ALL, AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_rwlock_rdlock, ast_rwlock_unlock, ast_set_flag, ast_strdupa, ast_test_flag, feature_group_exten::feature, ast_call_feature::feature_mask, feature_group::features, ast_bridge_config::features_callee, ast_bridge_config::features_caller, FEATURES_COUNT, features_lock, find_dynamic_feature(), pbx_builtin_getvar_helper(), and strsep().

Referenced by ast_bridge_call().

3450 {
3451  int x;
3452 
3453  ast_clear_flag(config, AST_FLAGS_ALL);
3454 
3456  for (x = 0; x < FEATURES_COUNT; x++) {
3458  continue;
3459 
3462 
3465  }
3467 
3468  if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
3469  const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
3470 
3471  if (dynamic_features) {
3472  char *tmp = ast_strdupa(dynamic_features);
3473  char *tok;
3474  struct ast_call_feature *feature;
3475 
3476  /* while we have a feature */
3477  while ((tok = strsep(&tmp, "#"))) {
3478  struct feature_group *fg;
3479 
3482  struct feature_group_exten *fge;
3483 
3484  AST_LIST_TRAVERSE(&fg->features, fge, entry) {
3487  }
3490  }
3491  }
3492  }
3494 
3496  if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
3497  if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
3499  }
3500  if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE)) {
3502  }
3503  }
3505  }
3506  }
3507  }
3508 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
static ast_rwlock_t features_lock
Definition: features.c:2979
static struct ast_call_feature * find_dynamic_feature(const char *name)
find a call feature by name
Definition: features.c:3100
char * strsep(char **str, const char *delims)
struct ast_flags features_callee
Definition: channel.h:976
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct feature_group::@266 features
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_rwlock_unlock(a)
Definition: lock.h:200
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
#define FEATURES_COUNT
Definition: features.c:2977
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
struct feature_group::@265 entry
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define AST_BRIDGE_DTMF_CHANNEL_1
Report DTMF on channel 1.
Definition: channel.h:1934
struct ast_call_feature * feature
Definition: features.c:400
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
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_FLAGS_ALL
Definition: utils.h:196
static struct ast_call_feature builtin_features[]
Definition: features.c:2981
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct feature_group_exten::@264 entry
#define AST_BRIDGE_DTMF_CHANNEL_0
Report DTMF on channel 0.
Definition: channel.h:1932
static void set_peers ( struct ast_channel **  caller,
struct ast_channel **  callee,
struct ast_channel peer,
struct ast_channel chan,
int  sense 
)
static

set caller and callee according to the direction

Parameters
caller,callee,peer,chan,senseDetect who triggered feature and set callee/caller variables accordingly

Definition at line 1951 of file features.c.

References FEATURE_SENSE_PEER.

Referenced by builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), and builtin_parkcall().

1953 {
1954  if (sense == FEATURE_SENSE_PEER) {
1955  *caller = peer;
1956  *callee = chan;
1957  } else {
1958  *callee = peer;
1959  *caller = chan;
1960  }
1961 }
#define FEATURE_SENSE_PEER
Definition: features.h:50
static void unmap_features ( void  )
static

Definition at line 3248 of file features.c.

References ast_rwlock_unlock, ast_rwlock_wrlock, FEATURES_COUNT, and features_lock.

Referenced by process_config().

3249 {
3250  int x;
3251 
3253  for (x = 0; x < FEATURES_COUNT; x++)
3254  strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
3256 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
static ast_rwlock_t features_lock
Definition: features.c:2979
#define ast_rwlock_unlock(a)
Definition: lock.h:200
#define FEATURES_COUNT
Definition: features.c:2977
static struct ast_call_feature builtin_features[]
Definition: features.c:2981
#define ast_rwlock_wrlock(a)
Definition: lock.h:202
static int usage_context_add_ramp ( struct parking_dp_ramp_map ramp_map,
const char *  exten,
int  exclusive,
struct ast_parkinglot lot,
int  complain 
)
static

Definition at line 6113 of file features.c.

References AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), build_dialplan_useage_ramp(), ast_parkinglot::cfg, parking_dp_ramp::exclusive, parking_dp_ramp::exten, LOG_WARNING, ast_parkinglot::name, and parkinglot_cfg::parking_con.

Referenced by dialplan_usage_add_parkinglot_data().

6114 {
6115  struct parking_dp_ramp *cur_ramp;
6116  struct parking_dp_ramp *new_ramp;
6117  int cmp;
6118 
6119  /* Make sure that exclusive is only 0 or 1 */
6120  if (exclusive) {
6121  exclusive = 1;
6122  }
6123 
6124  AST_LIST_TRAVERSE_SAFE_BEGIN(ramp_map, cur_ramp, node) {
6125  cmp = strcmp(exten, cur_ramp->exten);
6126  if (cmp > 0) {
6127  /* The parking lot ramp goes after this node. */
6128  continue;
6129  }
6130  if (cmp == 0) {
6131  /* The ramp is already in the map. */
6132  if (complain && (cur_ramp->exclusive || exclusive)) {
6134  "Parking lot '%s' parkext %s@%s used by another parking lot.\n",
6135  lot->name, exten, lot->cfg.parking_con);
6136  }
6137  return 0;
6138  }
6139  /* The new parking lot ramp goes before this node. */
6141  if (!new_ramp) {
6142  return -1;
6143  }
6145  return 0;
6146  }
6148 
6149  /* New parking lot access ramp goes on the end. */
6151  if (!new_ramp) {
6152  return -1;
6153  }
6154  AST_LIST_INSERT_TAIL(ramp_map, new_ramp, node);
6155  return 0;
6156 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
#define LOG_WARNING
Definition: logger.h:144
struct parking_dp_ramp::@267 node
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
static struct parking_dp_ramp * build_dialplan_useage_ramp(const char *exten, int exclusive)
Definition: features.c:6087
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
struct parkinglot_cfg cfg
Definition: features.c:560
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
char name[AST_MAX_CONTEXT]
Definition: features.c:558
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
unsigned int exclusive
Definition: features.c:428
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:584
char exten[1]
Definition: features.c:430
static int usage_context_add_spaces ( struct parking_dp_space_map space_map,
int  start,
int  stop,
struct ast_parkinglot lot,
int  complain 
)
static

Definition at line 6194 of file features.c.

References ast_free, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), build_dialplan_useage_spaces(), ast_parkinglot::cfg, LOG_WARNING, ast_parkinglot::name, parkinglot_cfg::parking_con, parking_dp_spaces::start, parking_dp_spaces::stop, and stop.

Referenced by dialplan_usage_add_parkinglot_data().

6195 {
6196  struct parking_dp_spaces *cur_node;
6197  struct parking_dp_spaces *expand_node;
6198  struct parking_dp_spaces *new_node;
6199 
6200  expand_node = NULL;
6201  AST_LIST_TRAVERSE_SAFE_BEGIN(space_map, cur_node, node) {
6202  /* NOTE: stop + 1 to combine immediately adjacent nodes into one. */
6203  if (expand_node) {
6204  /* The previous node is expanding to possibly eat following nodes. */
6205  if (expand_node->stop + 1 < cur_node->start) {
6206  /* Current node is completely after expanding node. */
6207  return 0;
6208  }
6209 
6210  if (complain
6211  && ((cur_node->start <= start && start <= cur_node->stop)
6212  || (cur_node->start <= stop && stop <= cur_node->stop)
6213  || (start < cur_node->start && cur_node->stop < stop))) {
6214  /* Only complain once per range add. */
6215  complain = 0;
6217  "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
6218  lot->name, start, stop, lot->cfg.parking_con);
6219  }
6220 
6221  /* Current node is eaten by the expanding node. */
6222  if (expand_node->stop < cur_node->stop) {
6223  expand_node->stop = cur_node->stop;
6224  }
6226  ast_free(cur_node);
6227  continue;
6228  }
6229 
6230  if (cur_node->stop + 1 < start) {
6231  /* New range is completely after current node. */
6232  continue;
6233  }
6234  if (stop + 1 < cur_node->start) {
6235  /* New range is completely before current node. */
6236  new_node = build_dialplan_useage_spaces(start, stop);
6237  if (!new_node) {
6238  return -1;
6239  }
6241  return 0;
6242  }
6243 
6244  if (complain
6245  && ((cur_node->start <= start && start <= cur_node->stop)
6246  || (cur_node->start <= stop && stop <= cur_node->stop)
6247  || (start < cur_node->start && cur_node->stop < stop))) {
6248  /* Only complain once per range add. */
6249  complain = 0;
6251  "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
6252  lot->name, start, stop, lot->cfg.parking_con);
6253  }
6254 
6255  /* Current node range overlaps or is immediately adjacent to new range. */
6256  if (start < cur_node->start) {
6257  /* Expand the current node in the front. */
6258  cur_node->start = start;
6259  }
6260  if (stop <= cur_node->stop) {
6261  /* Current node is not expanding in the rear. */
6262  return 0;
6263  }
6264  cur_node->stop = stop;
6265  expand_node = cur_node;
6266  }
6268 
6269  if (expand_node) {
6270  /*
6271  * The previous node expanded and either ate all following nodes
6272  * or it was the last node.
6273  */
6274  return 0;
6275  }
6276 
6277  /* New range goes on the end. */
6278  new_node = build_dialplan_useage_spaces(start, stop);
6279  if (!new_node) {
6280  return -1;
6281  }
6282  AST_LIST_INSERT_TAIL(space_map, new_node, node);
6283  return 0;
6284 }
static struct parking_dp_spaces * build_dialplan_useage_spaces(int start, int stop)
Definition: features.c:6168
#define LOG_WARNING
Definition: logger.h:144
unsigned int stop
Definition: app_meetme.c:969
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
struct parkinglot_cfg cfg
Definition: features.c:560
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_free(a)
Definition: astmm.h:97
struct parking_dp_spaces::@268 node
char name[AST_MAX_CONTEXT]
Definition: features.c:558
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:584
static int xfer_park_call_helper ( struct ast_channel park_me,
struct ast_channel parker,
struct ast_exten park_exten 
)
static

Definition at line 1891 of file features.c.

References AST_FEATURE_RETURN_SUCCESS, ast_get_extension_app_data(), AST_PARK_OPT_SILENCE, AST_STANDARD_APP_ARGS, ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, create_dynamic_parkinglot(), default_parkinglot, find_parkinglot(), findparkinglotname(), finishup(), masq_park_call(), parkeddynamic, ast_park_call_args::parkinglot, parkinglot_addref(), parkinglot_unref(), parse(), and park_app_args::pl_name.

Referenced by builtin_atxfer(), and builtin_blindtransfer().

1892 {
1893  char *parse;
1894  const char *app_data;
1895  const char *pl_name;
1896  struct ast_park_call_args args = { 0, };
1897  struct park_app_args app_args;
1898  int res;
1899 
1900  app_data = ast_get_extension_app_data(park_exten);
1901  if (!app_data) {
1902  app_data = "";
1903  }
1904  parse = ast_strdupa(app_data);
1905  AST_STANDARD_APP_ARGS(app_args, parse);
1906 
1907  /* Find the parking lot */
1908  if (!ast_strlen_zero(app_args.pl_name)) {
1909  pl_name = app_args.pl_name;
1910  } else {
1911  pl_name = findparkinglotname(parker);
1912  }
1913  if (ast_strlen_zero(pl_name)) {
1914  /* Parking lot is not specified, so use the default parking lot. */
1916  } else {
1917  args.parkinglot = find_parkinglot(pl_name);
1918  if (!args.parkinglot && parkeddynamic) {
1919  args.parkinglot = create_dynamic_parkinglot(pl_name, park_me);
1920  }
1921  }
1922 
1923  if (args.parkinglot) {
1924  /* Park the call */
1925  res = finishup(park_me);
1926  if (res) {
1927  /* park_me hungup on us. */
1929  return -1;
1930  }
1931  res = masq_park_call(park_me, parker, &args);
1933  } else {
1934  /* Parking failed because parking lot does not exist. */
1935  if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
1936  ast_stream_and_wait(parker, "pbx-parkingfailed", "");
1937  }
1938  finishup(park_me);
1939  res = -1;
1940  }
1941 
1942  return res ? AST_FEATURE_RETURN_SUCCESS : -1;
1943 }
static struct ast_parkinglot * parkinglot_addref(struct ast_parkinglot *parkinglot)
Definition: features.c:5435
#define ast_test_flag(p, flag)
Definition: utils.h:63
static struct ast_parkinglot * default_parkinglot
Default parking lot.
Definition: features.c:582
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:11146
static int finishup(struct ast_channel *chan)
Definition: features.c:1870
static const char * findparkinglotname(struct ast_channel *chan)
Find parking lot name from channel.
Definition: features.c:1082
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
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
#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
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
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_FEATURE_RETURN_SUCCESS
Definition: features.h:45
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604

Variable Documentation

int adsipark
static

Definition at line 612 of file features.c.

Referenced by park_call_full(), and process_config().

char* app_bridge = "Bridge"
static

Definition at line 7493 of file features.c.

unsigned int atxfercallbackretries
static

Definition at line 621 of file features.c.

Referenced by builtin_atxfer(), and process_config().

unsigned int atxferdropcall
static

Definition at line 619 of file features.c.

Referenced by builtin_atxfer(), and process_config().

unsigned int atxferloopdelay
static

Definition at line 620 of file features.c.

Referenced by builtin_atxfer(), and process_config().

int atxfernoanswertimeout
static

Definition at line 618 of file features.c.

Referenced by builtin_atxfer(), and process_config().

struct ast_app_option bridge_exec_options[128] = { [ 'p' ] = { .flag = BRIDGE_OPT_PLAYTONE }, [ 'h' ] = { .flag = OPT_CALLEE_HANGUP }, [ 'H' ] = { .flag = OPT_CALLER_HANGUP }, [ 'k' ] = { .flag = OPT_CALLEE_PARK }, [ 'K' ] = { .flag = OPT_CALLER_PARK }, [ 'L' ] = { .flag = OPT_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, [ 'S' ] = { .flag = OPT_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 't' ] = { .flag = OPT_CALLEE_TRANSFER }, [ 'T' ] = { .flag = OPT_CALLER_TRANSFER }, [ 'w' ] = { .flag = OPT_CALLEE_MONITOR }, [ 'W' ] = { .flag = OPT_CALLER_MONITOR }, [ 'x' ] = { .flag = OPT_CALLEE_KILL }, }
static

Definition at line 7530 of file features.c.

Referenced by bridge_exec().

struct ast_call_feature builtin_features[]
static

Definition at line 2981 of file features.c.

struct ast_datastore_info channel_app_data_datastore
static
Initial value:
= {
.type = "Channel appdata datastore",
.destroy = ast_free_ptr,
}
void ast_free_ptr(void *ptr)

Definition at line 952 of file features.c.

Referenced by set_chan_app_data().

struct ast_cli_entry cli_features[]
static
Initial value:
= {
AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
AST_CLI_DEFINE(handle_features_reload, "Reloads configured features"),
AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls"),
}
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
static char * handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to list configured features.
Definition: features.c:6799
static char * handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: features.c:6905
static char * handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to list parked calls.
Definition: features.c:7109

Definition at line 7165 of file features.c.

int comebacktoorigin = 1
static

Definition at line 616 of file features.c.

Referenced by manage_parked_call(), and process_config().

char courtesytone[256]
static

Courtesy tone used to pickup parked calls and on-touch-record

Definition at line 589 of file features.c.

Referenced by builtin_automixmonitor(), builtin_automonitor(), parked_call_exec(), and process_config().

struct ast_parkinglot* default_parkinglot
static

Default parking lot.

Note
Holds a parkinglot reference.
Will not be NULL while running.

Definition at line 582 of file features.c.

Referenced by create_dynamic_parkinglot(), handle_parkedcalls(), load_config(), park_call_exec(), park_space_reserve(), parked_call_exec(), and xfer_park_call_helper().

struct ast_datastore_info dial_features_info
static
Initial value:
= {
.type = "dial-features",
}
static void * dial_features_duplicate(void *data)
Definition: features.c:731
static void dial_features_destroy(void *data)
Definition: features.c:744

Definition at line 752 of file features.c.

Referenced by add_features_datastore(), builtin_atxfer(), manage_parked_call(), and parked_call_exec().

struct feature_groups feature_groups = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
static
struct feature_list feature_list = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
static
int featuredigittimeout
static

Definition at line 615 of file features.c.

Referenced by ast_bridge_call(), and process_config().

ast_mutex_t features_reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static

Ensure that features.conf reloads on one thread at a time.

Definition at line 610 of file features.c.

Referenced by ast_features_reload().

int force_reload_load
static

Force a config reload to reload regardless of config file timestamp.

Definition at line 585 of file features.c.

Referenced by build_parkinglot(), load_config(), parkinglot_activate_cb(), and parkinglot_is_marked_cb().

struct ast_app* mixmonitor_app = NULL
static

Definition at line 642 of file features.c.

Referenced by builtin_automixmonitor().

int mixmonitor_ok = 1
static

Definition at line 643 of file features.c.

Referenced by builtin_automixmonitor().

struct ast_app* monitor_app = NULL
static

Definition at line 639 of file features.c.

Referenced by ast_bridge_call(), and builtin_automonitor().

int monitor_ok = 1
static

Definition at line 640 of file features.c.

Referenced by ast_bridge_call(), and builtin_automonitor().

struct ast_app_option park_call_options[128] = { [ 'r' ] = { .flag = AST_PARK_OPT_RINGING }, [ 'R' ] = { .flag = AST_PARK_OPT_RANDOMIZE }, [ 's' ] = { .flag = AST_PARK_OPT_SILENCE }, }
static

Definition at line 5060 of file features.c.

Referenced by park_call_exec().

const char* parkcall = "Park"
static
const char* parkedcall = "ParkedCall"
static

Definition at line 419 of file features.c.

int parkeddynamic = 0
static

Enable creation of parkinglots dynamically

Definition at line 588 of file features.c.

Referenced by ast_masq_park_call_exten(), ast_park_call_exten(), park_call_exec(), park_space_reserve(), process_config(), and xfer_park_call_helper().

int parkedplay = 0
static

Who to play courtesytone to when someone picks up a parked call.

Definition at line 587 of file features.c.

Referenced by parked_call_exec(), and process_config().

char parking_con_dial[] = "park-dial"
static

Context for parking dialback to parker.

Note
The need for the context is a KLUDGE.
Todo:
Might be able to eliminate the parking_con_dial context kludge by running app_dial directly in its own thread to simulate a PBX.

Definition at line 607 of file features.c.

Referenced by ast_features_reload(), and manage_parked_call().

pthread_t parking_thread
static

Definition at line 648 of file features.c.

Referenced by ast_features_init(), features_shutdown(), and park_call_full().

struct parkinglot_cfg parkinglot_cfg_default
static
Initial value:
= {
.parkingtime = DEFAULT_PARK_TIME,
}
#define DEFAULT_PARK_TIME
Definition: features.c:383
#define DEFAULT_PARK_EXTENSION
Definition: features.c:384

Default configuration for normal parking lots.

Definition at line 5508 of file features.c.

Referenced by build_parkinglot().

struct parkinglot_cfg parkinglot_cfg_default_default
static

Default configuration for default parking lot.

Definition at line 5498 of file features.c.

Referenced by build_parkinglot().

struct ao2_container* parkinglots
static
char parkingretalertinfo[256]
static

Distinctive ring if chantech = SIP (adds a SIP AlertInfo header)

Definition at line 597 of file features.c.

Referenced by manage_parked_call(), and parkinglot_config_read().

char parkingretcidname[256]
static

Callerid name of returned parked call

Definition at line 595 of file features.c.

Referenced by manage_parked_call(), and parkinglot_config_read().

char parkingretdahdiring[3]
static

Distinctive ring if chantech = DAHDI

Definition at line 596 of file features.c.

Referenced by manage_parked_call(), and parkinglot_config_read().

struct ast_datastore_info pickup_active
static
Initial value:
= {
.type = "pickup-active",
}

The presence of this datastore on the channel indicates that someone is attemting to pickup or has picked up the channel. The purpose is to prevent a race between two channels attempting to pickup the same channel.

Definition at line 7334 of file features.c.

char pickup_ext[AST_MAX_EXTENSION]
static

Call pickup extension

Definition at line 421 of file features.c.

Referenced by analog_canmatch_featurecode(), ast_pickup_ext(), and canmatch_featurecode().

char pickupfailsound[256]
static

Pickup failure sound

Definition at line 593 of file features.c.

Referenced by ast_pickup_call(), and process_config().

char pickupsound[256]
static

Pickup sound

Definition at line 592 of file features.c.

Referenced by ast_pickup_call(), and process_config().

struct ast_app* stopmixmonitor_app = NULL
static

Definition at line 645 of file features.c.

Referenced by builtin_automixmonitor().

int stopmixmonitor_ok = 1
static

Definition at line 646 of file features.c.

Referenced by builtin_automixmonitor().

int transferdigittimeout
static

Definition at line 614 of file features.c.

Referenced by builtin_atxfer(), builtin_blindtransfer(), and process_config().

char xferfailsound[256]
static

Call transfer failure sound

Definition at line 591 of file features.c.

Referenced by builtin_atxfer(), and process_config().

char xfersound[256]
static

Call transfer sound

Definition at line 590 of file features.c.

Referenced by action_bridge(), bridge_exec(), builtin_atxfer(), local_attended_transfer(), and process_config().